2011-08-25 14 views
51

La mia domanda è relativa a SwingUtilities.invokeLater. Quando dovrei usarlo? Devo utilizzare ogni volta che ho bisogno di aggiornare i componenti della GUI? Cosa fa esattamente? Esiste un'alternativa perché non sembra intuitiva e aggiunge un codice apparentemente non necessario?SwingUtilities.invokeLater

+2

È l'equivalente di 'Control.BeginInvoke'. – SLaks

+0

@SLaks Significa che se ho un thread non devo usarlo? – FadelMS

+4

@FadelMS, poiché i framework Swing generano un thread (EDT), avrai sempre quel thread. (* Non * hai un "message-checking" -loop che elabora i click-utente ecc, giusto? Allora come vengono chiamati i vari metodi 'actionPerformed'? Per l'EDT!) Quindi quando dici di avere * uno * thread, dovrei interpretare questo come * solo * ha l'EDT (cioè, hai gettato una GUI e caduto dal limite del metodo principale). In tal caso, NO, * non * sarà necessario utilizzare 'invokeLater'. Tuttavia non sarà possibile eseguire alcuna elaborazione di "background". Se lo fai, bloccherai completamente la GUI ... – aioobe

risposta

52

Devo utilizzare ogni volta che ho bisogno di aggiornare i componenti della GUI?

No, se siete già sul filo evento dispatch (EDT), che è sempre il caso quando si risponde a utente iniziati gli eventi come i clic e selezioni. (I actionPerformed metodi, ecc, sono sempre chiamati dalla EDT.)

Se siete non sul EDT comunque e vuole fare aggiornamenti GUI (se si desidera aggiornare la GUI da qualche thread del timer, oppure da un po 'di thread di rete, ecc.), è necessario programmare l'aggiornamento che deve essere eseguito dall'EDT. Ecco a cosa serve questo metodo.

L'oscillazione è fondamentalmente non sicura. Ad esempio, tutte le interazioni con quell'API devono essere eseguite su un singolo thread (l'EDT). Se hai bisogno di fare gli aggiornamenti della GUI da un altro thread (thread del timer, thread di networking, ...) devi usare metodi come quello che hai citato (SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, ...).

+0

@ Jens: il che significa che posso farne a meno se sono sullo stesso thread (Swing) o faccio cose in fase di esecuzione. – FadelMS

+1

Bene, "o fare le cose in fase di esecuzione" non è molto preciso. Se fai cose in runtime, in, per esempio, in un thread del timer, allora no, non puoi fare a meno di questo tipo di metodi. – aioobe

+0

Grazie aioobe, capito. – FadelMS

7

Ogni applicazione swing ha almeno 2 filetti:

  1. Il thread principale che esegue l'applicazione
  2. L'EDT (Event Dispacciamento Thread) è un filo che aggiorna l'interfaccia utente (così l'interfaccia utente non si blocca).

Se si desidera aggiornare l'interfaccia utente, è necessario eseguire il codice all'interno dell'EDT. Metodi come SwingUtilities.invokeLater, SwingUtilities.invokeAndWait, EventQueue.invokeLater, EventQueue.invokeAndWait consentono di eseguire codice da EDT.

+0

semplice e facile da capire, grazie – Yahya

3

La maggior parte degli eventi avviati dall'utente (clic, tastiera) si troveranno già nell'EDT in modo da non dover utilizzare SwingUtilities per questo. Questo copre molti casi, ad eccezione del thread main() e dei thread worker che aggiornano l'EDT.

+0

non più, _all_ – kleopatra

+0

Bene, un utente può aggiornare un file che viene monitorato da un thread che aggiorna la GUI. –

+1

hmm ...che non conta come un evento avviato dall'utente (diretto, dove è la regola): l'utente aggiorna il file (all'interno di swing, su EDT) e lo salva (facendo clic su un pulsante, su EDT), che attiva un sistema operativo notifica di evento di aggiornamento file (fuori swing, fuori EDT), la notifica raggiunge il monitor (fuori EDT) che è responsabile dell'aggiornamento della GUI su EDT – kleopatra

7

La mia domanda questa volta è relativa a SwingUtilities.invokeLater: Quando dovrei usarlo?

La chiave per capire è che Java ha un thread separato (EDT) che gestisce gli eventi relativi allo Swing.

È necessario utilizzare invokeLater() per visualizzare l'JFrame principale di un'applicazione desktop (ad esempio), invece di provare a farlo nel thread corrente. Creerà inoltre il contesto per la chiusura graduale dell'applicazione in un secondo momento.

Questo è tutto per la maggior parte delle applicazioni.

Devo utilizzare ogni volta che ho bisogno di aggiornare i componenti della GUI? Cosa fa esattamente?

No.Se si modifica un componente della GUI, verrà attivato un evento registrato per la successiva spedizione da parte di Swing. Se c'è un listener per questo evento, il thread EDT lo chiamerà da qualche parte lungo la strada. Non è necessario utilizzare invokeLater(), è sufficiente impostare correttamente i listener sui componenti.

Ricordare che questo thread è lo stesso schema per il disegno di trame ecc. Sullo schermo. Quindi, gli ascoltatori non dovrebbero eseguire compiti complessi/lunghi/intensi della CPU, altrimenti lo schermo si bloccherà.

Esiste un'alternativa perché non sembra intuitivo e aggiunge codice apparentemente non necessario?

Non è necessario scrivere codice più che visualizzare l'applicazione con invokeLater() + ascoltatori a cui è interessato il componente. Il resto è gestito da Swing.

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

Utilizzo base per invokeLater()

  1. metodi principali dovrebbero essere sempre avvolti in invokeLater()

  2. in ritardo (ma in modo asincrono) azione/evento alla fine del EventQueue,

  3. Se EDT non esiste, è necessario creare un nuovo EDT utilizzando invokeLater(). È possibile verificare con if (SwingUtilities.isEventDispatchThread()) {...

  4. Esiste invokeAndWait(), ma fino ad oggi ho (solo mio punto di vista) non riesce a trovare un motivo per l'utilizzo di invokeAndWait() invece di invokeLater(), salvo modifiche duro nella GUI (JTree & JTable), ma solo con Substance L&F (eccellente per le prove di coerenza di eventi sul EDT)

  5. roba di base: Concurrency in Swing

  6. Tutto l'output da operazioni in background deve essere avvolto in invokeLater()

Problemi correlati