2011-03-30 13 views
6

Tengo un script groovy simple que desde su hilo principal de ejecución necesita mostrar algunos cuadros de diálogo para el usuario.¿Cuál es el uso seguro de subprocesos (envío de eventos) para JOptionPane.showMessageDialog y swing.utils.invokeAndWait?

Mi conocimiento oscilación es limitada y oxidado, pero recuerdo haber leído acerca de la necesidad de tener cuidado de mantener las cosas GUI en el hilo de despacho de eventos (EDT).

Si acabo de llamar al método estático JOptionPane.showMessageDialog desde mi hilo principal, ¿estoy en lo correcto al asumir que esto violaría la práctica correcta de mantener cosas de GUI en el EDT?

Debería ser en realidad usando el método swing.utils.invokeAndWait tales como en el siguiente ejemplo de código?


void showHelloThereDialog() 
     throws Exception { 
    Runnable showModalDialog = new 
     Runnable() { 
     public void run() { 
      JOptionPane.showMessageDialog(
       myMainFrame, "Hello There"); 
     } 
    }; 
    SwingUtilities.invokeAndWait 
     (showModalDialog); 
} 

Ahora el no hacer nada para que los valores de algo que no sea un diálogo de mensaje disponibles después invokeAndWait completa anteriormente.

Es de suponer que el hecho de que los cierres '' maravilloso implementan Ejecutable hará para el código más simple que la anterior.

¿Se requiere invokeAndWait? Y si es así, ¿podría alguien dar un ejemplo de implementación correcta para obtener el resultado de algo así como un confirmDialog usando groovy?

+0

Si está escribiendo código Swing y está usando Groovy, debería echarle un vistazo a Griffon. –

+1

@Don Gracias por la sugerencia, estoy al tanto de Griffon y definitivamente es interesante. Por otro lado, es mucho más pesado de lo que necesito en este momento y también siento que quiero entender un poco mejor las tuercas y los tornillos antes de confiar en tanta "magia". La única documentación que realmente conozco es el MEAP "Griffon in Action" http://www.manning.com/almiray/. ¿Sabes si es bueno (o si otras fuentes son útiles)? –

Respuesta

4

Tome un vistazo a groovy.swing.SwingBuilder, que encapsula invokeAndWait y invokeLater. Su ejemplo se puede escribir como:

import groovy.swing.SwingBuilder 
import javax.swing.* 
import java.awt.* 

def swing = new SwingBuilder() 
def myMainFrame = new Frame() 

swing.edt { 
    JOptionPane.showMessageDialog(
     myMainFrame, "Hello There"); 
} 
5

Esto debería estar en el modo EDT invokeAndWait o invokeLater, son obligatorios. Usted puede saberlo ya que el código para JOptionPane.showMessageDialog eventualmente crea y modifica los componentes de Swing. A partir de Java 6, Sun dice que todas las manipulaciones de los componentes de Swing (ya sea que se hayan realizado o no) deben realizarse en el EDT.

http://download.oracle.com/javase/6/docs/api/javax/swing/package-summary.html

http://www.velocityreviews.com/forums/t707173-why-does-jdk-1-6-recommend-creating-swing-components-on-the-edt.html

8

Una llamada a uno de showXxxDialog JOptionPane 's() está bloqueando hasta que el usuario selecciona Aceptar/Cancelar/etc. En general, usted no pone tales insturctions de bloqueo lento en el subproceso de despacho de evento (EDT) como una regla, porque cada uno de los otros componentes de la GUI se congelará. Entonces, un instinto instintivo de no ponerlo en el EDT es bueno, pero también es incorrecto. El motivo es el indicado por otros, el método crea componentes GUI y esto siempre debe hacerse en el EDT. Pero, ¿y el bloqueo? Notarás que incluso si lo ejecutas en el EDT, funciona bien. La razón se encuentra dentro del código fuente. La clase JOptionPane crea un objeto de diálogo y luego llama a show() seguido de dispose(), el primero de los cuales es lo que bloquea el hilo. Si usted lee los comentarios (o javadoc), verá que dice lo siguiente acerca del método:

Si el diálogo es modal y no está visible, esta llamada no retorno hasta que el diálogo está oculto por llamando a hide o dispose. Es permisible para mostrar cuadros de diálogo modales del evento envío de hilo porque el conjunto de herramientas se asegurará de que otra bomba de evento se ejecuta mientras que el uno que invoca este método es bloqueado.

Por lo tanto, es perfectamente seguro ejecutar JOptionPane en el EDT a pesar de su bloqueo.Obviamente, es seguro llamar al método Dialog show() desde el EDT, pero no ocurre lo mismo con JOptionPane porque sus métodos crean componentes GUI, agregan escuchas, acceden a otros contenedores cuando son modales y bloquean la entrada a ellos, etc. Usted no quiere todo de esto hecho fuera del EDT porque no es seguro para subprocesos y podría haber problemas. Es cierto que nunca he visto problemas al usar JOptionPane en el EDT, por lo que las posibilidades parecen bajas, pero sin duda son posibles. Pasar un nulo para el contenedor del cuadro de diálogo y solo dar objetos inmutables (como String s) como argumentos a los campos reducirá significativamente (tal vez incluso eliminará por lo que sé) la posibilidad de que algo malo ocurra porque todos los componentes relevantes de la GUI son hecho y accedido dentro del mismo hilo mientras no son visibles. Pero, deberías estar a salvo y ponerlo en el EDT. No es tan difícil llamar al SwingUtilities.invokeAndWait().

+0

+1 para una respuesta agradable, bien razonada y exhaustiva –

Cuestiones relacionadas