我创建了一个简单的计时器类,除非它的timerStop变量设置为true,否则会从20倒数到零,并在每秒后更新一个GUI数组中的JTextFiled。每次使用计时器时,都会创建一个新的GameTimer并将其传递给新的Thread。
问题: 计时器的第一次运行按预期执行,但后续实例将通过使用前一个计时器的最后一个值(它停止的数字)更新GUI文本字段开始,然后从20开始倒计时。
我已经尝试在代码末尾将变量重置为20并将值打印出来作为测试,并且该变量确实打印了#34; 20"但仍然是GUI更新下一个实例运行时的上一个停止时间。
我正在使用Netbeans IDE 8.0.2
真的很感激有关我的代码的任何建议和提示,谢谢!
public class GameTimer implements Runnable
{
private volatile int secondsLeft;
private MultiTextGUI[] guis;
private boolean timerStop;
public GameTimer(MultiTextGUI[] MTguis)
{
secondsLeft = 20;
guis = MTguis;
timerStop = false;
}
public void setTimerStop(boolean stop)
{
timerStop = stop;
}
@Override
public void run()
{
while (secondsLeft > 0 && !timerStop)
{
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println("Error: " + e.toString());
}
secondsLeft--;
System.out.println(secondsLeft); //TEST
for (MultiTextGUI gui: guis)
{
if (secondsLeft > 0)
{
if (gui != null)
{
gui.updateTimer(secondsLeft);
}
}
else
{
if (gui != null)
{
gui.setTimerOn(false);
}
}
}
}
secondsLeft = 20;
System.out.println(secondsLeft); //TEST
}
}
主线程:
GameTimer gt = new GameTimer(g);
Thread timerThread = new Thread(gt);
timerThread.start();
//code to show timer in gui
//code for countdownlatch
gt.setTimerStop(true);
答案 0 :(得分:0)
如果您使用的是Swing组件,则必须使用事件派发线程更新这些组件。在普通线程内更新组件将导致各种问题。
更新Swing组件时必须使用SwingUtilities.invokeLater。
以下代码确保事件派发线程上的execute中包含的语句。这是至关重要的原因是你可能会破坏你的挥杆UI的状态(假设这里使用的是什么)。绘制GUI是单线程的,如果您跳转并更新该单个线程(EDT)之外的组件,那么EDT可能正在您正在更新组件的过程中。腐败是最少的问题。
真正阴险的部分是,更新EDT之外的组件将在90%的时间内正常工作。然后当你最不期望它时,会发生一些疯狂的事情。这可能是你的问题与此无关,但在EDT中更新Swing仍然很重要。
有可用的教程。
SwingUtilities.invokeLater(new Runnable()
{
public void run ()
{
label.setText("New Value=" + x);
}
});
答案 1 :(得分:0)
在MultiTextGUI实例中设置更新值之前,您正在休眠一秒钟。如果显示在此1秒周期之前更新,则运行计时器的线程将不会更新显示的值,从而导致显示先前值。不确定是否可以在Thread.sleep(1000)调用之前设置该值并保留所需的行为。