snake make how games game for code java swing animation timer

java - make - Detener un temporizador Swing cuando un componente está oculto



snake game java (3)

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

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
  • Comience nuevamente el tiempo cada vez que el componente se vuelva visible

¿Es esto posible (por supuesto, por un hilo seguro)?


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.

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

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


Lo hacemos así:

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

}


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

Si difiere a @kleopatra en AncestorListener ; debería permitirle controlar el Timer como 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 patrón de observador comúnmente utilizado en la arquitectura de Swing .