Stop Swing timer when hiding component

I have a Swing timer ( javax.swing.Timer ) that is used to perform some animation in a custom Swing component.

However, this causes problems - in particular, it seems that the termination of the application ends due to the timer flow in real time even after closing all the windows. It would also be nice to avoid the overhead of timers running on hidden objects when the animation is not visible.

Ideally, I would like to do the following:

  • Stop timer when component is hidden
  • Start time again when the component becomes visible

Can this be done (in thread safe mode, of course!)

+7
source share
3 answers

I am skeptical of your first premise: this simple counter example shows that running javax.swing.Timer does not exclude EXIT_ON_CLOSE . The package is a private, generic javax.swing.TimerQueue launches a daemon thread that allows "Exit the program . " You may be reluctant to rely on this implementation detail, but maybe you should look for another reason why your program will not be able to exit.

If postpone to @kleopatra on AncestorListener ; It should allow you to control the Timer at will. The working cycle of component animation is typically fairly lightweight, and it usually predominates in rendering; Recent overheads are small when the component is not visible. It might be worth checking that the proposed optimization is worth the effort. If yes, consider a WindowListener to minimize activity in an inactive or displayed window.

Addendum: now the remote response suggested overriding setVisible() to set the timer. While superficially attractive, the approach is fragile and does not scale well. The listener approach uses the observer pattern commonly used in Swing architecture .

+5
source

The event queue must be silent for one second to initiate a shutdown. This is a hard-coded value in the AWTAutoShutdown class.

So, if your swing timer continues to generate events, less than seconds apart, this will lead to the termination of the application.

Take a look at this example (below). It will not be completed because the thread, even if it is marked as deamon, continues to add events to the queue. If we increase the sleep to 1,500 (1.5 seconds), it will end happily.

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

We do it like this:

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

}

+1
source

All Articles