Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2005
    Messaggi
    356

    Problemi con Thread.sleep()

    Salve a tutti,
    sto realizzando una piccola applicazione in java e ho problemi con il metodo thread.

    Dunque ad un certo punto dell'esecuzione, cliccando su un JPanel si attiva un metodo.
    Questo metodo fa le seguenti cose:

    1) fa alcune operazioni
    2) cambia l'imagine del JPanel
    3) aspetta 2 secondi (Thread.sleep(2000))
    4) cambia l'immagine di un secondo JPanel

    Il problema è che le operazioni non vengono eseguite così ma prima vengono fatte le operazioni, poi il thread si mette in attesa per 2 secondi e infine mi vengono cambiate le immagini praticamente contemporaneamente

    Ho provato poi a fare una prova, e ho messo, prima e dopo lo sleep() una stampa a video.

    Succede stampa prima la prima scritta, poi aspetta, stampa la seconda scritta, e poi cambia le immagini...
    Qualcuno saprebbe indicarmi il motivo? Cioè, perchè le immagini le cambia sempre alla fine?

    Grazie
    Jek
    Jekkil

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Problemi con Thread.sleep()

    Originariamente inviato da Jekkil
    Qualcuno saprebbe indicarmi il motivo?
    Solita questione (ormai discussa già in lungo e in largo sul forum) riguardo il threading in Swing.

    Concurrency in Swing
    Threads and Swing
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2005
    Messaggi
    356
    Ciao andbin,
    grazie mille per le guide.
    Se ho ben capito quindi, le modifiche dei componenti Swing sono effettuate in un thread diverso da quello del normale processo giusto? E se ho ben capito vengono lasciate alla fine. Ed è per questo che tutte le mie modifiche vengono fatte dopo tutte le altre operazioni, anche dopo la sleep. (ti prego correggimi se sbaglio)

    Prima che tu mi rispondessi però avevo risolto il problema invocando il metodo paintImmediately() subito dopo aver fatto la modifica al componente. e funziona...ma ora mi chiedo: è corretto?
    Jekkil

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Jekkil
    Se ho ben capito quindi, le modifiche dei componenti Swing sono effettuate in un thread diverso da quello del normale processo giusto?
    Ma cosa intendi per "normale processo"?? Perché così non dice un bel nulla ....

    Originariamente inviato da Jekkil
    E se ho ben capito vengono lasciate alla fine. Ed è per questo che tutte le mie modifiche vengono fatte dopo tutte le altre operazioni, anche dopo la sleep. (ti prego correggimi se sbaglio)
    Il succo è semplice: in una applicazione puoi avere quanti thread vuoi, ma per la gestione della interfaccia utente c'è 1 solo thread apposito (creato dal framework) chiamato convenzionalmente EDT (event dispatch thread). Questo thread si occupa di svariate cose, tra cui il "disegno" dei componenti Swing e il dispacciamento degli eventi (i metodi dei listener es. actionPerformed(), mousePressed() ecc... sono invocati nel contesto del EDT).
    È chiaro che essendo 1 thread solo .... fa tutto in modo "sequenziale", un po' disegna, un po' dispaccia eventi, ecc...
    Se tu nel contesto di un evento fai es.

    codice:
    label.setForeground(Color.RED);
    Thread.sleep(2000);
    label.setForeground(Color.BLACK);
    succedono 2 cose: intanto stai tenendo tu "impegnato" il EDT, quindi nessun altro disegno/evento può essere gestito (la tua interfaccia è "congelata" per quei 2 secondi) e poi comunque non "vedi" il cambiamento da rosso a nero. Perché i setForeground() non fanno nulla direttamente a video, cambiano solo la proprietà 'foreground' (una variabile) del componente e si limitano ad attivare un "flag" che dice "guarda che dovrà poi essere ridisegnata la label".

    Solo quando il controllo ritorna al framework, dopo che l'evento è terminato (il actionPerformed() o similare è terminato) allora scoprirà "ah, c'è la label da ridisegnare" e allora partirà tutta la sequenza di repaint, sempre nel contesto del EDT. Ma la proprietà foreground ormai è BLACK ... quindi non vedrai nessun rosso!

    Se hai capito questo, hai capito il succo di Swing.

    Originariamente inviato da Jekkil
    Prima che tu mi rispondessi però avevo risolto il problema invocando il metodo paintImmediately() subito dopo aver fatto la modifica al componente. e funziona...ma ora mi chiedo: è corretto?
    No, nonostante potrebbe funzionare non è comunque l'approccio più appropriato.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2005
    Messaggi
    356
    Perfetto! Ho capito tutto! Sei stato chiarissimo!

    Pero, se non è l'approccio più corretto allora qual'è la soluzione??


    P.S. Una domanda che non c'entra niente e di cui mi vergogno, ma non riesco a trovare la soluzione: sai come si fa su ubuntu e netbeans a fare in modo che una libreria sia vista automaticamente dall'ide senza doverla inserire ogni volta in ogni progetto?
    Jekkil

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Jekkil
    Pero, se non è l'approccio più corretto allora qual'è la soluzione??
    Usare un timer (javax.swing.Timer) o usare un thread a parte per elaborazioni "lunghe" (o sleep) facendo però in modo da accedere alla interfaccia utente solo nel EDT (il solito invokeLater() che probabilmente già conosci).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it
    Registrato dal
    Feb 2005
    Messaggi
    356
    mmm no non conosco...adesso me lo studio (naturalmente qualche dritta è ben accetta )

    grazie mille...

    ehm...riguardo all'altra piccola questioncina?
    Jekkil

  8. #8
    Utente di HTML.it
    Registrato dal
    Feb 2005
    Messaggi
    356
    Scusa un'altra domanda per capire meglio: cosa c'è di errato nell'usare il metodo paintImmediately()? Così ho un quadro preciso di tutto

    EDIT: per tenerti aggiornato: ho fatto una piccola modifica usando i timer...faccio in questo modo, quando clicco sul button avvio il timer e ad ogni interazione del timer faccio fare una serie di azioni diverse...
    In questo modo se è alla prima interazione (le conto) faccio alcune cose e poi la prima modifica alle swing, se è alla seconda faccio altre cose e poi la seconda modifica alle swing e poi blocco il timer.
    E' corretto così? perchè non mi convince troppo...
    Jekkil

  9. #9
    Utente di HTML.it
    Registrato dal
    Feb 2005
    Messaggi
    356
    Dunque ho provato per bene l'ultima soluzione pensata e devo dire che funziona senza intoppi...

    Resta solo il dubbio che sia corretta o no...però ci ho pensato un po' e non c'ho trovato controindicazioni...
    Jekkil

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.