SwingUtilities.invokeLater

La mia domanda è legata 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?

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

No, non se si è già nel thread di invio eventi (EDT), che è sempre il caso quando si risponde a eventi avviati dall’utente come clic e selezioni. (I metodi actionPerformsd ecc. Vengono sempre chiamati dall’EDT.)

Tuttavia, se non si è in EDT e si desidera eseguire gli aggiornamenti della GUI (se si desidera aggiornare la GUI da qualche thread del timer o da qualche thread di rete, ecc.), È necessario pianificare l’aggiornamento da eseguire dall’EDT . Ecco a cosa serve questo metodo.

Swing è fondamentalmente thread non sicuro. Vale a dire, 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, …).

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

Utilizzo di base per invokeLater()

  1. I metodi principali dovrebbero essere sempre racchiusi in invokeLater()

  2. Azione / evento ritardato (ma in modo asincrono) fino alla fine di EventQueue ,

  3. Se EDT non esiste allora devi creare un nuovo EDT usando invokeLater() . Puoi testarlo con if (SwingUtilities.isEventDispatchThread()) {...

  4. Esiste invokeAndWait() , ma fino ad oggi I (solo la mia vista) non riesce a trovare un motivo per usare invokeAndWait() invece di invokeLater() , tranne le modifiche difficili in GUI (JTree & JTable), ma solo con la sostanza L & F (eccellente per testare la coerenza degli eventi sull’EDT)

  5. Roba di base: concorrenza in Swing

  6. Tutti gli output delle attività in background devono essere racchiusi in invokeLater()

Ogni applicazione Swing ha almeno 2 thread:

  1. Il thread principale che esegue l’applicazione
  2. L’EDT (Event Dispatching Thread) è un thread che aggiorna l’interfaccia utente (quindi 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 dall’EDT.

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

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

Dovresti usare invokeLater() per visualizzare il JFrame principale di un’applicazione desktop (per 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à triggersto 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.

Tieni presente che questo thread è lo stesso thread che disegna frame, 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 intuitiva e aggiunge un codice apparentemente non necessario?

Non è necessario scrivere più codice rispetto alla visualizzazione dell’applicazione con invokeLater() + gli ascoltatori a cui sei interessato sul componente. Il resto è gestito da Swing.

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