Reputation: 1129
So I have a program that is basically like paint but made in Java and can only draw a few colours. By default the background of the program is white, but what I'd like to do is try to load an image and then be able to draw on top of that image. I can load the image but fro some reason it wont show the lines when I try drawing on it. Here is the code.
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Paint {
public static void main(String[] args) {
PaintWindow frame = new PaintWindow();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
}
}
class PaintWindow extends JFrame {
public PaintWindow() {
setTitle("JavShot Edit");
setSize(668, 600);
setLocationRelativeTo(null);
panel = new JPanel();
drawPad = new PadDraw();
panel.setPreferredSize(new Dimension(75, 68));
//Creates a new container
Container content = this.getContentPane();
content.setLayout(new BorderLayout());
//sets the panel to the left, padDraw in the center
content.add(panel, BorderLayout.WEST);
content.add(drawPad, BorderLayout.CENTER);
//add the color buttons:
makeColorButton(Color.BLUE);
makeColorButton(Color.MAGENTA);
makeColorButton(Color.RED);
makeColorButton(Color.GREEN);
makeColorButton(Color.BLACK);
makeColorButton(Color.WHITE);
//creates the clear button
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
drawPad.clear();
}
});
panel.add(clearButton);
}
/*
* makes a button that changes the color
* @param color the color used for the button
*/
public void makeColorButton(final Color color) {
JButton tempButton = new JButton();
tempButton.setBackground(color);
tempButton.setPreferredSize(new Dimension(16, 16));
panel.add(tempButton);
tempButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
drawPad.changeColor(color);
}
});
}
private JPanel panel;
private PadDraw drawPad;
}
class PadDraw extends JComponent {
//this is gonna be your image that you draw on
Image image;
//this is what we'll be using to draw on
Graphics2D graphics2D;
//these are gonna hold our mouse coordinates
int currentX, currentY, oldX, oldY;
public PadDraw() {
setDoubleBuffered(false);
addMouseListener(new MouseAdapter() {
//if the mouse is pressed it sets the oldX & oldY
//coordinates as the mouses x & y coordinates
public void mousePressed(MouseEvent e) {
oldX = e.getX();
oldY = e.getY();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
//while the mouse is dragged it sets currentX & currentY as the mouses x and y
//then it draws a line at the coordinates
//it repaints it and sets oldX and oldY as currentX and currentY
public void mouseDragged(MouseEvent e) {
currentX = e.getX();
currentY = e.getY();
graphics2D.drawLine(oldX, oldY, currentX, currentY);
graphics2D.drawLine(oldX + 1, oldY + 1, currentX + 1, currentY + 1);
repaint();
oldX = currentX;
oldY = currentY;
}
});
}
//this is the painting bit
//if it has nothing on it then
//it creates an image the size of the window
//sets the value of Graphics as the image
//sets the rendering
//runs the clear() method
//then it draws the image
public void paintComponent(Graphics g) {
try {
image = ImageIO.read(new File("C:\\Users\\user\\Desktop\\Untitled.png"));
graphics2D = (Graphics2D)image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
} catch (IOException e) { }
if(image == null) {
image = createImage(getSize().width, getSize().height);
graphics2D = (Graphics2D)image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, null);
}
//this is the clear
//it sets the colors as white
//then it fills the window with white
//thin it sets the color back to black
public void clear() {
graphics2D.setPaint(Color.white);
graphics2D.fillRect(0, 0, getSize().width, getSize().height);
graphics2D.setPaint(Color.black);
repaint();
}
public void changeColor(Color theColor) {
graphics2D.setPaint(theColor);
repaint();
}
}
I load the image here:
image = ImageIO.read(new File("C:\\Users\\user\\Desktop\\Untitled.png"));
graphics2D = (Graphics2D)image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
} catch (IOException e) { }
Does anyone know what the problem is?
Upvotes: 1
Views: 704
Reputation: 347204
Painting is a destructive process. That is, each time paintComponent
is called, you are expected to repaint what ever it is you need to displayed the screen, entirely from scratch.
There are (at least) two immediate issues with your approach
super.paintComponent
, this will effect the way in which the paint process updates the screen, this VERY important as you have extended from JComponent
which is transparent by default and may compromise the ability for the framework to function correctly (leaving nasty paint artifacts all over the place) - also remember, Graphics
is a shared resource. All the other components that are to be painted will share this resource, meaning that you could end up with what ever was painted before you being left on the screen.paintComponent
is called. This means, that what ever you painted to graphics2D
is going to be lost.I wouldn't bother setDoubleBuffered(false)
as this will effect the way in which the component is updated and could produce undesirable results.
I would add each point you want to draw to a List
of some kind and paint this list within the paintComponent
method.
Don't load resources within any paintXxx
method. These should be prepared before hand.
I can see that you are "trying" to perform some kind of double buffering, but this isn't really how it should be done. You are going little from it other then problems. Start with a simple solution first.
Upvotes: 4