【发布时间】:2018-06-12 11:20:00
【问题描述】:
我正在开发的一个小程序出现了一个奇怪的故障。它是 Pictionary 或 Charades 等游戏的记分员/计时器。
我将从程序应该做什么开始。单击 Start Timer 按钮禁用 Set Time、Reset Timer 和 Start Timer 按钮,然后开始计时器倒计时。倒计时本身是在一个线程中处理的,因此可以使用 Timer Stop 按钮将其停止。所有这些功能都运行良好,除了当我点击开始时发生的一个奇怪的小图形故障:
您可以看到“重置计时器”按钮的“幽灵”出现在数字上方,并且“6”的一点点出现在“重置计时器”按钮上方。这通常会发生,但有时会出现启动计时器的幽灵,或者有时什么都没有。这个“幽灵”在倒计时循环的下一次迭代和随后的计时器重绘中消失。
话虽如此,我已将问题追溯到禁用三个按钮。当我从我的代码中删除它时,没有任何故障。禁用按钮后,也许整个底部的 JPanel 需要重新粉刷?我不认为这是必要的。无论如何,我将在下面粘贴相关代码。我希望您能就如何防止这种情况的发生提出一些建议。
public void disableButtons() {
timerStartButton.setEnabled(false);
resetTimerButton.setEnabled(false);
setTimeButton.setEnabled(false);
}
public void enableButtons() {
timerStartButton.setEnabled(true);
resetTimerButton.setEnabled(true);
setTimeButton.setEnabled(true);
}
public void timerThread(){
disableButtons();
timerRunning = true;
Thread t = new Thread(new Runnable(){
@Override
public void run(){
timerInterrupted = false;
while(timerRunning && timer > 0){
try {
timerLabel.setText(Integer.toString(timer));
timerLabel.paintImmediately(timerLabel.getVisibleRect());
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ScoreTime.class.getName()).log(Level.SEVERE, null, ex);
}
timer--;
}
timerRunning = false;
if (!timerInterrupted) {
timer = 0;
timerLabel.setText(Integer.toString(timer));
if (soundOn) {
try {
//load the buzzer sound as a clip
AudioInputStream buzzerAudioIn = AudioSystem.getAudioInputStream(buzzerSoundFile);
Clip buzzerClip = AudioSystem.getClip();
buzzerClip.open(buzzerAudioIn);
buzzerClip.start();
Thread.sleep(1500);
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException ex) {
Logger.getLogger(ScoreTime.class.getName()).log(Level.SEVERE, null, ex);
}
}
else {
try {
Thread.sleep(1500);
} catch (InterruptedException ex) {
Logger.getLogger(ScoreTime.class.getName()).log(Level.SEVERE, null, ex);
}
}
timer = userTime;
timerLabel.setText(Integer.toString(timer));
enableButtons();
}
}
});
t.start();
}
【问题讨论】:
-
对我来说最突出的是您的线程正在直接更新 UI 组件。这应该通过 EventQueue.invokeLater() 来处理。
-
嗯...我还没有使用 EventQueue.invokeLater()。我仍然在学习线程方面搞砸了。我将不得不寻找一些关于它是如何工作的例子。如果我使用它,计时器中的数字还会实时更新吗?
标签: java swing button repaint display