繁体   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