2011-12-31 10 views
10

Leí en alguna parte que para cualquier hilo que afecta a los elementos visuales de la interfaz gráfica de usuario debe ser corrió en la EDT usando SwingUtilities.invokeAndWait/invokeLaterutilizar SwingUtilies.invokeAndWait/invokeLater

Para una interfaz gráfica de usuario básico, es necesario poner algo como new SwingGUI().setVisible(true); en la línea del EDT usando invokeAndWait? Solo para mostrar?

¿Esto cuenta?

Respuesta

3

Sí, si tocas un objeto Swing tienes que hacerlo en el EDT. En la mayoría de los casos ya estás allí, pero si no, usa las clases SwingUtilities. La razón de esto es que las clases Swing no tienen múltiples subprocesos, por lo que es probable que cause problemas desagradables si accede a él en otros subprocesos. Y podría ser que setVisible() esté haciendo muchas cosas bajo las sábanas para hacer que algo se muestre (como volver a colocar las cosas). Es mejor estar a salvo.

+0

¿Cuándo no me estoy ejecutando bajo el EDT? Entonces, ¿a qué te refieres es que si hago un hilo para cambiar algo, debería ejecutarlo con uno de estos métodos, verdad? Pero no estoy haciendo otro hilo, solo estoy ejecutando el hilo predeterminado ¿no? Entonces, ¿no sería innecesario hacer setVisible en invokeAndWait? –

+2

Si lo está ejecutando en el subproceso "principal" (predeterminado), entonces * no * está en el EDT. – Darkhogg

+0

Eche un vistazo a los enlaces en la respuesta de @ Robin. El hilo principal no es lo mismo que el hilo EDT, pero a menudo el código que está ejecutando con Swing es código para manejar un evento y, por lo tanto, en el EDT. –

9

La respuesta corta a su pregunta es: sí, incluso llamar al setVisible debería ocurrir en el EDT. Para averiguar si el subproceso actual es la EDT, puede utilizar el método EventQueue#isDispatchThread

Algunos enlaces de referencia:

Editar: después leyendo los enlaces que proporcioné, parece que algunos de los artículos en el sitio de Oracle están desactualizados en el documento aún pueden crear componentes Swing en otro hilo. Hay un stackoverflow question en este que contiene algunas buenas respuestas y enlaces a blogs y artículos sobre la 'nueva' política (nueva como en algunos años)

-1

Todo lo que acceda a los objetos Swing debe hacerlo a través del hilo de envío del evento (EDT). Hay una pequeña excepción a esto (que mencionaré más adelante). El propósito del EDT es procesar cualquier evento que pueda ocurrir debido a IO (eventos de mouse y teclado). Gran parte del tiempo esto puede significar alterar el diseño de su GUI. Swing no fue desarrollado para ser seguro para subprocesos, lo que significa que si dos subprocesos intentan modificar el mismo componente al mismo tiempo, entonces puede terminar con una GUI corrupta. Como ya hay un hilo conocido para acceder a los componentes Swing (EDT), ningún otro hilo debe intentar modificarlos o incluso leer su estado.

Ahora, para el caso excepcional cuando puede manipular objetos Swing fuera del EDT. Antes de que los componentes se hayan vuelto visibles, no es posible que IO esté desencadenando eventos. Por lo tanto, el hilo principal puede configurar una GUI Swing y luego establecer un solo JFrame para que sea visible. Como ahora hay un marco visible, pueden ocurrir eventos de IO y el hilo principal no debe intentar modificar ningún otro componente de Swing. Solo debería usar esta opción para iniciar una GUI, y realmente solo con problemas de juguete.

Lo que estoy diciendo es que lo siguiente está bien y no causará problemas si solo estás jugando con cosas.

public static void main(String[] args) { 
    // create components 
    JFrame f = new JFrame(); 
    ... 

    // do layout and other bits of setup 


    // show gui to user 
    f.setVisible(true); 
} 
+3

-1: las reglas de enhebrado de balanceo se han actualizado. Debe acceder a todos los componentes en el EDT, incluso cuando no estén visibles. Ver http://stackoverflow.com/questions/491323/is-it-safe-to-construct-swing-awt-widgets-not-on-the-event-dispatch-thread/491377#491377 – Robin

0

Cualquier cosa que se llama desde su

public static void main(String[] agrs) { 

directamente (sin desove otro hilo o el uso de invokeLater) se ejecuta en el hilo principal.

El acceso a los objetos de la GUI con el hilo principal mientras que el EDT puede acceder a ellos (de forma simultánea) (que se desencadena por la entrada del usuario) puede causar problemas de enhebrado. Llamar a invokeLater hace que las tareas (ejecutables) se ejecuten en el EDT, impidiendo el acceso simultáneo por otras tareas EDT, es decir. botón presiona etc.

Si puede estar seguro de que el EDT no está ocupado (antes de que la primera ventana sea configurable Visible (verdadero)) puede acceder a la GUI desde el hilo principal. Si puede estar seguro de que el EDT no tiene ninguna referencia al componente en el que está trabajando (está fuera del alcance de EDT), es decir. antes de que se agregue a cualquier contenedor, puede acceder desde el hilo principal sin que el EDT acceda a él simultáneamente, ya que el EDT no tiene forma de alcanzarlo.

+0

No. Incluso no es visible aún, se debe acceder a una ventana desde EDT. Ver el comentario de Robin sobre la respuesta de Dunes. –