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 :

SwingWorker et JProgressBar


Sujet :

EDT/SwingWorker Java

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    décembre 2011
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : décembre 2011
    Messages : 94
    Points : 53
    Points
    53
    Par défaut SwingWorker et JProgressBar
    Bonjour à tous,

    j'essaye d'utiliser SwingWorker pour mettre à jour la valeur d'une barre de progression pendant un traitement mais rien ne bouge.
    Le traitement est lancé à l'aide d'un bouton sur l'écran (classe Ecran.java).

    Voici mon code :

    La classe représentant mon écran
    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
     
    public class Ecran extends JFrame
     
     public Ecran()
     {
          barreProgression = new JProgressBar();
          barreProgression.setBounds(20, 113, 403, 25);
          barreProgression.setVisible(false);
          barreProgression.setStringPainted(true);
          panel.add(barreProgression);
     
     
          bouton = new BJButton();
          bouton.setAction(getActionBouton());
          this.getPanelBas().addButton(bouton);
     
     }
     
    private Action getActionBouton()
    	{
    		Action actionSelection = new AbstractAction() 
    		{
    			public void actionPerformed(ActionEvent e) 
    			{
    				setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
     
    				int retourValConfirmationInj = controller.confirmerTraitement();
    				if(retourValConfirmationInj == JOptionPane.OK_OPTION)
    				{
    					afficherBarreProgression();
    					controller.actionBouton();
    				}
    			}
    		};
    		return actionSelection;
    	}
     
    public void afficherBarreProgression()
    {
         barreProgression.setVisible(true);
    }

    La classe liée à mon controller

    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
     
    public class Controller
    {
          public JFrame getEcran()
          {
                ecran = new Ecran();
                return ecran;
          }
     
          public void actionBouton()
         {
              SwingWorker sw = new SwingWorker()
    		{
                           protected Object doInBackground() throws Exception
    			{
                                   while(rowIterator.hasNext())
    					{
                                                    setProgress(pourcentageProgress);
                                             }
                            }
                    };
     
                    sw.addPropertyChangeListener(new PropertyChangeListener() 
    		{
     
                       public void propertyChange(PropertyChangeEvent evt) 
                       {
    		                if ("progress".equals(evt.getPropertyName())) 
    				{
    					ecran.getBarreProgression().setValue((Integer) evt.getNewValue());
     
                                            if((Integer)evt.getNewValue() == 100)
    					{
    						JOptionPane.showMessageDialog(getView(), "FIN", "", JOptionPane.INFORMATION_MESSAGE);
    					}
    				}
    			}
    		});
          }
    }
    Le message "FIN" dans mon JOptionPane s'affiche correctement mais la valeur de ma progressbar ne s'affiche pas.
    Je n'arrive pas à comprendre pourquoi la valeur ne se met pas à jour. Est-cu du au fait que mon ecran n'est pas construit dans l'EDT?

    Merci d'avance

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    septembre 2009
    Messages
    12 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2009
    Messages : 12 373
    Points : 29 307
    Points
    29 307
    Billets dans le blog
    2
    Par défaut
    Salut,

    Difficile de te répondre en l'état parce que ton code n'est pas complet (En l'état, vu le while(rowIterator.hasNext()) sans appeler next(), à priori, ça boucle à l'infini). Tu vois la barre de progression, mais tu ne la vois pas progresser, c'est çà ? Et si tu ajoutes un simple System.out.println de evt.getNewValue(), juste avant ecran.getBarreProgression().setValue((Integer) evt.getNewValue());, est-ce que tu vois différentes valeurs s'afficher ? Combien d'itération y-a-t'il ? Peut-être que ça va itère tellement vite que tu ne vois pas la progression ? Si c'est pour tester avant implémentation, tu peux mettre temporairement une tempo (un Thread.sleep()), pour voir que ça progresse bien...
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    décembre 2011
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : décembre 2011
    Messages : 94
    Points : 53
    Points
    53
    Par défaut
    Merci pour ta réponse.

    Le code n'est pas complet en effet, j'ai repris les parties impliquées dans la mise à jour de la barre de progression.

    Oui la barre de progression s'affiche bien mais ne progresse pas. Elle reste à 0% (sa valeur est initialisée avant le traitement).
    En mettant un System.out.println de evt.getNewValue(), je vois bien les différents pourcentages s'afficher. D'ailleurs quand mon traitement atteint 100%, ce code ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    JOptionPane.showMessageDialog(getView(), "FIN", "", JOptionPane.INFORMATION_MESSAGE);
    est correctement exécutée et s'affiche.

    J'ai testé avec un traitement ne provoquant qu'une itération dans la boucle et j'ai bien un seul passage dans propertyChange (property = progress)

    Merci.

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    septembre 2009
    Messages
    12 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2009
    Messages : 12 373
    Points : 29 307
    Points
    29 307
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par nddvlp Voir le message
    En mettant un System.out.println de evt.getNewValue(), je vois bien les différents pourcentages s'afficher. D'ailleurs quand mon traitement atteint 100%, ce code ci
    Au moins, ça veut bien dire que la progression est effective : le problème est donc au niveau de la progressbar elle-même. Si tu ajoutes (temporairement pour test) un ChangeListener à la progressBar, avec un simple System.out.println de l'evénement, obtiens-tu des évènements ? Par ailleurs, ta barre est-elle en indeterminate ou non ? Sinon, affectes-tu bien un maximum correspondant à ton nombre d'itérations (une valeur différente de minimum au moins) ?
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    décembre 2011
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : décembre 2011
    Messages : 94
    Points : 53
    Points
    53
    Par défaut
    J'ai testé en ajoutant un ChangeListener à ma barre et celle-ci reçoit bien un évènement.
    Ma barre n'est pas en indeterminate.

    J'ai affecté un min (0) et un max (100) à ma barre mais rien ne change.

    J'ai voulu testé la modification d'un label à la fin de mon traitement mais là aussi ça ne fonctionne pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     public void propertyChange(PropertyChangeEvent evt) 
     {
    		 if ("progress".equals(evt.getPropertyName())) 
    		{
    			ecran.getBarreProgression().setValue((Integer) evt.getNewValue());
     
                            if((Integer)evt.getNewValue() == 100)
    			{
    				JOptionPane.showMessageDialog(getView(), "FIN", "", JOptionPane.INFORMATION_MESSAGE);
                                    ecran.getLabelTest.setText("TEST");
    			}
    		}
    }
    Mon JOptionPane s'affiche mais mon label test ne se modifie pas.

  6. #6
    Membre du Club
    Homme Profil pro
    Inscrit en
    décembre 2011
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : décembre 2011
    Messages : 94
    Points : 53
    Points
    53
    Par défaut
    J'ai du nouveau...
    Je viens de tester ma fonction en retirant le code qui demande la confirmation d'exécution à l'utilisateur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int retourValConfirmationInj = controller.confirmerTraitement();
    if(retourValConfirmationInj == JOptionPane.OK_OPTION)
    {
     
    }
    et là ça fonctionne. Ma barre de progression se met à jour et mon label test aussi.

    La méthode confirmerTraitement() est la suivante :

    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
     
    public int confirmerInjection() 
    {
    		String[] choix = {"Continuer","Annuler"};
    		String msg =  "Voulez-vous exécuter ce traitement?";
     
    		int retourVal = JOptionPane.showOptionDialog(getView(), 
    				msg, 
    				"Confirmation", 
    				JOptionPane.YES_NO_OPTION,
    				JOptionPane.QUESTION_MESSAGE,
    				null,choix,choix[0]);
     
    		return retourVal;
    }
    Ce code s'exécute dans l'EDT. Faut-il l'exécuter ailleur que dans l'EDT?

  7. #7
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    septembre 2009
    Messages
    12 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2009
    Messages : 12 373
    Points : 29 307
    Points
    29 307
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par nddvlp Voir le message
    J'ai voulu testé la modification d'un label à la fin de mon traitement mais là aussi ça ne fonctionne pas :
    A part le fait que le conteneur de la progressBar (et du label) affiché n'est pas celui que tu modifies (donc si tu as instancié au moins 2 fois ce conteneur), je ne vois pas pourquoi tu n'as pas de mise à jour de l'affichage.

    Tu créés à priori la hiérarchie de conteneurs par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public JFrame getEcran()
          {
                ecran = new Ecran();
                return ecran;
          }
     [
    Cette méthode est-elle appelée plus d'une fois ? En fait, il ne faudrait jamais écrire une méthode comme ça, qui change un état et le retourne (en plus le nom est trompeur, car il suggère qu'on obtient toujours la même instance, alors que ce n'est pas le cas). Ecrit d'un côté des méthodes qui construisent l'interface (createEcran() par exemple) et d'autres part, soit tu fais un singleton qui permet d’accéder de partout à l'instance unique d'Ecran créée, soit, mieux, tu transmets au contrôleur l'instance :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Ecran ecran = new Ecran(); 
    Controlleur controlleur = new Controlleur(ecran); // ou toute autre classe externe ou interne à Ecran qui a besoin d'une référence vers ecran. 
     
    ... 
     
    ecran.setVisible(true);
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  8. #8
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    septembre 2009
    Messages
    12 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2009
    Messages : 12 373
    Points : 29 307
    Points
    29 307
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par nddvlp Voir le message
    J'ai du nouveau...
    Je viens de tester ma fonction en retirant le code qui demande la confirmation d'exécution à l'utilisateur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int retourValConfirmationInj = controller.confirmerTraitement();
    if(retourValConfirmationInj == JOptionPane.OK_OPTION)
    {
     
    }
    et là ça fonctionne. Ma barre de progression se met à jour et mon label test aussi.

    La méthode confirmerTraitement() est la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    public int confirmerInjection() 
    ...
    Ce code s'exécute dans l'EDT. Faut-il l'exécuter ailleur que dans l'EDT?
    Là, je comprends encore moins. Il suffit que tu supprimes le if pour que ça fonctionne ? Ça invalide mon hypothèse précédente.
    Encore si on voyait la barre remplie, sans voir les étapes intermédiaires, on pourrait en effet dire qu'il y a une exécution dans l'EDT qui devrait être faite en dehors.

    Quand tu dis "Ce code s'exécute dans l'EDT", tu parles d'une invocation explicite avec SwingUtilties ? Un invokeLater ou un invokeAndWait ? Parce que de fait une action de bouton SWING s'exécute dans l'EDT, et ça ne pose aucun problème d'y afficher un dialogue, et ce sans influence sur une éventuelle mise à jour fait en conséquence d'un thread. Si, effectivement, on avait une boucle dans l'EDT qui met à jour la barre de progression, on aurait un délai d'attente, avec toute l'UI figée, on ne verrait que la barre remplie à la fin de la boucle.

    En tout cas, là sans le code complet, ça va être difficile pour moi de voir exactement où est le problème.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    décembre 2011
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : décembre 2011
    Messages : 94
    Points : 53
    Points
    53
    Par défaut
    J'ai compris mon erreur.

    Comme tu l'as suggéré, le conteneur était instancié 2 fois (deux appels à getView()).
    En effet, dans l'affichage du dialogue de confirmation, j'utilise de nouveau la méthode getView() pour indiquer sur quel composant afficher la boite de dialogue.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    JOptionPane.showOptionDialog(getView(), 
    				msg, 
    				"Confirmation", 
    				JOptionPane.YES_NO_OPTION,
    				JOptionPane.QUESTION_MESSAGE,
    				null,choix,choix[0]);
    J'ai essayé en remplaçant getView() par null et ça fonctionne à présent.

    Du coup ça explique la raison pour laquelle ça fonctionnait quand j'ai enlevé le message de confirmation.
    Comme tu me l'as conseillé, je vais changer cette (mauvaise) méthode getView.

    Un tout grand merci pour ton aide !

+ 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, 16h49
  2. JProgressBar et Swingworker
    Par JaroBx dans le forum EDT/SwingWorker
    Réponses: 3
    Dernier message: 16/07/2010, 10h01
  3. Swingworker et JProgressBar
    Par Micke7 dans le forum EDT/SwingWorker
    Réponses: 1
    Dernier message: 08/12/2009, 12h02
  4. JProgressBar et Thread avec SwingWorker
    Par sebastien61 dans le forum EDT/SwingWorker
    Réponses: 5
    Dernier message: 13/05/2009, 17h08
  5. SwingWorker Thread et JProgressBar
    Par keub51 dans le forum EDT/SwingWorker
    Réponses: 8
    Dernier message: 13/02/2008, 16h52

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