IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

EDT/SwingWorker Java Discussion :

JProgressBar et Thread avec SwingWorker


Sujet :

EDT/SwingWorker Java

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 5
    Points : 5
    Points
    5
    Par défaut JProgressBar et Thread avec SwingWorker
    Bonjour,

    Je suis débutant en multi-threading, je programme en Java.
    J'ai d'un coté 1 interface graphique, et d'autre coté un processus utilisateur. Dans l'interface graphique il y a 1 JProgressBar qui indique la progression du calcul utilisateur.

    Je me suis fortement inspiré de l'exemple suivant :
    http://rom.developpez.com/java-swingworker/

    Pour faire simple, j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    class MaClasse extends JPanel {
          public void okActionPerformed(ActionEvent e)
                MonSwingWorker sw = new MonSwingWorker();
                sw.execute();
     
                wait();
     
                // ici : le infos doivent etre collectées !
                Info informations = sw .getInformations();
     
                System.out.println(informations.size());
          }
     
         public class MonSwingWorker() extends SwingWorker {
               public void scan(fichier) // scan d'un fichier ligne par ligne
               {
                     for(int i=0 ; i<nbLigne ; i++)
                            setProgress(i/nbLigne);
               }
     
              protected Void doInBackground(){
                     scan(fichier);
                     notify();
              }
     
              protected void done() {// appelée à la fin
    		 System.out.println("Done");
              }
         }
    }
    Alors mon problème est qu'il faut que sw ai collecté toutes les infos du fichier avant de continuer. Si je ne mets pas de notify et wait , la tâche est trop longue et les infos n'ont pas le temps d'etre calculées (informations.size() = 0)

    Quand je mets notify et wait, la tâche calcule bien les info ("Done" affiché), mais le processus principal ne reprend pas la main (pas d'affichage de "informations.size()...". J'ai essayé avec un notifyAll(), mais le problème reste le même.

    Avez vous une idée d'ou cela peut provenir ? Ca ne doit pas etre hyper compliqué, mais ça m'échappe...
    J'ai trouvé pas mal de topic sur ce type de problème, mais peu sont dans le même cas que moi (parcours du fichier en entier indispensable pour poursuivre l'EDT)

    Merci d'avance pour votre aide.

  2. #2
    Membre régulier Avatar de DjGonk
    Profil pro
    Inscrit en
    Février 2007
    Messages
    88
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 88
    Points : 98
    Points
    98
    Par défaut
    Au lieu de wait, est ce que tu as essayer une boucle while?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    while(sw.isDone() == false){
          //TODO : A voir si tu fais un wait ou pas
          wait(10);
    }

  3. #3
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Je ne comprends pas vraiment ton problème.
    Si tu dois attendre que ton swingworker se termine pour utiliser tes Infos, pourquoi n'utilises tu pas la méthode done pour faire ton traitement dans l'EDT.
    C'est fait pour cela.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Tout d'abord merci pour vos réponses.

    @DjGonk : Oui j'avais essayé de faire ça, mais 2 cas surviennent :
    1 - Si je mets le wait dans le while : Exception levée (e.getMessage = null !)
    2 - Si je ne le mets pas, boucle infinie dans l'EDT et le swingWorker n'avance pas

    @fr1man : Quand tu dis "La méthode done" c'est celle de SwingWorker ? Il faut que je mette a jour la barre d'avancement. Pourrais tu me donner davantage de détails stp ?

    Désolé si je pose des questions idiotes... Merci d'avance en tout cas.

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Citation Envoyé par sebastien61 Voir le message
    Alors mon problème est qu'il faut que sw ai collecté toutes les infos du fichier avant de continuer. Si je ne mets pas de notify et wait , la tâche est trop longue et les infos n'ont pas le temps d'etre calculées (informations.size() = 0)

    Quand je mets notify et wait, la tâche calcule bien les info ("Done" affiché), mais le processus principal ne reprend pas la main (pas d'affichage de "informations.size()...". J'ai essayé avec un notifyAll(), mais le problème reste le même.
    Ton problème vient du fait que tu veux faire du traitement séquentiel, ce qui est une erreur en Swing (et avec la plupart des UIs évolué).

    Bien sûr tu vas me dire qu'ici tu utilises bien un thread et que donc tu es en parallèle et non pas en séquentiel...
    Le problème c'est que tu attends que le thread soit terminé pour continuer ton travail, donc cela revient à faire du séquentiel : a quoi te sert le thread puisque tu n'as pas de traitement en parallèle !!!



    La solution c'est de faire de l'évenementielle. Dans ton listener tu ne doit pas attendre la fin de la tâche. Tu dois juste te contenter de mettre à jour l'affichage avant le lancement de la tâche (par exemple grisé le bouton ou affiché une progress bar).

    Dans ton SwingWorker tu vas effectuer les traitements dans un nouveau thread, ce qui va permettre à l'EDT de continuer, de sortir du listener et de faire ce qu'il a a faire (mettre à jour l'affichage, traiter les autres evenements, ...)

    Enfin, lorsque ton traitement est terminé, tu peux mettre à jour l'affichage via la méthode done().


    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    class MaClasse extends JPanel {
     
    	public void okActionPerformed(ActionEvent e) {
     
    		// 1 - On est dans l'EDT
    		// => On peut mettre a jour l'affichage avant le début de la tâche
     
    		new SwingWorker<Info,Object>() {
    			@Override
    			protected Info doInBackground() throws Exception {
    				// 2 - On est dans un thread 'en tâche de fond'
    				// => On peut effecuter nos traitements lourds
     
    				// ...
    				scan(fichier);
     
    				return getInformations(); // et eventuellement renvoyer un résultat 
    			}
     
    			@Override
    			protected void done() {
    				// 3 - On est dans l'EDT, et le traitement est fini
    				// => On peut mettre à jour l'affichage avec les données
    				try {
    					// On récupère le résultat
    					Info result = get();
     
    					// Le traitement s'est bien passé
    					// On peut afficher les résultats dans l'interface graphique
     
    				} catch (InterruptedException e) {
    					// Le thread a été interrompu
    					// TODO
    				} catch (ExecutionException e) {
    					// La méthode doInBackground a généré une exception
    					// TODO
    				}
    			}
    		}.execute();
    	}
     
    }

    a++

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Ah ok, merci adiGuba, je viens de comprendre... Et ça marche !
    Je savais que c'était pas super approprié ce que j'avais fait, mais je croyais que c'était indispensable pour pouvoir mettre à jour la progressbar. (le découpage en classes)
    Ca fait un sacré bloc maintenant, mais bon du moment que ça marche...

    Merci beaucoup à tous en tout cas.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Souci avec SwingWorker et JProgressBar
    Par Niun dans le forum EDT/SwingWorker
    Réponses: 16
    Dernier message: 09/12/2011, 15h49
  2. thread avec wxworks
    Par moltes91 dans le forum wxWidgets
    Réponses: 12
    Dernier message: 08/04/2005, 14h56
  3. Thread avec C++
    Par pierrev1 dans le forum SDL
    Réponses: 3
    Dernier message: 18/03/2005, 13h59
  4. Thread avec une fonction membre d'une classe
    Par SteelBox dans le forum Windows
    Réponses: 6
    Dernier message: 01/03/2004, 01h15
  5. [VB6][active x] faire du multi-thread avec vb
    Par pecheur dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 20/05/2003, 12h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo