2

I want to draw an oval when I click the mouse in my panel. And drawing is allowed after I click the button. But a problem is occurs: a copy of the button is drawn in the top left of the panel.

This is my code:

 public class PaintPanel extends JPanel implements MouseListener, MouseMotionListener{

        private boolean draw = false;
        private JButton button;
        private Point myPoint;
        public PaintPanel(){
            this.setSize(800,600);
            button = new JButton("Allow draw");
            button.setSize(30,30);
            this.add(button);
            this.addMouseListener(this);
            this.addMouseMotionListener(this);
            button.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    draw = true;

                }
            });
        }
        @Override
        public void paintComponent(Graphics g){
            g.setFont(new Font("Arial",Font.BOLD,24));
            g.setColor(Color.BLUE);
            if(draw){
                g.drawOval(myPoint.x-10, myPoint.y-10, 20, 20);
            }
        }
        @Override
        public void mousePressed(MouseEvent e) {
            if(draw){
                myPoint = e.getPoint();
                repaint();
            }
        }
        public static void main(String[] agrs){
            JFrame frame = new JFrame("Painting on panel");
            frame.add(new PaintPanel());
            frame.setVisible(true);
            frame.setSize(800,600);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
        }
    }
Charles
  • 50,943
  • 13
  • 104
  • 142
  • 1
    Swing apps should be run from the EDT. See [Initial Threads](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) for more details. – Paul Samsotha Mar 12 '14 at 03:11

2 Answers2

3

You broke the paint chain.

Add super.paintComponent(g) before you do any custom painting

public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.setFont(new Font("Arial",Font.BOLD,24));
    g.setColor(Color.BLUE);
    if(draw){
        g.drawOval(myPoint.x-10, myPoint.y-10, 20, 20);
    }
}

Graphics is a shared resource. It is provided to everything that is painted within a given paint cycle, meaning, that unless you clear it first, it will contain other things that have already been painted before you.

One of the jobs of paintComponent is to prepare the Graphics context for painting, but clearing it (filling it with the components background color)

Take a closer look at Performing Custom Painting and Painting in AWT and Swing for more details

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I want to draw append. previos oval doesn't disappear – hjepsjga_94 Mar 12 '14 at 03:11
  • Then add them to some kind of `List` and repaint them when `paintComponent` is called. Painting in Swing is a destructive process, this is how the API works, you need to work within it. – MadProgrammer Mar 12 '14 at 03:12
  • _"I want to draw append. previos oval doesn't disappear "_. @hjepsjga_94 see [this example](http://stackoverflow.com/a/22123304/2587435) in regards to MadProgrammer's point about the `List` – Paul Samsotha Mar 12 '14 at 03:14
  • @hjepsjga_94 For [example](http://stackoverflow.com/questions/12683533/drawing-a-rectangle-that-wont-disappear-in-next-paint/12683601#12683601) – MadProgrammer Mar 12 '14 at 03:16
1

I want to draw append. previos oval doesn't disappear

See Custom Painting Approaches for the two common ways to do incremental painting:

  1. Keep a List of all the objects you want to paint and then iterate through this List in the paintComponent() method of your component
  2. Use a BufferedImage and draw your objects on the BufferedImage and then just paint the BufferedImage in your paintComponent() method.
camickr
  • 321,443
  • 19
  • 166
  • 288