cherry ha scritto:
la prima parte della risposta non l'ho capita, ma non fa niente.
No ... questa è proprio una parte che
va capita bene!
cherry ha scritto:
In alternativa, creare un thread a parte, che però richiede altri accorgimenti.
E come si fa?
Creare un thread è facile ... non è quello il problema (tra l'altro dovresti già saperlo se arrivi a Swing). Il punto è che se in un thread che non è il EDT vuoi accedere alla interfaccia utente (qualunque set, get, add ecc... sui componenti), allora bisogna farlo nel modo corretto e con certi accorgimenti ... e ricadiamo proprio nella parte che "non hai capito". Quindi cercherò di dare una breve spiegazione.
Una applicazione Java può usare quanti thread vuole ma per la gestione della interfaccia utente il thread è uno solo, viene convenzionalmente chiamato EDT (Event Dispatch Thread). Questo thread viene creato e gestito dal framework (di questo non ci si deve preoccupare). Ma devi comunque sapere quali sono le implicazioni di tutto questo.
Il EDT si occupa di tutta la interfaccia utente, in particolare del disegno dei componenti Swing e del dispacciamento degli eventi (i vari XyzEvent) ai listener registrati sui componenti.
Tutti i paint/paintComponent dei componenti sono invocati nel contesto del EDT. Pure tutti i metodi dei listener ... actionPerformed, mouseClicked, keyPressed ecc... sono invocati nel contesto del EDT.
Il EDT gestisce una sua coda degli eventi, man mano che c'è qualcosa "da fare", lo toglie dalla coda e fa il necessario. In pratica è un grosso loop che continuamente e alternativamente disegna, dispaccia eventi, ecc... Sui moderni PC ovviamente è velocissimo ma è comunque un unico
flusso di esecuzione e pertanto fa
una sola cosa per volta.
Se sta invocando il actionPerformed di tuo listener ... non sta disegnando un componente ... e viceversa se sta eseguendo il paintComponent di un JButton non sta dispacciando un evento!
Se tu in un actionPerformed ti metti a fare lunghi loop, sleep di tot secondi e simili, lo stai tenendo impegnato e quindi il framework NON può fare altro, non può aggiornare componenti né dispacciare eventi.
E non è solo questo: Swing non è thread-safe, ovvero solo nel EDT puoi accedere in modo "sicuro" ai componenti e modificare la interfaccia utente. Nel contesto di altri thread
non dovresti farlo. Se lo fai e senza accorgimenti particolari, rischi dal non vedere modifiche fino alla potenziale corruzione di strutture dati o crash causati da eccezioni.
Ci sono poche operazioni (oltretutto ben documentate) che sono thread-safe e che puoi fare sulla interfaccia utente anche non dal EDT.
Swing insomma è single-thread. Ci sono ragioni storiche e anche di maggior semplicità per cui le interfacce utente sono in genere single-thread. Questo non è solo per Java/Swing ... vale anche in altri framework/sistemi. Anche Android usa il paradigma della UI single-thread.
Tutto questo cosa vuol dire? Che il thread della interfaccia utente (in qualunque modo si chiami per convenzione) NON lo devi mai tenere "impegnato" tu troppo a lungo. Fare sleep di secondi, query a database, ecc... in questo thread NON va bene.
Questo deve essere ben chiaro, se si vuole andare un po' lontano in Swing ...