SwingUtilities.invokeLater () perché è necessario?

Perché è necessario inserire il codice di aggiornamento della GUI in SwingUtilities.invokeLater() ?

Perché non può essere curato internamente da Swing stesso? Perché il chiamante deve preoccuparsi di come Swing gestisce l’UI?

Gli oggetti Swing non sono thread-safe . SwingUtilities.invokeLater() consente di eseguire un’attività in un secondo momento, come suggerisce il nome; ma ancora più importante, l’attività verrà eseguita nel thread di invio eventi di AWT. Quando si utilizza invokeLater , l’attività viene eseguita in modo asincrono; c’è anche invokeAndWait , che non tornerà fino a quando l’attività non ha completato l’esecuzione.

Alcune informazioni sulla decisione di non rendere Swing thread-safe possono essere trovate qui: Toolkit multithread: Un sogno fallito?

Perché gli aggiornamenti della GUI devono essere eseguiti nel thread di invio dell’evento. Se stai operando in un thread diverso, facendo l’aggiornamento in invokeLater lo estrae dalla tua discussione e nel thread dell’evento.

Altre spiegazioni qui: http://www.oracle.com/technetwork/java/painting-140037.html

La cosa intelligente da fare con i grandi aggiornamenti (come ripopolare un JTable dal database) su Swing è ottenere il modello sottostante, fare gli aggiornamenti sul modello nel tuo thread, quindi invokeLater una notifica usando invokeLater . Ciò mantiene la tua gui rispondendo agli eventi e al ridisegno. Se l’aggiornamento sarà molto esteso, puoi persino invokeLater queste notifiche con invokeLater a intervalli regolari mentre invokeLater aggiornamento, ad esempio ogni due o due secondi.

Swing è single-threaded. Ogni aggiornamento dell’interfaccia utente deve avvenire dal cosiddetto EDT: il thread event-dispather che è il thread principale della GUI Swing (e penso che AWT) usi. Se non lo fai, allora le cose strane possono o accadrà (anche se mi piace Windows FOrms meglio qui che getta un’eccezione se fai qualcosa di sbagliato).

Detto questo, non è necessario avvolgere ogni singola operazione dell’interfaccia utente in SwingUtilities.invokeLater() – se il codice che stai scrivendo è già stato eseguito dall’EDT, questo non è necessario. Quindi ActionListener per un clic sul pulsante non ha bisogno di questo. Ma un listener su un object esterno, in esecuzione in qualche altro thread, che aggiorna una JLabel da qualche parte – lì ne hai bisogno.

Swing non è stato scritto per essere un toolkit GUI thread-safe, quindi tutti gli aggiornamenti della GUI dovrebbero essere eseguiti da un singolo thread per evitare deadlock. In Swing questo è il thread Dispatcher eventi (EDT).

Vedi Concurrent in Swing dal tutorial di Java per maggiori dettagli. Fa inoltre riferimento a questo articolo sul perché è difficile scrivere un toolkit GUI multithread.

Tutti i dipinti dei componenti devono essere eseguiti in un singolo thread, quindi sono resi correttamente. In questo modo il componente saprà, quale parte è già stata dipinta e quale parte non ha.

Se invochi un metodo correlato alla “pittura” (pittura, aggiornamento, paintComponent, show, setVisible, pack ecc.) Al di fuori dell’EDT, tenterai di dipingere in due thread diversi e questo potrebbe causare problemi.

Quando hai bisogno di usare un altro thread per aggiornare l’interfaccia utente, dovresti invocarlo con la funzione invokeLater, che a sua volta lo inserirà nell’EDT, quindi continuerai a dipingere nello stesso thread.

Non è necessario utilizzarlo, se si sta codificando in un metodo già eseguito in EDT (ad esempio, actionPerformsd o paint o uno di quelli) O se si sta eseguendo codice non correlato all’interfaccia utente (ad esempio, l’elaborazione dei file sullo sfondo ecc.)

Per comprendere meglio tutti questi concetti leggi: La regola del thread singolo

SwingUtilities.invokeLater ()

Cause doRun.run () da eseguire in modo asincrono nel thread di invio eventi AWT. Ciò accadrà dopo che tutti gli eventi AWT in sospeso sono stati elaborati. Questo metodo deve essere utilizzato quando un thread dell’applicazione deve aggiornare la GUI.

Ripetizione degli altri: Swing non è thread-safe, quindi un thread deve eseguire tutti gli aggiornamenti per evitare problemi di concorrenza. invokeLater è un metodo di utilità per eseguire qualcosa all’interno del thread di elaborazione degli eventi.

Perché Swing non lo fa internamente: questa è la mia impressione … penso perché sarebbe eccessivo – controllare ogni luogo in cui si sta verificando un aggiornamento. Sarebbe gonfiare il codice Swing, difficile la revisione e la manutenibilità del codice.

D’altra parte non è così difficile per un’applicazione sapere se non è in esecuzione all’interno del thread della GUI e chiamare invokeLater. Sarà quando la propria applicazione ha già avviato alcuni thread.