我创建了一个简单的GameTimer类,它从给定的数字倒计时,一个包含updateTimer()方法的Swing GUI,它更新EDT上的计时器组件,以及一个RunTimer类,它连续调用updateTimer()直到GameTimer停止
计时器的第一个实例总是正常运行,但一旦停止并创建并启动另一个计时器,新计时器有时会在当前倒计时和最后一个计时器停止的值之间闪烁。
将组件更新移至EDT似乎无效。
在计时器的最后一次旋转之后调用updateTimer()以确保更新最后一个值还没有工作。
制作' secondsLeft'变量静态解决了问题,但这意味着我无法同时使用GameTimer的多个实例来计时不同的事件。
我添加了输出,当我从20开始倒数计时器时打印出变量值,将其停在17,然后创建并启动一个新的倒数计时器。
困惑,请帮忙!
public class GameTimer implements Runnable {
private int secondsLeft;
private boolean timerStop;
/**
* Creates a timer with a given number of seconds on the clock.
*/
public GameTimer(int seconds)
{
secondsLeft = seconds;
timerStop = false; // Set to true when timer should stop
}
/**
* Stops timer permanently
*/
public void stopTimer()
{
timerStop = true;
}
public int getSecondsLeft()
{
return secondsLeft;
}
@Override
public void run()
{
// While there timer is still counting down or all players finish
// their actions.
while (!timerStop)
{
//TEST
System.out.println("GamerTimer before sleep reads: " + String.valueOf(secondsLeft));
// Wait 1 second
try
{
Thread.sleep(1000);
}
catch (Exception e)
{
System.out.println("Error: " + e.toString());
}
//decrement timer 1 second
secondsLeft--;
if (secondsLeft <= 0)
{
timerStop = true;
}
//TEST - COMMENT OUT AFTER TESTING
System.out.println("GamerTimer after sleep reads: " + String.valueOf(secondsLeft));
}
}
}
private void updateTimer(final int secondsLeft)
{
timePanel.setVisible(true);
try
{
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run()
{
//TEST VALUES - COMMENT OUT AFTER TESTING
//System.out.println(String.valueOf(SwingUtilities.isEventDispatchThread()));
timeTextField.setText(String.valueOf(secondsLeft));
if (secondsLeft <= 5)
{
timeTextField.setBackground(Color.yellow);
}
else
{
timeTextField.setBackground(Color.white);
}
}
});
}
catch (Exception e)
{
System.out.println("Error: " + e.toString());
}
}
public class RunTimer implements Runnable
{
private GameTimer t;
public RunTimer(final GameTimer timer)
{
t = timer;
}
@Override
public void run()
{
stopTimer = false;
while (!stopTimer)
{
//TEST VALUES - COMMENT OUT AFTER TESTING
System.out.println("RunTimer class reads: " + String.valueOf(t.getSecondsLeft()));
updateTimer(t.getSecondsLeft());
try
{
Thread.sleep(500);
}
catch (Exception e)
{
System.out.println("Error: " + e.toString());
}
}
timePanel.setVisible(false);
}
}
**Output Results:**
GamerTimer before sleep reads: 20
RunTimer class reads: 20
RunTimer class reads: 20
GamerTimer after sleep reads: 19
GamerTimer before sleep reads: 19
RunTimer class reads: 19
RunTimer class reads: 19
GamerTimer after sleep reads: 18
GamerTimer before sleep reads: 18
RunTimer class reads: 18
RunTimer class reads: 18
GamerTimer after sleep reads: 17
GamerTimer before sleep reads: 17
RunTimer class reads: 17
GamerTimer before sleep reads: 20
RunTimer class reads: 20
RunTimer class reads: 17
RunTimer class reads: 20
GamerTimer after sleep reads: 16
RunTimer class reads: 16
GamerTimer after sleep reads: 19
GamerTimer before sleep reads: 19
RunTimer class reads: 19
RunTimer class reads: 16
RunTimer class reads: 19
RunTimer class reads: 16
GamerTimer after sleep reads: 18
GamerTimer before sleep reads: 18
RunTimer class reads: 18
RunTimer class reads: 16
RunTimer class reads: 18
RunTimer class reads: 16
GamerTimer after sleep reads: 17
GamerTimer before sleep reads: 17
RunTimer class reads: 17
RunTimer class reads: 16
RunTimer class reads: 17
RunTimer class reads: 16
BUILD STOPPED (total time: 11 seconds)