我创建了CountDown.java文件并尝试将我的Word-trouble.java文件(主applet)添加为CountDown ct = new CountDown();
但它没有在主applet中显示计时器。
以下是编码:
package pack.urdu;
import java.awt.*; //windows toolkit
import java.applet.*; //applet support
public class CountDown extends Applet implements Runnable{
int counter; Thread cd;
public void start() { // create thread
counter = 60; cd = new Thread(this); cd.start();
}
public void stop() { cd = null;}
public void run() { // executed by Thread
while (counter>0 && cd!=null) {
try{Thread.sleep(1000);} catch (InterruptedException e){}
--counter; repaint(); //update screen
}
}
public void paint(Graphics g) {
g.drawString(String.valueOf(counter),25,75);
}
}
答案 0 :(得分:0)
我犯了一个错误,我看到很多程序员犯了错误:你正在计算经过的时间,计算刷新时间。如果由于线程争用而导致睡眠持续时间超过一秒,则计时器将漂移。
不是跟踪每秒递增的计数器,而是记录开始时间:
long startTime = System.currentTimeMillis();
然后,您的绘画方法变为:
public void paint(Graphics g) {
int elapsedSeconds = (int)(System.currentTimeMillis()-startTime)/1000
g.drawString(String.valueOf(elapsedSeconds),25,75);
}
此方法可以经常调用,也可以根据需要多次调用,并且始终显示正确的经过秒数。无需在任何指定时间增加任何内容。
您唯一需要做的就是安排刷新屏幕。 (我想说你只需要在用户查看它时刷新屏幕:-)但是因为我们不知道我们需要更频繁地更新)。其机制可能取决于图形库。一个懒惰的想法是每秒刷新十次,屏幕大部分时间都是正确的。
如果您确实希望有一个发送重绘事件的线程,那么您应该在计时器点击一个新值时发送这些事件,从而每秒只发送一个。这完成了:
while (stillRunning) {
long elapsedTime = System.currentTimeMillis() - startTime;
long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);
Thread.sleep(timeTillNextDisplayChange);
repaint();
}
请注意,你不会睡1000ms!如果你的系统运行良好,这将非常接近1000毫秒,但略小于(1)线程启动延迟(可能由线程争用引起)和(2)此循环的处理时间(这是相当小)。在任何情况下,以这种方式计算睡眠将防止计时器漂移,并确保您的显示更新就像秒值更改一样。
请参阅我网站上对Common Misunderstandings of Timers的扩展讨论。