gpt4 book ai didi

java - Swing 计时器仅在最后一个事件上运行

转载 作者:行者123 更新时间:2023-11-30 03:42:45 27 4
gpt4 key购买 nike

我正在尝试构建一个 Simon Says 游戏,该游戏会闪烁按下按钮。我目前正在尝试研究如何使按钮一个接一个地闪烁。按照文档(尽我所能),我编写了下面的代码,但由于某种原因只有绿色按钮闪烁。我进一步测试了一下,发现只有 btnGo 事件中的最后一个方法可以按预期工作。我认为这与计时器运行的方式有关,并且在计时器完成之前将红色和蓝色按钮变回黑色,但我不确定如何或为什么?

public void flashRed(){
btn1.setBackground(Color.red);
btn2.setBackground(Color.black);
btn3.setBackground(Color.black);
btn4.setBackground(Color.black);
repaint();
t.start();
}
public void flashYellow(){
btn1.setBackground(Color.black);
btn2.setBackground(Color.yellow);
btn3.setBackground(Color.black);
btn4.setBackground(Color.black);
repaint();
t.start();
}
public void flashGreen(){
btn1.setBackground(Color.black);
btn2.setBackground(Color.black);
btn3.setBackground(Color.green);
btn4.setBackground(Color.black);
repaint();
t.start();
}
public void flashBlue(){
btn1.setBackground(Color.black);
btn2.setBackground(Color.black);
btn3.setBackground(Color.black);
btn4.setBackground(Color.blue);
repaint();
t.start();
}

@Override
public void actionPerformed(ActionEvent event) {
if(event.getSource() == btnGo)
{
flashRed();
flashBlue();
flashGreen();

}
if(event.getSource() ==t){
btn1.setBackground(Color.black); //resets btn1 to black
btn2.setBackground(Color.black);
btn3.setBackground(Color.black);
btn4.setBackground(Color.black);

repaint();
t.stop(); //stops the timer
}
}

最佳答案

有几点需要记住:

  • Swing 是单线程的(线程称为 E(vent) D(ispatch) T(hread))。当您在该线程上执行操作时,您的 UI 无法重新绘制,反之亦然。
  • 调用repaint()实际上并不执行重绘。它只是在 EDT 上安排一次重新绘制。如果安排了多次重绘,它们会被简单地分组并且只执行一次
  • JComponents 上的大多数方法不会立即更改组件。他们只是更改该组件的状态并安排重新绘制。重绘完成后,您会看到所做的更改反射(reflect)在 UI 中。

那么当您按下 JButton 并触发您的 ActionListener 时会发生什么:

flashRed();
flashBlue();
flashGreen();

这将改变很多按钮的背景颜色,但根本没有时间执行重绘,因为您的代码正在占用 EDT。只有当您的 ActionListener 完成时,repaint 才能执行。此时,除了绿色按钮之外,所有按钮的背景都变回黑色。这就是为什么您只看到绿色按钮闪烁。

要解决这个问题,您需要做的就是将它们一一闪烁,并在中间释放 EDT,给它时间来执行重绘。我将通过使用计时器来解决这个问题。但为什么你只用它来将按钮的背景恢复为黑色,我也会用它来闪烁。

在伪代码中,ActionListener 看起来像:

switch ( iteration ){
case first:
flashRed();
increaseIteration();
break;
case second:
flashBlue();
increaseIteration();
break;
...
case last:
restoreAllToBlack();
timer.stop();
break;
}

关于java - Swing 计时器仅在最后一个事件上运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26440603/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com