1

CountDown.java ファイルを作成し、Word-trouble.java ファイル (メイン アプレット) に追加しようとしましたCountDown ct = new CountDown(); が、メイン アプレットにタイマーが表示されません。

コーディングは次のとおりです。

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);

}

}
4

1 に答える 1

0

多くのプログラマーが犯す間違いを犯しています。経過時間の計算とリフレッシュ時間の計算を混同しています。スレッドの競合が原因でスリープ時間が 1 秒を超えると、タイマーがずれます。

毎秒インクリメントするカウンターを追跡する代わりに、開始時間を記録するだけです。

long startTime = System.currentTimeMillis();

その後、ペイント メソッドは次のようになります。

public void paint(Graphics g) {
    int elapsedSeconds = (int)(System.currentTimeMillis()-startTime)/1000
    g.drawString(String.valueOf(elapsedSeconds),25,75);
}

このメソッドは何度でも呼び出すことができ、常に正しい経過秒数を表示します。指定された時間に何かをインクリメントする必要はありません。

他に行う必要があるのは、画面が更新されるように調整することだけです。(ユーザーが画面を見たときにのみ画面を更新する必要があると言いたいです:-)しかし、より頻繁に更新する必要があるかどうかはわかりません)。このメカニズムは、グラフィック ライブラリに依存する場合があります。怠惰なアイデアの 1 つは、1 秒間に 10 回更新することであり、ほとんどの場合、画面は正しく表示されます。

再描画イベントを送信するスレッドが必要な場合は、タイマーがクリックして新しい値になったときにこれらのイベントを送信し、1 秒に 1 回だけ送信する必要があります。これは以下で行われます:

while (stillRunning) {
    long elapsedTime = System.currentTimeMillis() - startTime;
    long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);
    Thread.sleep(timeTillNextDisplayChange);
    repaint();
}

1000ミリ秒スリープしないことに注意してください!システムのパフォーマンスが良好な場合、これは 1000 ミリ秒に非常に近くなりますが、(1) スレッドの競合が原因である可能性があるスレッドの起動遅延と、(2) このループの処理時間 (これはかなり小さい)。いずれにせよ、この方法でスリープを計算すると、タイマーのドリフトが防止され、秒の値が変化したときにディスプレイが確実に更新されます。

私の Web サイトで、タイマーの一般的な誤解に関する詳細な議論を参照してください。

于 2013-01-15T07:37:02.803 に答える