Reputation: 91
Im making a small painting program that basically has buttons on the left, indicating the colors, and wherever you click and drag, it'll draw a circle using graphics. i know, not efficient at all, and i can be using strokes and stuff, but im still learning and didn't get to that yet, so im testing it out with what i know. Everything seems to be working, with one small problem. I can click, drag, and a line is drawn. But when i change the color, and go draw something else, the first circle drawn is the previous color. I have tried many things but cant seem to fix it.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.Timer;
public class painting extends JFrame{
ArrayList<Integer> mouseLocXList = new ArrayList<Integer>();
ArrayList<Integer> mouseLocYList = new ArrayList<Integer>();
ArrayList<Color> colors = new ArrayList<Color>();
Color colorChosen = Color.black;
String[] colorsSideBarButtonString = {"Red", "Blue", "Green", "Orange", "Pink"};
Color[] colorsSideBar = {Color.red, Color.blue, Color.green, Color.orange ,
Color.pink};
JButton[] buttons = new JButton[colorsSideBarButtonString.length];
public painting(){
setSize(1200,700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setBackground(Color.WHITE);
setLayout(null);
setFocusable(true);
addMouseMotionListener(new handler());
colors.add(Color.black);
for(int x = 0; x < colorsSideBarButtonString.length; x++){
buttons[x] = new JButton(colorsSideBarButtonString[x]);
buttons[x].setBounds(2,(x*50)+30,70,46);
add(buttons[x]);
buttons[x].addActionListener(new buttonListener());
}
setVisible(true);
}
public static void main(String[] args){
new painting();
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.black);
g.drawLine(72, 0, 72, 900);
g.drawLine(1150, 0, 1150, 900);
g.drawString("Colors", 17, 45);
for(int i = 0; i < mouseLocXList.size(); i++){
g.setColor(colors.get(i));
g.fillOval(mouseLocXList.get(i),mouseLocYList.get(i),30,30);
}
}
public class handler implements MouseMotionListener{
public void mouseDragged(MouseEvent e) {
mouseLocXList.add(e.getX());
mouseLocYList.add(e.getY());
colors.add(colorChosen);
repaint();
}
public void mouseMoved(MouseEvent e) {
}
}
public class buttonListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
for(int c = 0; c < buttons.length; c++)
if(e.getSource() == buttons[c]){
colorChosen = colorsSideBar[c];
}
}
}
}
Sorry the programs kinda long, i dont see where i can shorten it, everything seems necessary. Basically every time the mouse is clicked and dragged, its location is stored in an array, where its then drawn in a for loop in graphics. The color is clicked, and added to its own array, and every update to the mouses location while dragged, the current color is added to the colors array so it can be redrawn in color while in the for loop. I would think the best way to fix the problem is to run it.
Once again, i know this is probably one of the worst written programs you've ever seen. I understand, but i am just testing out and trying to see how advanced i can make this.
Upvotes: 0
Views: 316
Reputation: 347184
Painting is destructive, that is, each time paint
is called, it will clear/remove what ever was painted before it.
This is very important, as the Graphics
context is shared by all the components that are painted during the paint cycle, meaning, when it gets to you, it might already have something painted on it.
You need to do two things.
First, you need to create something that is paintable, that is, some kind of object which provides a simple paint
or draw
method which you can pass the Graphics
context to. This object should know what it's painting and in what color
Second, you need to add each of these "paintable" objects to a List
of some kind as they are created. This will allow you to loop through the List
and repaint them when you need to.
You should avoid overriding paint
of top level containers like JFrame
, apart from the fact that they aren't double buffered and can produce flickering when updated, you could end up painting under the borders of the frame's decorations (0x0 is actually the top left of the window/frame, not the viewable area under the frame's title bar).
Instead, use a JPanel
and override it's paintComponent
method
Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
Updated...
You color list is out of sync with your mouse points because you did...
colors.add(Color.black);
In the constructor. This means that the first circle will be painted in black and the next in the selected color. When you change colors, it is still out of sync
Upvotes: 2