This question is based on a problem I had a while back with a simple Swing dice program. The original question I posted is here and has an accepted answer, but I'd like to know exactly what is happening, why the problem occurs, and why the solution works.
I managed to whittle down the original code to get to the core of the problem and it now looks very different:
ColorPanel
s that each draw a coloured squareHowever when I just call repaint()
in the MouseListener
, the program behaves very strangely:
If you use getParent().repaint()
instead this behaviour goes away and the program behaves as expected:
The code minus imports etc is as follows:
public class ColorPanelsWindow extends JFrame{
static class ColorPanel extends JPanel {
//color starts off black
//once it is changed should never be
//black again
private Color color = Color.BLACK;
ColorPanel(){
//add listener
addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent arg0) {
color = rotateColor();
repaint();
//using getParent().repaint() instead of repaint() solves the problem
//getParent().repaint();
}
});
}
//rotates the color black/blue > red > green > blue
private Color rotateColor(){
if (color==Color.BLACK || color == Color.BLUE)
return Color.RED;
if (color==Color.RED)
return Color.GREEN;
else return Color.BLUE;
}
@Override
public void paintComponent(Graphics g){
g.setColor(color);
g.fillRect(0, 0, 100, 100);
}
}
ColorPanelsWindow(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridLayout(1,0));
add(new ColorPanel());
add(new ColorPanel());
//the size must be set so that the window is too small
// and the two ColorPanels are overlapping
setSize(40, 40);
// setSize(300, 200);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new ColorPanelsWindow();
}
});
}
}
So my question is, what on earth is going on here?
but I'd like to know exactly what is happening,
I see the same problems using JDK7u60 on Windows 7. Definitely seems like a bug to me.
My best guess is that it is a problem with the double buffering.
I added so debug code to the paintComponent()
method.
1) When you click on the right component only its paintComponent()
method is called and the panel is painted the proper color.
2) When you click on the left component only its paintComponent()
method is called and the panel is painted the proper color, however the panel on the right reverts back to the black color, without invoking the paintComonent()
method on the right panel. This leads me to believe that somehow an old buffer is being used (this would be the bug and I have no idea how to fix it).
The reason that getParent().repaint()
works is because this forces both components to be repainted no matter which panel you click on.