2012-08-06 21 views
9

Tengo un par de preguntas con respecto a Swing y el uso de EDT para actualizaciones de la GUI. Acabo de empezar a leer sobre este tema, así que soy un principiante en esta área:Java Swing: se ejecuta en EDT

  1. ¿Qué operaciones se requieren para ejecutar en el EDT? Si no lo hacen, ¿es simplemente una excepción planteada?
  2. ¿Hay momentos específicos en los que realmente estamos en el EDT automáticamente?
  3. si programamos una tarea usando SingUtilities.invokeLater la ponemos en la cola actual de las tareas de actualización de la GUI ¿verdad?
  4. Creo que los accesos a la cola anterior están sincronizados, o se usa alguna colección concurrente, pero si programo dos tareas de actualización de la GUI, desde dos hilos de fondo, ¿es imposible decir cuál se agregará primero? Por ejemplo, si el Tema 1 FIRST envía una tarea para configurar el texto de un JLable en "sí", y luego, poco tiempo después, aparece el segundo hilo y envía la tarea de establecer ese valor a "no", ¿estamos seguros de que el resultado será "sí", o es simplemente una cuestión de cómo estas cosas están programadas por el sistema operativo?
  5. ¿Cómo exactamente el SwingWorker asegura que el método done() se ejecuta en EDT? Se establece el siguiente código:

    future = new FutureTask<T>(callable) { 
           @Override 
           protected void done() { 
            doneEDT(); 
            setState(StateValue.DONE); 
           } 
          }; 
    

así que me preguntaba si FutureTask alguna manera se asegura de que invokeLater se llama?

Gracias por todas sus respuestas.

Respuesta

14
  1. Una buena regla es que todas las operaciones (acceso/actualizaciones/...) deben ocurrir en la EDT. Hay algunas excepciones mencionadas en el javadoc (ciertos métodos de ciertas clases), pero son tan difíciles de recordar que es más fácil seguir el enfoque de "hacer todo en el EDT". No se plantearán excepciones (afortunadamente, JavaFX solucionó este inconveniente). Puede usar un RepaintManager personalizado para detectar la mayoría de estas violaciones: vea this article.
  2. Todo lo que el usuario active se maneja en el EDT. Por ejemplo, si el usuario hace clic en un botón, se llamará al actionPerformed del correspondiente Action o ActionListener en el EDT.
  3. Corregir
  4. Lo que programe primero se ejecutará primero. La llamada invokeLater simplemente agrega Runnable al final de la cola. Usando invokeLater una segunda vez un poco más tarde agregará este nuevo Runnable después del Runnable previamente programado.
  5. Tome un vistazo al código de doneEDT

    private void doneEDT() { 
        Runnable doDone = 
         new Runnable() { 
          public void run() { 
           done(); 
          } 
         }; 
        if (SwingUtilities.isEventDispatchThread()) { 
         doDone.run(); 
        } else { 
         doSubmit.add(doDone); 
        } 
    } 
    
+0

Dos preguntas: 4. Entonces, ¿es el primer hilo que se ejecuta más tarde? Entonces, ¿puede ser el caso que OS programe los segundos hilos de fondo invokeLater llame FIRST y la orden se arruine? 5. Todavía no veo cómo eso logra EDT. do Submit agrega Runnable to AcumulativeRunnable ... – Bober02

+0

@ Bober02 Vea el ejecutable javax.swing.SwingWorker.DoSubmitAccumulativeRunnable, que se ejecuta en el EDT debido al uso del Swing 'Timer'. Para 4: sí, deberá asegurarse de que su único hilo de fondo programe el ejecutable antes de que el otro hilo programe su ejecución si quiere controlar el pedido – Robin

+1

En algún momento, todo lo enviado a doSubmit() se ejecuta en el EDT. No tiene que importar cómo y dónde se hace: esta clase se ha probado y funciona como está documentado. –

-1

1. En aplicaciones GUI Java, main() método no se vive mucho tiempo, después de programar la construcción de interfaz gráfica de usuario en elEvent Dispatcher Thread, el método main()se cierra ... y ahora la responsabilidad de su EDT para manejar la interfaz gráfica de usuario.

2. Así que no necesitamos para comenzar nuestra aplicación en la EDT, su realiza automáticamente.

Mantenga siempre la UI trabajando en el subproceso de interfaz de usuario, y la No-UI funciona en el subproceso No-UI.

Mantiene siempre el hilo EDT, que es el hilo de la GUI solo para el trabajo de GUI.

Ej:

public static void main(String[] args){ 
    EventQueue.invokeLater(new Runnable(){ 
      public void run(){  
      myframe.setVisible(true); 
     } 
    } 
} 

4. crear un hilo no-UI separada de manejar que mucho tiempo teniendo método.

5. puede simplemente usar un Thread o utilizar SwingWorker que está especialmente introducido en Java para sincronizar la interfaz de usuario y la No-UI hilo.

6. SwingWorker no garantiza que el método done() se ejecute en EDT, pero sincronice la salida de este con el hilo EDT, que es el hilo de la GUI.

+2

Para su punto 6: véase la clase Javadoc de SwingWorker: Evento de Despacho Tema: Todas las actividades relacionadas con la oscilación se producen en este hilo. SwingWorker invoca los métodos process y done() y notifica cualquier PropertyChangeListeners en este hilo. – Robin

8
  1. Básicamente, cada vez que utilice un componente Swing o un modelo de un componente Swing, debe hacerlo en el EDT. Si no lo hace, no se generará ninguna excepción. Podría funcionar, pero tampoco podría funcionar, tener un comportamiento errático, datos corruptos, etc.
  2. Se llama a cada escucha de evento Swing en el EDT. Básicamente, excepto el método principal, cada línea de código de una aplicación Swing se ejecuta en el EDT de manera predeterminada, a menos que inicie explícitamente un hilo, use un SwingWorker, o algo así.
  3. sí.
  4. Las tareas enviadas a SwingUtilities.invokeLater() se ejecutan en el mismo orden en que se enviaron.
  5. Internamente, usa SwingUtilities.invokeLater() o un método similar. The FutureTask no tiene nada que ver con Swing. Es el SwingWorker que asegura que su método hecho se ejecuta en el EDT. El método doneEDT() tiene el siguiente comentario: Invoca realizado en el EDT.
0

SwingWorker asegurar que el método de hecho() se ejecuta en EDT través continuación Código:

Runnable doDone = 
     new Runnable() { 
      public void run() { 
       done(); 
      } 
     }; 
    if (SwingUtilities.isEventDispatchThread()) { 
     doDone.run(); 
    } else { 
     doSubmit.add(doDone); 
    } 

En realidad, añadir la variable Dodone en AccumulativeRunnable doSubmit,

Consulte el código fuente de AccumulativeRunnable.java que encontrarán allí tiene un código de abajo

protected void submit() {

SwingUtilities.invokeLater (this);

}

Por eso SwingWorker garantizar el método Fin() se ejecuta en EDT