Java 在Swing中进行实时/动态更改

Java 在Swing中进行实时/动态更改,java,swing,concurrency,windowbuilder,Java,Swing,Concurrency,Windowbuilder,我正在制作一个有方块的游戏(一个格子的面板),当游戏结束时,会有一个算法以“实时”的方式一个接一个地改变面板的颜色,用户会看到方块慢慢地改变颜色。我试着做如下事情: Thread.sleep(1000); grid.getComponent(boxNumber).setBackground(Color.YELLOW); Thread.sleep(1000); grid.getComponent(boxNumber).setBackground(Color.ORANGE);

我正在制作一个有方块的游戏(一个格子的面板),当游戏结束时,会有一个算法以“实时”的方式一个接一个地改变面板的颜色,用户会看到方块慢慢地改变颜色。我试着做如下事情:

Thread.sleep(1000);      

grid.getComponent(boxNumber).setBackground(Color.YELLOW);

Thread.sleep(1000); 

grid.getComponent(boxNumber).setBackground(Color.ORANGE);

虽然长方体的颜色会变为黄色,但之后不会变为橙色。有人有什么想法吗?希望我能说清楚。

这些需要在Swing事件线程上发生。呼叫设置后台通过:

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    grid.getComponent(boxNumber).setBackground(Color.ORANGE);
  }
});
注意,您的
Thread.sleep()
不应位于事件线程中(或直接位于Swing事件侦听器(ActionListener、WindowListener等)中)


谨慎的做法是查看特定于此类事件的。这些事件需要在Swing事件线程上发生。通过以下方式调用set background:

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    grid.getComponent(boxNumber).setBackground(Color.ORANGE);
  }
});
注意,您的
Thread.sleep()
不应位于事件线程中(或直接位于Swing事件侦听器(ActionListener、WindowListener等)中)


另外,请谨慎地查看专门用于此类操作的方法。

阅读Swing教程中关于的部分,了解不应使用sleep()方法的原因


一种解决方案是使用SwingWorker,然后您可以“发布”组件的颜色,以便在EDT上正确更新,还可以在worker中调用sleep()方法。

阅读Swing教程中关于的部分,了解为什么不应该使用sleep()方法


一种解决方案是使用SwingWorker,然后您可以“发布”组件的颜色,以便在EDT上正确更新组件,还可以在worker中调用sleep()方法。

-通常在EDT中执行
Thread.sleep(1000);
。您应该尝试使用。
-之后还需要调用
revalidate()/validate()和repaint()

所以可能是这样的:

Timer yellowTimer = new Timer(1000,new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
             jtp.setBackground(Color.YELLOW);
            //call revalidate()/validate() and repaint() afterward
             jtp.revalidate();
             jtp.repaint();
        }
    });
yellowTimer.setRepeats(false);

Timer orangeTimer = new Timer(2000,new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
             jtp.setBackground(Color.ORANGE);
             //call revalidate()/validate() and repaint() afterward
             jtp.revalidate();
             jtp.repaint();
        }
    });
orangeTimer.setRepeats(false);

yellowTimer.start();
orangeTimer.start();

-通常在EDT中执行
线程睡眠(1000);
不是一个好主意。您应该尝试使用。
-之后还需要调用
revalidate()/validate()和repaint()

所以可能是这样的:

Timer yellowTimer = new Timer(1000,new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
             jtp.setBackground(Color.YELLOW);
            //call revalidate()/validate() and repaint() afterward
             jtp.revalidate();
             jtp.repaint();
        }
    });
yellowTimer.setRepeats(false);

Timer orangeTimer = new Timer(2000,new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
             jtp.setBackground(Color.ORANGE);
             //call revalidate()/validate() and repaint() afterward
             jtp.revalidate();
             jtp.repaint();
        }
    });
orangeTimer.setRepeats(false);

yellowTimer.start();
orangeTimer.start();

你试过调用
invalidate
?不,不太了解它。我是Swing的新手。我会尝试一下。谢谢。编辑:我只是看了一下,我不确定这对我有什么帮助=/没有必要调用invalidate().Swing组件将自动重新绘制。您是否尝试调用
invalidate
.Swing组件将自动重新绘制自己。+1定时器是一个潜在的解决方案(但不是最好的,因为现在逻辑分布在两个类中)。-1,不需要重新验证(),因为组件的大小不会更改,并且重新绘制()不需要,因为Swing组件足够聪明,可以自己重新绘制。+1定时器是一个潜在的解决方案(但不是最好的,因为现在逻辑分布在两个类中)。-1,不需要重新验证(),因为组件的大小不会改变,也不需要重新绘制(),因为Swing组件足够聪明,可以自己重新绘制。