2011-08-25 21 views
51

Mi pregunta está relacionada con SwingUtilities.invokeLater. ¿Cuándo debería usarlo? ¿Tengo que usar cada vez que necesito actualizar los componentes de la GUI? ¿Qué hace exactamente? ¿Hay alguna alternativa, ya que no suena intuitivo y agrega un código aparentemente innecesario?SwingUtilities.invokeLater

+2

Es el equivalente de 'Control.BeginInvoke'. – SLaks

+0

@SLaks ¿Eso significa que si tengo un hilo no tengo que usarlo? – FadelMS

+4

@FadelMS, ya que los marcos Swing genera un hilo propio (el EDT), siempre tendrá ese hilo. (* Usted * no tiene un "ciclo de chequeo de mensajes" que procesa los clics del usuario, etc. Entonces, ¿cómo se llaman los diversos métodos 'actionPerformed'? Por el EDT!) Entonces, cuando dice que tiene * uno * hilo, tendría que interpretarlo como * solo * tienes el EDT (es decir, arrojaste una GUI y caíste del borde del método principal). En ese caso, NO, usted * no necesitará * usar 'invokeLater'. Sin embargo, no podrá hacer ningún procesamiento de "fondo". Si lo hace, bloqueará completamente la GUI ... – aioobe

Respuesta

52

¿Tengo que usar cada vez que necesito actualizar los componentes de la GUI?

No, si ya se encuentra en el hilo de distribución de eventos (EDT), que es siempre el caso cuando se responde a eventos iniciados por el usuario, tales como clics y selecciones. (Los métodos actionPerformed etc, están siempre llamados por el EDT.)

Si eres No obstante en la EDT y quieres hacer cambios GUI (si desea actualizar la interfaz gráfica de usuario de un hilo temporizador, o desde algunos hilos de red, etc.), tendrá que programar la actualización que realizará el EDT. Para eso es este método.

Swing es básicamente inseguro de hilo. Es decir, toda la interacción con esa API debe realizarse en un único hilo (el EDT). Si necesita hacer actualizaciones de GUI desde otro hilo (hilo de temporizador, hilo de red, ...) necesita usar métodos como el que mencionó (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, ...).

+0

@ Jens: lo que significa que puedo prescindir de él si estoy en el mismo hilo (Swing) o haciendo cosas en tiempo de ejecución. – FadelMS

+1

Bueno, "o hacer cosas en tiempo de ejecución" no es muy preciso. Si haces cosas en tiempo de ejecución, por ejemplo, en un thread de temporizador, entonces no, no puedes prescindir de este tipo de métodos. – aioobe

+0

Gracias aioobe, lo tengo. – FadelMS

7

Cada aplicación Swing tiene al menos 2 hilos:

  1. El hilo principal que ejecuta la aplicación
  2. El EDT (Despacho de Eventos Thread) es un hilo que actualiza la interfaz de usuario (por lo que la interfaz de usuario no se congelará)

Si desea actualizar la interfaz de usuario, debe ejecutar el código dentro del EDT. Métodos como SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait le permiten ejecutar código mediante el EDT.

+0

simple y fácil de entender, gracias – Yahya

3

La mayoría de los eventos iniciados por el usuario (clics, teclado) ya estarán en el EDT, por lo que no tendrá que usar SwingUtilities para eso. Eso cubre una gran cantidad de casos, a excepción de su thread principal() y subprocesos de trabajo que actualizan el EDT.

+0

no más, _todos_ – kleopatra

+0

Bueno, un usuario podría actualizar un archivo que está siendo supervisado por un hilo que actualiza la GUI. –

+1

hmm ...eso no cuenta como un evento (directo, ahí es donde se cumple la regla) iniciado por el usuario: el usuario actualiza el archivo (dentro de swing, en EDT) y lo guarda (al hacer clic en un botón, en EDT), lo que desencadena un SO notificación de evento de actualización de archivo (fuera de balanceo, fuera de EDT), esa notificación llega al monitor (fuera de EDT) que es responsable de actualizar la GUI en EDT – kleopatra

7

Mi pregunta esta vez está relacionada con SwingUtilities.invokeLater: ¿Cuándo debería usarla?

Lo que es clave para comprender es que Java tiene un hilo separado (EDT) que maneja eventos relacionados con Swing.

Debe usar invokeLater() para mostrar el JFrame principal de una aplicación de escritorio (por ejemplo), en lugar de intentar hacerlo en el hilo actual. También creará el contexto para el cierre elegante de la aplicación más tarde.

Eso es todo para la mayoría de las aplicaciones.

¿Tengo que usar cada vez que necesito actualizar los componentes de la GUI? ¿Qué hace exactamente?

No.Si modifica un componente de la GUI, activará un evento que se registrará para su posterior envío por Swing. Si hay un oyente para este evento, el hilo EDT lo llamará en algún lugar en el futuro. No es necesario que use invokeLater(), simplemente configure sus oyentes en los componentes correctamente.

Tenga en cuenta que este hilo es el mismo hilo que dibuja marcos, etc ... en su pantalla. Por lo tanto, los oyentes no deben realizar tareas complejas/largas/intensivas en la CPU, de lo contrario su pantalla se congelará.

¿Existe una alternativa, ya que no suena intuitivo y agrega un código aparentemente innecesario?

No necesita escribir más código que mostrar su aplicación con invokeLater() + oyentes que le interesen en el componente. El resto lo maneja Swing.

12
Swing is single threaded and all changes to the GUI must be done on EDT 

básico de uso para invokeLater()

  1. métodos principales deben ser siempre envueltos en invokeLater()

  2. retardada (pero de forma asíncrona) de acción/evento al final de EventQueue,

  3. Si EDT no existe, entonces tiene que crear un EDT nuevo usando invokeLater(). Puede probarlo con if (SwingUtilities.isEventDispatchThread()) {...

  4. Existe invokeAndWait(), pero hasta hoy (sólo mi opinión) no puede encontrar una razón para usar en lugar de invokeAndWait()invokeLater(), salvo cambios de disco duro en interfaz gráfica de usuario (JTree & JTable), pero sólo con Substance L&F (excelente para las pruebas de consistencia de los acontecimientos en la EDT)

  5. materia básica: Concurrency in Swing

  6. toda la salida de las tareas de fondo debe ser envuelto en invokeLater()

Cuestiones relacionadas