簡體   English   中英

隱藏組件時停止Swing計時器

[英]Stopping a Swing timer when a component is hidden

我有一個Swing計時器( javax.swing.Timer ),用於在自定義Swing組件中執行一些動畫。

但是,這會導致問題 - 特別是它似乎會因為活動計時器線程停止應用程序終止,即使在所有窗口關閉后也是如此。 另外,當無法看到動畫時,避免計時器在隱藏對象上運行的開銷也會很好。

理想情況下,我想做以下事情:

  • 隱藏組件時停止計時器
  • 只要組件可見,就重新開始時間

這可能嗎(當然是以線程安全的方式!)

我對你的第一個前提持懷疑態度:這個簡單的反例表明運行javax.swing.Timer並不排除EXIT_ON_CLOSE package-private,共享javax.swing.TimerQueue啟動一個守護程序線程,允許程序退出 您可能不願意依賴此實現細節,但可能值得尋找程序無法退出的另一個原因。

如果在AncestorListener上推薦@kleopatra; 它應該允許您根據需要控制Timer 組件動畫的占空比通常相當輕,並且通常由渲染主導; 當組件不可見時,后者的開銷很小。 可能值得進行分析以驗證所提出的優化是值得的。 如果是這樣,請考慮使用WindowListener來最小化非活動或圖標化窗口中的活動。

附錄:現在刪除的答案建議覆蓋setVisible()來調節計時器。 雖然表面上很吸引人,但這種方法很脆弱,而且規模很小。 偵聽器方法利用Swing架構中常用的觀察器模式

事件隊列應該安靜一秒鍾,以便初始化關閉。 這是AWTAutoShutdown類中的硬編碼值。

因此,如果您的揮桿計時器持續生成事件,相隔不到一秒,這將使應用程序無法終止。

看看這個例子(下面)。 它不會終止,因為線程即使標記為deamon,也會不斷向隊列添加事件。 如果我們將睡眠時間增加到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();
}

我們這樣做:

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

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM