2012-09-16 27 views
7

Tengo un temporizador Swing (javax.swing.Timer) que se utiliza para realizar algunas animaciones dentro de un componente Swing personalizado.Parando un temporizador Swing cuando un componente está oculto

Sin embargo, esto está causando problemas, en particular, parece detener la finalización de la aplicación debido a la secuencia del temporizador en vivo incluso después de que se cierran todas las ventanas. También sería bueno evitar la sobrecarga de los temporizadores que se ejecutan en objetos ocultos cuando la animación no se puede ver.

Idealmente me gustaría hacer lo siguiente:

  • Detener el temporizador cuando el componente está oculto
  • de inicio del tiempo de nuevo cuando el componente se hace visible

Es esto posible hacer (en una forma segura de hilo, por supuesto!)

+4

hmm .. lo que está mal con un ancestorListener (que sería mi primer pensamiento)? – kleopatra

+0

O puede agregar un [ComponentListener] (http://docs.oracle.com/javase/7/docs/api/java/awt/event/ComponentListener.html) y agregar ** timer.start()/stop() dentro de sus métodos componentHidden (...) y componentShown (...) ** –

+1

@GagandeepBalin un componenteListener solo es un tipo de propertyChangeListener a la propiedad visible de un componente único, que no se cambia si fiun ancestro está oculto/mostrado. – kleopatra

Respuesta

5

Soy escéptico de su primera premisa: este simple counter-example muestra que unejecuciónno excluye EXIT_ON_CLOSE. El paquete privado, compartido javax.swing.TimerQueue inicia un hilo daemon, que permite Program Exit. Puede ser comprensiblemente reacio a confiar en este detalle de implementación, pero puede valer la pena buscar otra razón por la que su programa no puede salir.

Si difiere a @kleopatra en AncestorListener; debería permitirle controlar el Timer según lo desee. El ciclo de trabajo de una animación componente es bastante claro, y generalmente está dominado por el renderizado; la sobrecarga de este último es pequeña cuando el componente no es visible. Puede valer la pena evaluar si la optimización propuesta vale la pena. Si es así, considere un WindowListener para minimizar la actividad en una ventana inactiva o iconificada.

Adición: Una respuesta ahora eliminada sugirió anular setVisible() para condicionar el temporizador. Si bien es superficialmente atractivo, el enfoque es frágil y escasea pobremente. El enfoque de oyente aprovecha el observer pattern comúnmente utilizado en Swing architecture.

+0

Gracias, este enfoque funcionó bien (en realidad usé un HeirarchyListener para poder detectar algunos otros eventos, pero creo que el principio es el mismo). También creo que también tienes razón en los temporizadores, pero como dices, puede ser mejor no confiar en ese comportamiento. – mikera

+1

Como referencia, aquí hay un [ejemplo] relacionado (http://stackoverflow.com/q/10880326/230513) que compara los tres oyentes mencionados. – trashgod

1

La cola de eventos debe permanecer en silencio durante un segundo para que se inicie el apagado. Ese es un valor codificado en la clase AWTAutoShutdown.

Así que si su temporizador de oscilación sigue generando eventos, menos de un segundo de diferencia, eso evitaría que la aplicación finalice.

Mire este ejemplo (abajo). No terminaría, porque el hilo, aunque marcado como deamon, sigue agregando eventos a la cola. Si aumentamos el sueño a 1500 (1,5 segundos), terminaría felizmente.

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

lo hacemos de esta manera:

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

}

+0

Cambiaría el 'if ((x & y)> 0)' en 'if ((x & y)) = 0)', ya que no funcionará si 'y' tiene su MSB configurado. – Matthieu

Cuestiones relacionadas