2012-08-06 6 views
9

Ho un paio di domande riguardo a Swing e utilizzo di EDT per gli aggiornamenti della GUI. Ho appena iniziato a leggere su questa roba quindi sono un principiante assoluto in quest'area:Java Swing - in esecuzione su EDT

  1. Quali operazioni sono necessarie per l'esecuzione su EDT? Se non lo fanno, è semplicemente un'eccezione sollevata?
  2. Ci sono dei momenti specifici in cui siamo effettivamente nell'EDT automaticamente?
  3. se pianifichiamo un'attività utilizzando SingUtilities.invokeLater, la accodiamo alla coda corrente delle attività di aggiornamento della GUI, giusto?
  4. Gli accessi alla coda precedente sono sincronizzati o viene utilizzata una raccolta simultanea, ma se pianifico due attività di aggiornamento della GUI, da due thread in background, è impossibile stabilire quale verrà aggiunto per primo? Ad esempio, se Thread 1 FIRST invia un'attività di impostare il testo di un JLable su "sì", e quindi, poco tempo dopo, il secondo thread arriva e invia l'attività di impostare quel valore su "no", siamo sicuri che il risultato sarà "sì", o è semplicemente una questione di come queste cose sono programmate dal sistema operativo?
  5. In che modo esattamente SwingWorker garantisce che il metodo done() venga eseguito su EDT? Si imposta il codice seguente:

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

quindi mi chiedevo se FutureTask rende in qualche modo in modo che invokeLater si chiama?

Grazie per tutte le vostre risposte.

risposta

14
  1. Una buona regola è che tutte le operazioni (accesso/aggiornamenti/...) dovrebbero accadere sul EDT. Ci sono alcune eccezioni menzionate nel javadoc (certi metodi di certe classi), ma sono così difficili da ricordare che è più facile attenersi all'approccio 'fai tutto sull'EDT'. Non verranno sollevate eccezioni (per fortuna, JavaFX ha risolto questa lacuna). È possibile utilizzare un valore personalizzato RepaintManager per rilevare la maggior parte di queste violazioni: vedere this article.
  2. Tutto ciò che viene attivato dall'utente viene gestito sull'EDT. Ad esempio, se l'utente fa clic su un pulsante, il actionPerformed del corrispondente Action o ActionListener verrà chiamato sull'EDT.
  3. Corretto
  4. La cosa che si pianifica per prima verrà eseguita per prima. La chiamata invokeLater aggiunge semplicemente lo Runnable alla fine della coda. Utilizzando invokeLater una seconda volta un po 'più tardi si aggiungerà questo nuovo Runnable dopo il Runnable precedentemente programmato.
  5. Date un'occhiata al codice per doneEDT

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

Due domande: 4. Quindi è il primo thread che esegue invocare più tardi, giusto? Quindi può succedere che il sistema operativo pianifichi il secondo thread in background invocando la chiamata FIRST FIRST e l'ordine sarà incasinato? 5. Non riesco ancora a vedere come si raggiunge l'EDT. Invia Invia il Runnable a AccumulativeRunnable ... – Bober02

+0

@ Bober02 Vedere javax.swing.SwingWorker.DoSubmitAccumulative Runnable eseguibile, che viene eseguito sull'EDT a causa dell'uso del 'Timer' di swing. Per 4: sì, dovrai assicurarti che il tuo thread in background pianifichi il runnable prima che l'altro thread pianifichi il suo eseguibile se vuoi controllare l'ordine – Robin

+1

A un certo punto, tutto ciò che viene inviato a doSubmit() viene eseguito nell'EDT. Non devi preoccuparti di come e dove è stato fatto: questa classe è stata testata e funziona come documentato. –

-1

1. Nelle applicazioni Java GUI, main() metodo non è vissuto a lungo, dopo la pianificazione della costruzione della GUI nelEvent Dispatcher Thread, il metodo main()si chiude ... e ora la responsabilità del suo EDT per gestire l'interfaccia grafica.

2. Quindi non abbiamo bisogno di iniziare la nostra applicazione sul EDT, suo fatto automaticamente.

Mantenere sempre l'interfaccia utente attiva sul thread dell'interfaccia utente e l'interfaccia utente diversa sul thread non dell'interfaccia utente.

Quindi mantieni sempre il tuo thread EDT, che è il thread della GUI solo per la GUI.

Esempio:

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

4. Creare un separato filo non interfaccia utente per gestire quel lungo tempo prendendo metodo.

5. si può semplicemente utilizzare un Thread o utilizzare SwingWorker che è appositamente introdotto in Java per sincronizzare thread dell'interfaccia utente e Non-UI.

6. SwingWorker non garantisce che il metodo done() venga eseguito su EDT, ma sincronizzarne l'output su thread EDT, che è il thread della GUI.

+2

Per il vostro punto 6: vedere Classe javadoc di SwingWorker: Evento spedizione Discussione: Tutte le attività relative a battente si verificano su questo thread. SwingWorker richiama i metodi process e done() e notifica qualsiasi PropertyChangeListeners su questo thread. – Robin

8
  1. Fondamentalmente, ogni volta che si utilizza un componente Swing o un modello di un componente Swing, è necessario farlo nell'EDT. In caso contrario, non verrà sollevata alcuna eccezione. Potrebbe funzionare, ma potrebbe anche non funzionare, avere un comportamento irregolare, dati corrotti, ecc.
  2. Ogni listener di eventi Swing viene chiamato nell'EDT. Fondamentalmente, ad eccezione del metodo principale, ogni riga di codice di un'applicazione Swing viene eseguita in EDT per impostazione predefinita, a meno che non inizi esplicitamente un thread, usi uno SwingWorker o qualcosa del genere.
  3. sì.
  4. Le attività inviate a SwingUtilities.invokeLater() vengono eseguite nello stesso ordine dell'ordine in cui sono state inoltrate.
  5. Internamente utilizza SwingUtilities.invokeLater() o un metodo simile. Il FutureTask non ha nulla a che fare con Swing. È lo SwingWorker che garantisce che il suo metodo done sia eseguito nell'EDT. Il metodo doneEDT() ha il seguente commento: Invoca fatto sull'EDT.
0

SwingWorker assicurare che fatto() viene eseguito su EDT via sottostante Codice:

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

realtà aggiungere la variabile Dodone in AccumulativeRunnable doSubmit,

Vedere il codice sorgente di AccumulativeRunnable.java you troveranno ci deve un codice sotto

vuoto protetta submit() {

SwingUtilities.invokeLater (questo);

}

Ecco perché SwingWorker garantire il metodo fatto() in esecuzione su EDT