I am trying to create a simple draw program that saves a basic drawing upon button click. I copied the draw methods from my textbook, I am just toying around. This is the buffered image I have created:
private static BufferedImage bi = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
And this creates the paint panel:
public PaintPanel() {
addMouseMotionListener(
new MouseMotionAdapter() {
public void mouseDragged(MouseEvent event) {
if (pointCount < points.length) {
points[pointCount] = event.getPoint();
++pointCount;
repaint();
}
}
});
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < pointCount; i++)
g.fillOval(points[i].x, points[i].y, 4, 4);
}
On a button click:
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
PaintPanel.saveImage();
System.exit(0);
}
I call this method:
public static void saveImage() {
try {
ImageIO.write(bi, "png", new File("test.png"));
} catch (IOException ioe) {
System.out.println("Eek");
ioe.printStackTrace();
}
}
But the png file that I save is just black.
The BufferedImage and panel component have 2 distinct Graphics objects. Therefore it is necessary to explicitly update the Graphics object for the former:
Graphics graphics = bi.getGraphics();
for (int i = 0; i < pointCount; i++) {
graphics.fillOval(points[i].x, points[i].y, 4, 4);
}
Related
I am only posting the relevant code. I am fairly new to java and right now I am building a program that will allow the user to use a draw method. However, when I click the button for drawing in the interface, it automatically generates a random line anywhere on the page and does not allow user interaction. I think the error is occurring in my mouseListener method, but I am not sure as this is my first time doing anything like this. Any help would be greatly appreciated. Thank you!
Also, the error that prints out is: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
public class SimplePaint extends JFrame {
JButton drawing = new JButton();
Line2D draw = new Line2D.Float();
Point start = null;
Point end = null;
public SimplePaint() {
JPanel panel = new JPanel() {
{
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
start = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
start = e.getPoint();
//start = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
end = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
end = e.getPoint();
repaint();
}
});
}
};
drawing.setText("Draw");
panel.add(drawing);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == drawing) {
draw = new Line2D.Float(start.x, start.y, end.x, end.y);
}
repaint();
}
};
drawing.addActionListener(actionListener);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Float(0, 250, 2000, 300);
g2.draw(draw);
}
}
I'm trying to create a program that able the user to drag and drop the oval around in the space. I was able to drag and drop but after I tried do it again on the second run, the oval jump all over the places. I was wondering if anyone know why this happen? Am i missing something? Thank you
public class MoveOval extends JFrame {
private Ellipse2D node = new Ellipse2D.Float(200,200,80,120);
private Point offset;
private int preX,preY;
private Image dbImage;
private Graphics dbg;
Adapter ma = new Adapter();
public static void main(String args[]){
JFrame frame = new MoveOval();
frame.setSize(600,600);
frame.setVisible(true);
}
public MoveOval(){
super("Move Oval");
setDefaultCloseOperation(EXIT_ON_CLOSE);
addMouseListener(ma);
addMouseMotionListener(ma);
}
private class Adapter extends MouseAdapter{
public void mousePressed(MouseEvent e){
if(node.contains(e.getPoint())){
preX = node.getBounds().x-e.getX();
preY = node.getBounds().y-e.getX();
offset = new Point(preX, preY);
}
}
public void mouseDragged(MouseEvent e){
if(node.contains(e.getPoint())){
updateLocation(e);
}
}
public void mouseReleased(MouseEvent e) {
offset=null;
}
}
public void updateLocation(MouseEvent e){
Point to = e.getPoint();
to.x += offset.x;
to.y += offset.y;
Rectangle bounds = node.getBounds();
bounds.setLocation(to);
node.setFrame(bounds);
repaint();
}
public void paint(Graphics g){
dbImage=createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paintComponent(Graphics g){
Graphics2D gd = (Graphics2D)g.create();
gd.setColor(Color.blue);
gd.fill(node);
}
}
Actually a very simple mistake and easy to fix.
public void mousePressed(MouseEvent e){
if(node.contains(e.getPoint())){
preX = node.getBounds().x-e.getX();
preY = node.getBounds().y-e.getX(); // <- That's the bad guy.
offset = new Point(preX, preY);
}
}
It has to be -e.getY() not -e.getX().
In my code after i added code to paintComponent() when i run it, all the JLabel, textfields, and buttons disappear the textfields and buttons reappear when i click on them while the program is running but i still can't see any of the JLabels.
I hope it is something silly i have commented out the code in the paintComponent() method that seems to cause this error.
public class snowBoarding extends JFrame {
private JButton getReset() {
if (Reset == null) {
Reset = new JButton();
Reset.setBounds(new Rectangle(162, 411, 131, 39));
Reset.setFont(new Font("Dialog", Font.BOLD, 18));
Reset.setText("Reset");
Reset.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e){
textField_1.setText("0");
textField_2.setText("0");
textField_3.setText("0");
textField_4.setText("0");
textField_5.setText("0");
textField_6.setText("0");
textField_7.setText("0");
textField_8.setText("0");
textField_9.setText("0");
textField_10.setText("0");
textField_11.setText("0");
textField.setText("0");
total_1.setText("0");
total_2.setText("0");
Overall.setText("0");
DrawPanel.clear(DrawPanel.getGraphics());
DrawPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
}
});
}
return Reset;
}
public JButton getButton_calc_draw() {
if (Button_calc_draw == null) {
Button_calc_draw = new JButton();
Button_calc_draw.setBounds(303, 411, 131, 39);
Button_calc_draw.setFont(new Font ("Dialog", Font.BOLD, 18));
Button_calc_draw.setText("Draw");
Button_calc_draw.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
// Get values from the text fields
run_1[0] = Integer.parseInt(textField.getText());
run_1[1] = Integer.parseInt(textField_1.getText());
run_1[2] = Integer.parseInt(textField_2.getText());
run_1[3] = Integer.parseInt(textField_3.getText());
run_1[4] = Integer.parseInt(textField_4.getText());
run_1[5] = Integer.parseInt(textField_5.getText());
for (int i = 0; i < run_1.length; i++) {
temp[i] = run_1[i];
}
Arrays.sort(temp);
for (int i = 1; i < (temp.length -1) ; i++){
avg1+=temp[i];
}
avg1 = avg1/4;
run_2[0] = Integer.parseInt(textField_6.getText());
run_2[1] = Integer.parseInt(textField_7.getText());
run_2[2] = Integer.parseInt(textField_8.getText());
run_2[3] = Integer.parseInt(textField_9.getText());
run_2[4] = Integer.parseInt(textField_10.getText());
run_2[5] = Integer.parseInt(textField_11.getText());
for (int i = 0; i < run_2.length; i++) {
temp[i] = run_2[i];
}
Arrays.sort(temp);
for (int i = 1; i < (temp.length -1) ; i++){
avg2+=temp[i];
}
avg2 = avg2/4;
if (avg1 > avg2){
OverallScore = avg1;
}
else {
OverallScore = avg2;
}
total_1.setText(Integer.toString(avg1));
total_2.setText(Integer.toString(avg2));
Overall.setText(Integer.toString(OverallScore));
DrawPanel.repaint();
}
// Transfer the image from the BufferedImage to the JPanel to make it visible.
;
});
}
return Button_calc_draw;
}
}
});
}
return Reset;
}
private myJPanel getDrawPanel() {
if (DrawPanel == null) {
DrawPanel = new myJPanel();
DrawPanel.setLayout(new GridBagLayout());
DrawPanel.setBounds(new Rectangle(258, 39, 326, 361));
DrawPanel.setBackground(Color.white);
DrawPanel.setEnabled(true);
DrawPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
//Instantiate the BufferedImage object and give it the same width
// and height as that of the drawing area JPanel
img = new BufferedImage(DrawPanel.getWidth(),
DrawPanel.getHeight(),
BufferedImage.TYPE_INT_RGB);
//Get its graphics context. A graphics context of a particular object allows us to draw on it.
g2dImg = (Graphics2D)img.getGraphics();
//Draw a filled white coloured rectangle on the entire area to clear it.
g2dImg.setPaint(Color.WHITE);
g2dImg.fill(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
}
return DrawPanel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
snowBoarding thisClass = new snowBoarding();
thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
thisClass.setVisible(true);
}
});
}
public snowBoarding() {
super();
setResizable(false);
getContentPane().setLayout(null);
initialize();
}
private void initialize() {
this.setSize(600, 500);
this.setContentPane(getJContentPane());
this.setTitle("Snowboarding Score Calculator");
this.setResizable(false);
this.setVisible(true);
}
}
class myJPanel extends JPanel {
BufferedImage img;
Graphics2D g2dImg;
private static final long serialVersionUID = 1L;
private Rectangle2D.Double rectangle;
public void paintComponent(Graphics g) {
//Must be called to draw the JPanel control.
// As a side effect, it also clears it.
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
rectangle = new Rectangle2D.Double(0, 260-score[0] * 2, 25, score[0] * 2);
g2D.setPaint(Color.blue);
g2D.fill(rectangle);
g2D.draw(rectangle);
}
protected void clear(Graphics g) {
super.paintComponent(g);
// Also clear the BufferedImage object by drawing a white coloured filled rectangle all over.
g2dImg.setPaint(Color.WHITE);
g2dImg.fill(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
}
}
edit: removing unnecessary code
i need the repaint to draw rectangles using the run_1 and the run_2 array as the x or y values after i click draw and the reset to return the painted image back to a white slate.
draw button --> draws the graph
reset button --> removes the graph so that a new graph can be created.
You shall not use g2dImg in paintComponent(), but g instead (the parameter received by method paintComponent()). More precisely, ((Grpahics2D)g) instead of g2dImg.
g2dImg doesn't seem to be initialized in your code posted here, maybe you have done it somewhere...
More generally, you shall always use the Graphics instance you received in paint methods (casting it to Graphics2D if needed). You shall not try to reuse/share/store instances of Graphics.
The same applies for the clear() method.
Here is an example of how to rewrite this paintComponent() method:
private boolean shallPaint = false;
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (shallPaint) {
Graphics2D g2D = (Graphics2D) g;
rectangle = new Rectangle2D.Double(0, 260-score1 * 2, 25, score1 * 2);
g2D.setPaint(Color.blue);
g2D.fill(rectangle);
g2D.draw(rectangle);
}
}
public void setShallPaint(boolean pShallPaint) {
shallPaint = pShallPaint;
}
Then simply call myJPanel.repaint() to repaint it.
You shall replace, in your reset button:
DrawPanel.clear(DrawPanel.getGraphics());
with:
DrawPanel.setShallPaint(false);
DrawPanel.repaint();
And in Button_calc_draw:
DrawPanel.setShallPaint(true);
DrawPanel.repaint();
I am currently working on my personal project. The idea is to import a picture and crop it into n-pieces of bufferedimage then draw them with random sequence to a java canvas. After that save the canvas to image file. Right now iam stuck at saving the canvas and i have searching for the solutions but none of them work. Here my save procedure.
Please help, thanks in advance
private void save() {
int r = jFileChooser1.showSaveDialog(this);
File file2 = null;
if(r == jFileChooser1.APPROVE_OPTION){
file2 = jFileChooser1.getSelectedFile();
Graphics g2d = canvas.getGraphics();
BufferedImage bi = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.paint(g2);
g2.dispose();
g2d.dispose();
try
{
ImageIO.write(bi, "jpg", file2);
}
catch (Exception ex) {
System.out.println("Error saving");
}
}
}
Update :
Now i get it, after using paintComponents now i can save the picture. Thanks #madProgrammer
public class CaptureImage extends javax.swing.JFrame {
MyPanel canvas;
BufferedImage[] processedImage;
public CaptureImage(BufferedImage[] proc) {
processedImage = proc;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private void createAndShowGUI() {
System.out.println("Created GUI on EDT? "
+ SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Output Picture");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
save();
System.exit(0);//cierra aplicacion
}
});
canvas = new MyPanel(processedImage);
f.add(canvas);
f.setSize(400, 400);
f.setVisible(true);
}
public void save() {
JFileChooser jFileChooser1 = new JFileChooser();
int r = jFileChooser1.showSaveDialog(this);
File file2 = null;
if (r == jFileChooser1.APPROVE_OPTION) {
file2 = jFileChooser1.getSelectedFile();
BufferedImage bi = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.print(g2);
try {
ImageIO.write(bi, "jpg", file2);
g2.dispose();
} catch (Exception ex) {
System.out.println("Error saving");
}
}
}
}
class MyPanel extends JPanel {
private Image[] processedImage;
public MyPanel(Image[] processedImage) {
this.processedImage = processedImage;
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
repaint();
}
});
}
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int loopj = 10;
int loopi = 10;
int l = 0;
int jPieces = 100;
int[] r = new int[jPieces];
int rand = 0;
for (int i = 0; i < r.length; i++) {
rand = (int) (Math.random() * (r.length));
if (Arrays.binarySearch(r, 0, r.length, rand) <= -1) {
r[i] = rand;
}
}
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < loopi; i++) {
for (int j = 0; j < loopj; j++) {
g2d.drawImage(processedImage[r[l]], i * 30, j * 30, this);
l++;
}
}
}
}
There's no need to use getGraphics and you certainly shouldn't be disposing of it.
Instead of using paint, which could include double buffering, you should try using printAll
BufferedImage bi = new BufferedImage(canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.printAll(g2);
g2.dispose();
See Component#printAll for more details.
You should also be using the size of the canvas to determine the size of the image. The above example assumes that the canvas has already been sized appropriately...
I have a JTextPane with an image for its background.
prevWords = new JTextPane()
{
public void paint(Graphics g)
{
BufferedImage img;
try
{
img = ImageIO.read(new File("Images/logo.png"));
img.getGraphics().setColor(new Color(Color.TRANSLUCENT));
g.drawImage(img, 0, 0, null);
}
catch (IOException e)
{
System.out.println("Failed to load logo.");
}
super.paintComponents(g);
}
};
When I write text to the the pane, it I cannot see it. I have set the text in pane to be white as well.
This is a complete hack.
The problem here is, the UI is painting the background twice...
You need to circumvent the UI in such a way so that you can paint the image into the background while still getting the text to render over the top.
In the end, I had to make the text pane transparent so I could force the UI not to paint the background.
public class TextPaneBackground {
public static void main(String[] args) {
new TextPaneBackground();
}
public TextPaneBackground() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(new TextPaneWithBackground()));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TextPaneWithBackground extends JTextPane {
private BufferedImage background;
public TextPaneWithBackground() {
try {
background = ImageIO.read(new File("C:/Users/shane/Dropbox/MegaTokyo/Evil_Small.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
setForeground(Color.WHITE);
setOpaque(false);
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return background == null ? super.getPreferredScrollableViewportSize() : new Dimension(background.getWidth(), background.getHeight());
}
#Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
if (isOpaque()) {
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
}
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight()- background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
}
getUI().paint(g2d, this);
g2d.dispose();
}
}
}
Reimeus hinted at the ability to insert an image into the Document directly, this might be a better, long term solution.