这个问题是基于我之前使用简单的Swing骰子程序遇到的问题。我发布的原始问题在这里,有一个被接受的答案,但我想知道究竟发生了什么、为什么会出现这个问题以及为什么解决方法有效。
我已经将原始代码缩减到核心部分,现在它看起来非常不同:
- 我有两个
ColorPanel
,每个面板上都画了一个有颜色的正方形。 - 当你点击一个面板时,该方块会按照以下顺序更改颜色:从黑色开始,然后变成红色、绿色、蓝色、红色、绿色、蓝色等。
- 一旦一个方块改变了颜色,它就永远不应该再变成黑色。
但是,当我只在MouseListener
中调用repaint()
时,程序行为非常奇怪:
- 我点击一个面板,正方形的颜色会改变。
- 然后我点击另一个面板,它的正方形颜色也会改变,但是第一个正方形也会变成黑色。
- 你可以在下面的GIF中看到这种行为:
如果使用getParent().repaint()
,此问题将消失,程序将按预期运行:
- 该问题似乎仅在面板/正方形开始“重叠”时发生。
- 如果使用阻止此类问题的布局或不设置小尺寸,则不会出现问题。
- 最初我认为涉及并发问题,但问题并非每次都会出现。
- 我在原始问题中遇到的代码似乎并未对所有人造成问题,因此我的IDE、jdk等可能也相关:Windows 7,Eclipse Kepler,jdk1.7.0_03。
除导入等内容以外的代码如下:
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();
}
});
}
}
所以我的问题是,这到底是怎么回事?