javaswinggraphicspaintcomponentmouse-listeners

Java simple paint code not working


I have this simple paint code that should draw but instead it moves the oval around the panel. When I remove super.paintComponent(g) line the program works it paints and not just move the oval, but I keep reading that we should not remove this line, so what can I do to leave the line in but still get the desired results?

class OraclePaint extends JFrame {
    public static void main(String[] args) {
        OraclePaint ss = new OraclePaint();
        ss.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ss.add(new MyPanel());
        ss.setSize(250, 200);
        ss.setVisible(true);
    }
}

class MyPanel extends JPanel {
    private int x = -10, y = -10;

    public MyPanel() {
        addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(MouseEvent event) {
                x = event.getX();
                y = event.getY();
                repaint();
            }
        }); // end call to addMouseMotionListener
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillOval(x, y, 22, 22);
    }
}

Solution

  • Based on the description, I assume that you want something like "a simple paint program".

    It is correct to invoke super.paintComponent(g) as the first line of an overridden paintComponent. And it is true that this erases the background (that is, everything that was painted before will be deleted).

    In Swing, everything that you want to paint has to be painted in the paintComponent method (or in any method that is called from there, and receives the same Graphics object).

    If you want to "save" everything that you have painted, you have to paint everything into an image (that is, into a BufferedImage), and paint this image in your paintComponent method.

    There are some other issues with the code, but without changing too much of the remaining code, this could roughly (!) be achieved like this:

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionAdapter;
    import java.awt.image.BufferedImage;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    class OraclePaint extends JFrame {
        public static void main(String[] args) {
            OraclePaint ss = new OraclePaint();
            ss.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            ss.add(new MyPanel());
            ss.setSize(250, 200);
            ss.setVisible(true);
        }
    }
    
    class MyPanel extends JPanel {
        private BufferedImage image = null;
    
        public MyPanel() {
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent event) {
                    if (image != null) {
    
                        // Paint into the image
                        Graphics g = image.getGraphics();
                        g.setColor(Color.BLACK);
                        g.fillOval(event.getX(),  event.getY(), 22, 22);
                        g.dispose();
    
                        repaint();
                    }
                }
            }); // end call to addMouseMotionListener
        }
    
        // Make sure that the image is not 'null' and that
        // it has the same size as this panel
        private void validateImage()
        {
            if (image == null)
            {
                image = new BufferedImage(getWidth(), getHeight(),
                    BufferedImage.TYPE_INT_ARGB);
            }
            if (image.getWidth() != getWidth() || image.getHeight() != getHeight())
            {
                BufferedImage newImage = new BufferedImage(getWidth(), getHeight(),
                    BufferedImage.TYPE_INT_ARGB);
                Graphics g = newImage.getGraphics();
                g.drawImage(image, 0, 0, null);
                g.dispose();
                image = newImage;
            }
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            validateImage();
            g.drawImage(image, 0, 0, null);
        }
    }