7

カスタム Swing コンポーネント内でアニメーションを実行するために使用されるSwing タイマー ( javax.swing.Timer ) があります。

ただし、これは問題を引き起こしています。特に、すべてのウィンドウが閉じられた後でも、ライブ タイマー スレッドが原因で、アプリケーションの終了が停止しているようです。また、アニメーションが表示されないときに非表示のオブジェクトで実行されるタイマーのオーバーヘッドを回避するとよいでしょう。

理想的には、次のことをしたいと思います。

  • コンポーネントが非表示になったらタイマーを停止する
  • コンポーネントが表示されるたびに時間を再開します

これは可能ですか(もちろん、スレッドセーフな方法で!)

4

3 に答える 3

5

私はあなたの最初の前提に懐疑的です:この単純な反例は、ランニングjavax.swing.Timerが排除しないことを示していEXIT_ON_CLOSEます。package-private、sharedjavax.swing.TimerQueueはデーモンスレッドを開始し、プログラムの終了を許可します。当然のことながら、この実装の詳細に頼るのは気が進まないかもしれませんが、プログラムが終了しない別の理由を探す価値があるかもしれません。

で@kleopatraに延期する場合AncestorListener; それはあなたが望むように制御することを可能にするはずですTimer。コンポーネントアニメーションのデューティサイクルは一般的にかなり軽く、通常はレンダリングが主流です。コンポーネントが表示されていない場合、後者のオーバーヘッドは小さくなります。提案された最適化が努力の価値があることを確認するためにプロファイリングする価値があるかもしれません。WindowListenerその場合は、非アクティブまたはアイコン化されたウィンドウでのアクティビティを最小限に抑えることを検討してください。

補遺:現在削除されている回答はsetVisible()、タイマーを調整するためにオーバーライドすることを提案しました。表面的には魅力的ですが、アプローチはもろく、拡張性も低くなります。リスナーアプローチは、Swingアーキテクチャで一般的に使用されるオブザーバーパターンを活用します。

于 2012-09-16T14:38:48.740 に答える
1

シャットダウンを初期化するには、イベント キューを 1 秒間静止する必要があります。これは、AWTAutoShutdown クラスでハードコーディングされた値です。

そのため、swing タイマーが 1 秒未満の間隔でイベントを生成し続けると、アプリケーションが終了しなくなります。

この例を見てください (下)。スレッドはデーモンとしてマークされていても、イベントをキューに追加し続けるため、終了しません。スリープを 1500 (1.5 秒) に増やすと、問題なく終了します。

public static void main(String[] args)
{
    Thread thread = new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            while (true)
            {
                // Submit an empty event to the queue
                EventQueue.invokeLater(new Runnable()
                {
                    @Override
                    public void run()
                    {
                    }
                });
                try
                {
                    Thread.sleep(500);
                }
                catch (InterruptedException e)
                {
                    throw new IllegalStateException(e);
                }
            }
        }
    });
    thread.setDaemon(true);
    thread.start();
}
于 2013-07-02T06:40:15.413 に答える
1

次のようにします。

  private static final class DisplayabilityListener implements HierarchyListener {
  private final JComponent component;
  private final Timer timer;

  private DisplayabilityListener(JComponent component, Timer timer) {
     this.component = component;
     this.timer = timer;
  }

  @Override
  public void hierarchyChanged(HierarchyEvent e) {
     if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) > 0) {
        if (component.isDisplayable()) {
           timer.start();
        } else {
           timer.stop();
        }
     }
  }

}

于 2013-07-02T08:22:35.750 に答える