1

私はJavaにかなり慣れていませんが、一般的なプログラミングはしていません。WindowsVistaでJava1.7.0_07を使用しています。Timer定期的にSwingを目盛りにする方法を見つけようとしています。

actionPerformedタイマー遅延を設定し、イベントハンドラーにはrepaint()メソッドしかありませんが、タイマーティックが安定していないか、正確ではないことに気付きました。

私はしばらくの間解決策を探していて、ジョンBマシューズ博士のかなりきちんとしたキネティックモデルの例を見てきました。彼の例では、デフォルトの遅延は40mSですが、タイマーは実際には47mS +/- 1mSで動作します(32mSから63mSまで時折変動します)。彼のイベントハンドラー内で費やされる時間actionPerformedは常に0mSです。これらの結果は、彼のコードをアプリケーションとして実行した結果です。

「原子」の動きを注意深く観察すると、吃音が目立ちます。タイマーがこのように動作する原因がわかりません。コンピューターで最小限のWindowsタスクを実行していますが、問題は引き続き発生します。

この問題の解決策はありますか、それともこれはJavaの単なる機能ですか?

4

1 に答える 1

2

ソースコードを見たり、徹底的な調査を行ったりしませんでした。しかし、私の最善の推測は、これが「機能」であるということです。

これにより、メソッドが EDT で呼び出されるjavax.swing.Timerことが保証されます。actionPerformedしたがって、Timerがその間隔に達すると、おそらくRunnableEDT で がスケジュールされ、次にactionPerformedメソッドが呼び出されます。ただし、EDT がその瞬間にビジーである場合 (たとえば、再描画を実行中)、それを実行することはできませんRunnable

したがって、わずかな遅延は避けられません...

ソースコードを確認したところ、私の最初の推測は正しいようです

void post() {
     if (notify.compareAndSet(false, true) || !coalesce) {
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 SwingUtilities.invokeLater(doPostEvent);
                 return null;
            }
        }, getAccessControlContext());
    }
}

を使用してinvokeLaterをスケジュールしRunnableます (おそらく、 の場合のように遅延が累積しないようにするためですinvokeAndWait)。ただし、これは、タイマーがイベントを送信してからactionPerformedメソッドが実際にトリガーされるまでの間に、EDT が以前のタスクを完了する必要があることを意味します。また、「EDT さん、今行っていることをやめて、まず私の仕事を実行してください」と言うメカニズムがないため、遅延を回避するメカニズムはありません。

(JDK7 で利用可能)Timerを使用する独自のものを作成すると、より良い結果が得られる可能性があります。SecondaryLoopしかし、それは大げさな推測です(私は何も試しませんでした)

于 2012-11-18T09:39:55.433 に答える