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

AWT/Swing Java Discussion :

Gestion des threads dans une application swing


Sujet :

AWT/Swing Java

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    205
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 205
    Points : 0
    Points
    0
    Par défaut Gestion des threads dans une application swing
    Je ne sais pas trop où poster ma question ???

    Bon je la pose ici pour le moment !


    Bon en fait c'est une appli Swing, qui a une JFrame et 3 sous JPanel par exemple (appelés screen dans mon exemple et screens, la liste de ces JPanel)

    Et donc chaque JPanel représente un tableau de bord qui contient une valeur qui doit être raffraichie, et je cherche à calculer dans la JFrame la somme de ces valeurs, mais avec les Threads je m'embrouille un peu aussi, y'a l'EDT, et swingWorker, mais j'ai fait autrement, même si apparemment c'est pas thread safe ...

    Voilà le code :
    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
     
    // RefreshALL et calcul
    		JButton refresh2 = new JButton("RefreshAll");
    		refresh2.addActionListener(new ActionListener(){
    			public void actionPerformed(ActionEvent e) {
    				new Thread(new Runnable(){
    					public void run(){
    						try {
    							for (int i = 0; i < screens.size(); i++) {
    								Thread.sleep(50);
    								System.out.println("	--Nom  "+i+" :" +screens.get(i).getNomValeur());
    								screens.get(i).getRefresh().doClick();
    								if (i==0){
    									somme = 0.00;
    								}
    								somme += Double.valueOf(screens.get(i).getScreenCas().get(0).getPerformance().getText());
    							} 
    							sommeTotale.setText("Somme Totale : " + somme);
    						} catch (InterruptedException e) {
    							e.printStackTrace();
    						}
    					}
    				}).start();	
    				add(sommeTotale);
    			}
    		});
    et le problème, c'est que si je clique plusieurs fois d'affilée sur le bouton "refreshALL" ben il me foire le calcul, à cause des thread qui se croise !

    C'est dans l'initialisation de la somme, ou j'en sais rien, si quelqu'un à une idée merci !

  2. #2
    Membre actif Avatar de Roy Miro
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    273
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 273
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    Pour le moment, je suppose que lorsque tu cliques sur "refresh all", tu créé un thread par screen qui va actualiser la valeur du screen. Tu as besoin de bloquer l'affichage de la somme jusqu'à ce que chacun de ces threads ait fini sa tâche.

    Tu as donc forcément 1 thread principal 'TP' et p-e n threads 't'(en supposant n screen).
    Tu pourrais créer un autre thread 'T' qui va, lui, créer les n thread t.

    Ensuite, TP va "joindre" T: Cela veut dire que, en supposant que TP récupère la somme totale pour l'afficher, il devra attendre que les n threads aient fini leur méthode run avant éventuellement d'actualiser son propre champ.

    Note: la somme totale peut-être représentée par un attribut sum de TP que tu passe à T qui lui va repasser aux t.

    Le problème dans ton code est que tu crééé un thread qui va s'exécuter de son côté (avec sa propre pile d'exécution), mais pendant ce temps ton code qui a créé le thread continue lui de s'exécuter jusqu'à atteindre et ce même si ton thread (qui vit sa vie à côté) n'a pas fini sa tâche.

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    205
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 205
    Points : 0
    Points
    0
    Par défaut


    Et il y a aussi le fait que en SWING, il y a l'histoire de l'EDT, qui normalement doit gérer tout, enfin, je m'attaquerais à sa plus tard !

    Donc je devrais faire hériter mes "screens" qui implémente JPanel, de Thread, ou Runnable ? ou un truc comme ca ?

    J'ai pas souvent programmé les THread, et je sais pas si c'est vraiment un système multithreadé que j'essaye de faire ...


    ET AUSSI, second problème, c'est que de la manière où j'ai programmé, je ne peux rien faire sur mes Threads, puisque je ne déclare pas d'instance :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    JButton refresh2 = new JButton("RefreshAll");
    		refresh2.addActionListener(new ActionListener(){
    			public void actionPerformed(ActionEvent e) {
    				new Thread(new Runnable(){
    					public void run(){
    						try {
    							for (int i = 0; i < screens.size(); i++) {
    								Thread.sleep(50);
     
    .............
    .............
    }
    				}).start();
    je peux faire qu'une action, donc faudrait que je déclare une variable, c'est tout genre Thread t = new Thread ?


    Car disons qu'avant que je Thread mes "refresh" dans chaque JPanel, ben le refresh des JPanel était freezé pendant le temps de la mise à jour et donc, il attendait bien que ce soit fini pour passer au suivant ... Enfin je sais pas si je suis clair, merci en tout cas tu semble avoir compris mon problème ...

    Ou alors je décompose les actions de cette manière :
    1°) je refresh tous mes screen
    2°) je vais chercher la valeur de chacun

    Car actuellement je fais :
    1°) je refresh un screen, et je prends sa valeur
    2°) je refresh un screen, et j'ajoute sa valeur
    ... etc

  4. #4
    Membre actif Avatar de Roy Miro
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    273
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 273
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    Si j'ai bien compris ton schéma, chacun de tes JPanel possède un bouton "maj". Chacun de ces boutons a sa méthode actionPerformed (comme tu as fait pour le refresh all).
    Pour un actionPerformed donné, tu as un code qui met à jour le JPanel auquel le bouton est lié. Donc quand tu clique sur ce bouton tu crééé un thread qui va mettre le JPanel à jour.
    Je te propose de sortir le code qui créé le thread de m.à.j de tes actionPerformed. Tu mets ce code dans une méthode à part. Puis tu appelles cette méthodes dans ton actionPerformed.
    Ensuite, dans le actionPerformed du refresh all, tu n'as plus qu'à appeler, pour chaque JPanel, cette méthode.

    Un exemple pour être plus clair:

    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
    public class MyPanel {
     
    private JPanel p;
    private JButton refresh;
    private String valeur;
     
    MyPanel(){
    ...
    refresh.addActionListener(new ActionListener(){
           public void actionPerformed(ActionEvent e) {
     
                     this.updatePanel();
           }
          });
           p.add(b);
    ...
    }
     
    void updatePanel(){
    //màj du panel
    MyRunnable myRunnable = new MyRunnable (valeur);
    Thread t = new Thread(myRunnable);
    }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class MyRunnable implements Runnable{
     
    private String stringToUpdate;
    MyRunnable (String s){
           this.stringToUpdate = s;
    }
     
    @Override
    public void run(){
         //aller chercher la nouvelle valeur et faire ce qu'il faut
          stringToUpdate = //nouvelle valeur
    }
    }
    Enfin, ta JFrame censé contenir tes MyPanel:
    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
     
    public class MyFrame {
     private JFrame f;
     private JButton refreshAll;
     private String somme;
     private MyPanel p1;
     private MyPanel p2;
     
     
    MyFrame(){
    ....
       refreshAll.addActionListener(new ActionListener(){
          public void actionPerformed(ActionEvent e) {
               Thread t = new Thread(new Runnable(){
                  public void run(){
                     update();
               }
             }});
    ...
    }
     
    void update(){
             p1.updatePanel();
             p2.updatePanel();
    }
     
    }
    Pour ne pas freezer quand tu cliques sur "refresh all", tu peux faire appel à l'EDT au niveau du actionPerformed du "refresh all" ou y créer un nouveau thread qui va appeler les updatePanel()

    Dis le si qqch n'est pas clair.

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    205
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 205
    Points : 0
    Points
    0
    Par défaut
    Salut, et merci pour ta réponse.

    Oui, je pense que c'est la solution à adopter, ca ordonnera un peu mieux les choses, bon là j'ai pas le temps, mais quand j'aurais essayé, je ferais un retour !


    Merci !

  6. #6
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    205
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 205
    Points : 0
    Points
    0
    Par défaut
    Bonsoir,

    Donc, je viens d'effectuer les modifications et ca fonctionne un peu mieux !

    Je suppose que tu avais omis, les Thread.Start(), après la création des Thread dans tes exemples de codes...

    Le souci, c'est que au premier coup que je clique "refresh All, il me calcul la "somme totale" et me donne Zéro "0.00", donc ca c'est car mes Thread ont pas encore mis la valeur à jour, et donc que toutes les valeurs de chacun de mes panels est initialisé à 0.00 et au 2ème coup, il me calcul la somme exacte ... Et le problème de si je clique à répétition qu'il me donne une somme fausse, ne se présente plus !


    Pour le "0.00" ca revient à ce que je disais au post précédents :

    Ou alors je décompose les actions de cette manière :
    I/1°) je refresh tous mes screen
    2°) je vais chercher la valeur de chacun

    Car actuellement je fais :
    II/1°) je refresh un screen, et je prends sa valeur
    2°) je refresh le screen suivant, et j'ajoute sa valeur
    ... etc


    code du refreshAll sur Jframe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Update Panels
    	public void updatePanels(){
    		somme = 0.00;
    		for (int i = 0; i < screens.size(); i++) {
    			System.out.println("	--Nom  "+i+" :" +screens.get(i).getNom());
    			screens.get(i).updatePanel();
    			somme += Double.valueOf(screens.get(i).getScreenCas().get(0).getPerformance().getText());
    		} 
    		sommeTotale.setText("Somme Totale : " + somme);
    		add(sommeTotale);
    	}
    Le problème c'est qu'avec ce code, je ne vois pas le programme appuyé sur les boutons refresh de chaque panel, car j'utilise "update", bon c'est pas nécéssaire, mais ca donnait un rendu visuel qui montrait que les valeurs avaient été mises à jours et donc si je remplace dans le code précédents :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Ca :
    screens.get(i).updatePanel();
     
    Par ca :
    screens.get(i).GetRefresh2().DoCLick();
    Ben j'ai le rendu visuel, mais il me fait les mêmes erreurs qu'avant si je clique plusieurs fois sur le refresh ALL !

    Pourtant le code de mes Refresh des Jpanel est :
    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
     
    //Refresh2
    		refresh2 = new JButton("Refresh2");
    		refresh2.addActionListener(new ActionListener(){
    			public void actionPerformed(ActionEvent e) {
    				updatePanel();
    			}
    		});
    		add(refresh2);
     
     
    // UPDATE 
    	public void updatePanel(){
    		MyRunnable my = new MyRunnable(valeur, connector, this);
    		Thread t = new Thread(my);
    		t.start();
    	}
    Pourtant, tout ce que je fais de plus, c'est faire appel au bouton, qui lui même fait appel à updatePanel() !

  7. #7
    Membre actif Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Points : 275
    Points
    275
    Par défaut ThreadsDemo
    Salut MaxLaMenaX,

    ce petit exemple pourrait t'aider:
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
     
    package threads;
     
    import java.awt.*;
    import java.awt.event.*;
    import java.util.*;
    import java.util.concurrent.*;
    import java.util.logging.*;
    import javax.swing.*;
     
    /**
     *
     * @author André Uhres
     */
    public class ThreadsDemo extends JFrame {
     
        private JButton btRefresh1, btRefresh2, btRefresh3, btRefreshAll;
        private JLabel jLabel1, jLabel2, jLabel3, lbSum;
        private JPanel jPanel1, jPanel2, jPanel3;
        private final Random r = new Random();
        private SwingWorker<Integer, Object> thread1, thread2, thread3;
        private SwingWorker<Void, Void> threadSum;
        private CountDownLatch latch;
     
        public ThreadsDemo() {
            btRefreshAll = new JButton();
            jPanel1 = new JPanel();
            btRefresh1 = new JButton();
            jLabel1 = new JLabel();
            jPanel2 = new JPanel();
            btRefresh2 = new JButton();
            jLabel2 = new JLabel();
            jPanel3 = new JPanel();
            btRefresh3 = new JButton();
            jLabel3 = new JLabel();
            lbSum = new JLabel();
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setTitle("ThreadDemo");
            getContentPane().setLayout(new GridLayout(0, 1));
            btRefreshAll.setText("Refresh all and calculate sum");
            btRefreshAll.addActionListener(new ActionListener() {
     
                @Override
                public void actionPerformed(ActionEvent evt) {
                    btRefreshAllActionPerformed(evt);
                }
            });
            getContentPane().add(btRefreshAll);
            jPanel1.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
            btRefresh1.setText("Refresh");
            btRefresh1.addActionListener(new ActionListener() {
     
                @Override
                public void actionPerformed(final ActionEvent evt) {
                    btRefresh1ActionPerformed(evt);
                }
            });
            jPanel1.add(btRefresh1);
     
            jLabel1.setText("0");
            jLabel1.setPreferredSize(new Dimension(100, 14));
            jPanel1.add(jLabel1);
            getContentPane().add(jPanel1);
            jPanel2.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
            btRefresh2.setText("Refresh");
            btRefresh2.addActionListener(new ActionListener() {
     
                @Override
                public void actionPerformed(final ActionEvent evt) {
                    btRefresh2ActionPerformed(evt);
                }
            });
            jPanel2.add(btRefresh2);
            jLabel2.setText("0");
            jLabel2.setPreferredSize(new Dimension(100, 14));
            jPanel2.add(jLabel2);
            getContentPane().add(jPanel2);
            jPanel3.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
            btRefresh3.setText("Refresh");
            btRefresh3.addActionListener(new ActionListener() {
     
                @Override
                public void actionPerformed(final ActionEvent evt) {
                    btRefresh3ActionPerformed(evt);
                }
            });
            jPanel3.add(btRefresh3);
            jLabel3.setText("0");
            jLabel3.setPreferredSize(new Dimension(100, 14));
            jPanel3.add(jLabel3);
            getContentPane().add(jPanel3);
            lbSum.setBackground(new Color(255, 255, 204));
            lbSum.setText("sum = 0");
            lbSum.setOpaque(true);
            getContentPane().add(lbSum);
            setSize(400, 300);
            setLocationRelativeTo(null);
        }
     
        private void btRefreshAllActionPerformed(final ActionEvent evt) {
            btRefreshAll.setEnabled(false);
            threadSum = new SwingWorker<Void, Void>() {
     
                @Override
                protected Void doInBackground() throws Exception {
                    latch = new CountDownLatch(3);
                    btRefresh1.doClick();
                    btRefresh2.doClick();
                    btRefresh3.doClick();
                    latch.await();
                    return null;
                }
     
                @Override
                protected void done() {
                    int sum = Integer.parseInt(jLabel1.getText());
                    sum += Integer.parseInt(jLabel2.getText());
                    sum += Integer.parseInt(jLabel3.getText());
                    lbSum.setText("sum = " + String.valueOf(sum));
                    btRefreshAll.setEnabled(true);
                }
            };
            threadSum.execute();
        }
     
        private void btRefresh1ActionPerformed(final ActionEvent evt) {
            update(thread1, jLabel1);
     
        }
     
        private void btRefresh2ActionPerformed(final ActionEvent evt) {
            update(thread2, jLabel2);
        }
     
        private void btRefresh3ActionPerformed(final ActionEvent evt) {
            update(thread3, jLabel3);
        }
     
        private void update(SwingWorker<Integer, Object> thread, final JLabel label) {
            if (thread == null || thread.isDone()) {
                thread = new RefreshWorker(10, label);
                thread.execute();
            }
     
        }
     
        public static void main(final String args[]) {
            SwingUtilities.invokeLater(new Runnable() {
     
                @Override
                public void run() {
                    new ThreadsDemo().setVisible(true);
                }
            });
        }
     
        private class RefreshWorker extends SwingWorker<Integer, Object> {
     
            private final int maxNum;
            private final JLabel label;
     
            public RefreshWorker(final int maxNum, final JLabel label) {
                this.maxNum = maxNum;
                this.label = label;
            }
     
            @Override
            protected Integer doInBackground() throws Exception {
                int num = r.nextInt(maxNum);
                return num;
            }
     
            @Override
            protected void done() {
                try {
                    int num = get();
                    label.setText(String.valueOf(num));
                } catch (InterruptedException ex) {
                    Logger.getLogger(ThreadsDemo.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ExecutionException ex) {
                    Logger.getLogger(ThreadsDemo.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    if (latch != null) {
                        latch.countDown();
                    }
                }
            }
        }
    }
    Salutations,
    André

  8. #8
    Membre actif Avatar de Roy Miro
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    273
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 273
    Points : 290
    Points
    290
    Par défaut
    Citation Envoyé par MaxLaMenaX Voir le message
    Pourtant, tout ce que je fais de plus, c'est faire appel au bouton, qui lui même fait appel à updatePanel() !
    Pourrais-tu poster le code de ta méthode DoClick()?
    Citation Envoyé par MaxLaMenaX Voir le message
    Ou alors je décompose les actions de cette manière :
    I/1°) je refresh tous mes screen
    2°) je vais chercher la valeur de chacun

    Car actuellement je fais :
    II/1°) je refresh un screen, et je prends sa valeur
    2°) je refresh le screen suivant, et j'ajoute sa valeur
    ... etc
    Pour faire I, tu peux revenir vers mon premier post avec Thread.join()

    Pour II, le souci est que tu refresh les panels individuellement (pour chacun tu as crééé un thread dans l'actionPerformed). Or tu n'as aucune garantie que les threads agissent de manière ordonnée: la méthode run du thread principal (qui màj ta JFrame) peut se finir avant que les run des screens aient fini leur tâche donc tu risques d'avoir un total erroné.

    N'oublie pas que 2 threads distincts peuvent être vus comme 2 programmes s'exécutant parallèlement.

  9. #9
    Membre actif Avatar de uhrand
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2009
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 203
    Points : 275
    Points
    275
    Par défaut
    Citation Envoyé par Roy Miro Voir le message
    Pour faire I, tu peux revenir vers mon premier post avec Thread.join()
    Salut Roy Miro,

    la classe "CountDownLatch" nous permet de coordonner le démarrage et l'arrêt des threads. De cette manière nous pouvons attendre la fin de plusieurs threads, alors que la méthode Thread.join() nous permet uniquement l'attente pour un seul thread.

    Salutations,
    André

  10. #10
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    205
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 205
    Points : 0
    Points
    0
    Par défaut
    Salut, et Merci à tous deux.

    Envoyé par MaxLaMenaX Voir le message
    Pourtant, tout ce que je fais de plus, c'est faire appel au bouton, qui lui même fait appel à updatePanel() !
    Pourrais-tu poster le code de ta méthode DoClick()?
    JButton hérite de AbstractButton qui fournit la méthode DoClick()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    doClick
     
    public void doClick()
     
        Programmatically perform a "click". This does the same thing as if the user had pressed and released the button.
    et donc cette fonction fait appel au actionPerformed() de Refresh2, dont j'ai posté le code, un post un peu plus haut

    Salut MaxLaMenaX,

    ce petit exemple pourrait t'aider:
    Merci, je vais essayer de comprendre comment fonctionne CountDownLatch()


    Ayé, je viens de tester ...



    Bon, oui c'est exactement ce que je cherche à faire, sauf que ma fonction de mise à jours de la valeur du JLabel dure environ 3 secondes, alors que là c'est un Random donc c'est très court...

    Et il y a juste ce petit problème de rendu visuel dont j'ai posté l'image, qui freeze un Button lorsque l'on test plusieurs fois de suite. Peut être qu'un Thread.Sleep(50) entre chaque rafraichissement devrait le régler ?

    Et, la seule différence dans mon architecture, c'est que l'on peut ajouter des JPanel à l'infini sur la JFrame, c'est pour cela que j'utilise screens dans mon code qui est une liste de JPanel...

    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
     
     @Override
                protected Void doInBackground() throws Exception {
                    latch = new CountDownLatch(3);
                    btRefresh1.doClick();
                    btRefresh2.doClick();
                    btRefresh3.doClick();
                    latch.await();
                    return null;
                }
     
                @Override
                protected void done() {
                    int sum = Integer.parseInt(jLabel1.getText());
                    sum += Integer.parseInt(jLabel2.getText());
                    sum += Integer.parseInt(jLabel3.getText());
                    lbSum.setText("sum = " + String.valueOf(sum));
                    btRefreshAll.setEnabled(true);
                }
    et donc dans ces deux fonctions, il faut que je fasse une boucle, plutôt que de coder de manière statique et séquentielle ! (et je ne me demande, si ce n'est pas là d'où vient le problème)

    Et aussi dans un dernier temps, ce que je voudrais, c'est que cela me refresh (tous les JPanels de ma JFrame et me calcule la somme à intervalle de temps régulier paramètrable. Et que je puisse l'arrêter quand je le souhaite.
    Au début j'avais utilisé une boucle infini avec un booleén pour en sortir, mais c'était un peu de la bidouille et ca ne fonctionnait pas très bien.

    Je ne sais pas si je vais devoir utiliser un Timer ou un Deamon ? (qui fera appel au rfershALL à interval régulier de temps)

    J'adapte à mon code et je feed back, merci.

  11. #11
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    205
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 205
    Points : 0
    Points
    0
    Par défaut
    Bon premièrement, j'ai essayé d'externaliser une classe Screen héritant de JPanel afin de pouvoir créer des JPanel Dynamiquement à partir de l'exemple que m'a donné uhrand ce qui me donne les deux classes suivantes :

    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Random;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutionException;
     
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingWorker;
     
    public class Screen extends JPanel{
    	private static final long serialVersionUID = 1L;
    	private JButton btRefresh;
    	private JLabel jLabel;
    	private SwingWorker<Integer, Object> thread;
    	private final Random r = new Random();
    	private CountDownLatch latch;
     
    	public Screen(JFrame j){
    		super();
    		btRefresh = new JButton("Refresh");
    		btRefresh.addActionListener(new ActionListener() {
    			@Override
    			public void actionPerformed(final ActionEvent evt) {
    				btRefreshActionPerformed(evt);
    			}
    		});
     
    		add(btRefresh);
    		jLabel = new JLabel("0");
    		add(jLabel);
    		j.add(this);
    	}
     
    	protected void btRefreshActionPerformed(ActionEvent evt) {
    		update(thread, jLabel);
    	}
     
    	private void update(SwingWorker<Integer, Object> thread, JLabel jLabel) {
    		if (thread == null || thread.isDone()) {
    			thread = new RefreshWorker(10, jLabel);
    			thread.execute();
    		}
    	}
     
    	private class RefreshWorker extends SwingWorker<Integer, Object> {
     
    		private final int maxNum;
    		private final JLabel label;
     
    		public RefreshWorker(final int maxNum, final JLabel label) {
    			this.maxNum = maxNum;
    			this.label = label;
    		}
     
    		@Override
    		protected Integer doInBackground() throws Exception {
    			int num = r.nextInt(maxNum);
    			return num;
    		}
     
    		@Override
    		protected void done() {
    			try {
    				int num = get();
    				label.setText(String.valueOf(num));
    			} catch (InterruptedException ex) {
    				// Logger.getLogger(ThreadsDemo.class.getName()).log(Level.SEVERE, null, ex);
    			} catch (ExecutionException ex) {
    				//Logger.getLogger(ThreadsDemo.class.getName()).log(Level.SEVERE, null, ex);
    			} finally {
    				if (latch != null) {
    					latch.countDown();
    				}
    			}
    		}
    	}
     
    	// Getter & Getter
    	public JButton getBtRefresh() {
    		return btRefresh;
    	}
    	public void setBtRefresh(JButton btRefresh) {
    		this.btRefresh = btRefresh;
    	}
     
    	public JLabel getjLabel() {
    		return jLabel;
    	}
    	public void setjLabel(JLabel jLabel) {
    		this.jLabel = jLabel;
    	}	
    }
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    import java.awt.Color;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.CountDownLatch;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    import javax.swing.WindowConstants;
     
    public class ThreadsDemo2 extends JFrame {
     
    	private JButton btRefreshAll;
    	private JLabel lbSum;
    	private final Random r = new Random();
    	private SwingWorker<Void, Void> threadSum;
    	private CountDownLatch latch;
    	private List<Screen> screens;
     
    	public ThreadsDemo2() {
    		btRefreshAll = new JButton();
    		lbSum = new JLabel();
    		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    		setTitle("ThreadDemo");
    		getContentPane().setLayout(new GridLayout(0, 1));
    		btRefreshAll.setText("Refresh all and calculate sum");
    		btRefreshAll.addActionListener(new ActionListener() {
     
    			@Override
    			public void actionPerformed(ActionEvent evt) {
    				btRefreshAllActionPerformed(evt);
    			}
    		});
    		getContentPane().add(btRefreshAll);
     
    		lbSum.setBackground(new Color(255, 255, 204));
    		lbSum.setText("sum = 0");
    		lbSum.setOpaque(true);
    		getContentPane().add(lbSum);
    		setSize(400, 300);
    		setLocationRelativeTo(null);
     
    		screens = new ArrayList<Screen>();
     
    		Screen s = new Screen(this);
    		getContentPane().add(s);
     
    		Screen s1 = new Screen(this);
    		getContentPane().add(s1);
     
    		Screen s2 = new Screen(this);
    		getContentPane().add(s2);
     
    		Screen s3 = new Screen(this);
    		getContentPane().add(s3);
     
    		screens.add(s);
    		screens.add(s1);
    		screens.add(s2);
    		screens.add(s3);
    	}
     
    	private void btRefreshAllActionPerformed(final ActionEvent evt) {
    		btRefreshAll.setEnabled(false);
    		threadSum = new SwingWorker<Void, Void>() {
     
    			@Override
    			protected Void doInBackground() throws Exception {
    				System.out.println("screen.size() " + screens.size());
    				latch = new CountDownLatch(screens.size());
    				for (int i = 0; i <screens.size(); i++) {
    					screens.get(i).getBtRefresh().doClick();
    				}
    				latch.await();
    				return null;
    			}
     
    			@Override
    			protected void done() {
    				int sum = 0;
    				for (int i = 0; i <screens.size(); i++) {
    					sum += Integer.parseInt(screens.get(i).getjLabel().getText());
    				}
    				lbSum.setText("sum = " + String.valueOf(sum));
    				btRefreshAll.setEnabled(true);
    			}
    		};
    		threadSum.execute();
    	}
     
    	public static void main(final String args[]) {
    		SwingUtilities.invokeLater(new Runnable() {
     
    			@Override
    			public void run() {
    				new ThreadsDemo2().setVisible(true);
    			}
    		});
    	}
    }
    Les "refresh" indépendants de chaque panel, randomisent bien une valeur, mais le "refreshALL" ne fonctionne plus, ne maîtrisant pas tout à fait SwingWorker, j'ai du mal externaliser mon code.
    Le Button RefreshALL ne redevient jamais "enabled" donc je suppose que le "latch" attends quelque chose.


    Deuxièmement, toujours à partir de l'exemple de uhrand, j'ai juste essayé de changer le DoInBackGround() du refreshWorker avec ma fonction qui dure 3 secondes :

    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
     private class RefreshWorker extends SwingWorker<Integer, Object> {
     
            private final int maxNum;
            private final JLabel label;
     
            public RefreshWorker(final int maxNum, final JLabel label) {
                this.maxNum = maxNum;
                this.label = label;
            }
     
            @Override
            protected Integer doInBackground() throws Exception {
     
            	System.out.println("test" + Double.valueOf(c.getCours()));
                int num = maxNum;
                num = (int) Math.round(Double.valueOf(c.getCours()));
     
                return num;
            }
     
            @Override
            protected void done() {
                try {
                    int num = get();
                    label.setText(String.valueOf(num));
                } catch (InterruptedException ex) {
                   // Logger.getLogger(ThreadsDemo.class.getName()).log(Level.SEVERE, null, ex);
                } catch (ExecutionException ex) {
                    //Logger.getLogger(ThreadsDemo.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    if (latch != null) {
                        latch.countDown();
                    }
                }
            }
        }
    Mais en le testant, à l'éxecution, le logiciel ne passe plus dans la fonction DoInBackground().


    Bon je patauge un peu, mais ca avance petit à petit !

Discussions similaires

  1. Utilisation des threads dans une application Perl/Tk
    Par Kroui dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 04/07/2011, 20h00
  2. Réponses: 0
    Dernier message: 24/06/2010, 12h11
  3. gestion des reporting dans une application wpf
    Par sanaaafkir dans le forum Windows Presentation Foundation
    Réponses: 6
    Dernier message: 16/05/2008, 14h02
  4. Gestion des droits dans une application Java
    Par Donaldo dans le forum Langage
    Réponses: 10
    Dernier message: 14/02/2008, 18h15
  5. XML/XSL et gestion des fichiers dans une application Web
    Par fatenatwork dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 01/02/2008, 14h09

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