Search code examples
javaswingpaintcomponent

Java paintComponent paints a copy of the top GUI panel for no apparent reason


I'm working on a simple painting application in Java but Swing doesn't want to cooperate. At first I tried making a JTabbedPane that holds the DrawArea and a settings panel, but for some bizarre reason the second mouseDragged() (and by extension the drawArea.repaint() method) was triggered, the JTabbedPane seemed to duplicate. Imagine two identical tab panes stacked vertically. I thought this was just some bug in JTabbedPane, but I rewrote everything to a very simple custom menu using JButtons on a panel and the exact same thing happened. It's not like the GUI actually duplicated the top area; it's unusable and I can paint over it. Check it out: enter image description here

Edit: I found a similar question. If I call super.paintComponent(g), the problem goes away (and drawArea.setBackground(color) actually works!) but the function called on super (a new keyword for me) basically repaints the drawArea so the paint trail is no longer saved.

If I paint a rectangle to fill the drawArea it overwrites the issue even though mouseDragged is still fired. Here's the rendering code:

@Override
public void mouseDragged(MouseEvent e) {
    x = e.getX(); y = e.getY();
    drawArea.repaint();
}

// (subclass):
class DrawArea extends JPanel {
    public void paintComponent(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillOval(x-3, y-3, 7, 7);
    }
}

And here's the GUI code:

    frame = new JFrame("Jadra");
    frame.setSize(650, 600);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    menu = new JPanel();

    settingsButton = new JButton("Settings");
    clearButton = new JButton("Clear");
    exitButton = new JButton("Quit");

    menu.setLayout(new FlowLayout());
    menu.add(settingsButton);
    menu.add(clearButton);
    menu.add(exitButton);
    menu.setBackground(new Color(30, 90, 60));

    drawArea = new DrawArea();
    drawArea.setBackground(Color.red);
    drawArea.setOpaque(true);
    drawArea.addMouseMotionListener(this);

    frame.getContentPane().add(menu, BorderLayout.NORTH);
    frame.getContentPane().add(drawArea, BorderLayout.CENTER);

    Thread pt = new Thread(new Painter());
    frame.setVisible(true);
    pt.start();

Please tell me I did something really stupid. Otherwise this looks like a really annoying bug. I really appreciate your help. Thanks!


Solution

  • Your DrawPanel.paintComponent() method should chain upward to the method it overrides from JPanel to allow default painting to occur. Simply add

    super.paintComponent(g);
    

    As the first line to this method.