[英]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.