Précédent   Forum du club des développeurs et IT Pro > Java > Interfaces Graphiques en Java > AWT/SWING > EDT/SwingWorker
EDT/SwingWorker Vos questions sur l'EDT (Event Dispatching Thread) et l'utilisation de SwingWorker.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 07/02/2013, 13h23   #1
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
Par défaut Erreur dans le tuto SwingWorker

Bonjour,
J'ai lu attentivement le tutoriel sur le SwingWorker http://rom.developpez.com/java-swingworker/ et en compilant l'exemple sous eclipse j'ai une erreur à la fin du programme.
La voici
java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: the value should be from 0 to 100

et elle semble se trouver dans la méthode done()
Code :
1
2
3
4
5
6
7
8
9
10
11
        @Override
        protected void done() {
            try {
                /* Le traitement est terminé. */
                setProgress(100);
                /* À la fin du traitement, affichage du nombre de fichiers parcourus dans le textfield. */
                textField.setText(String.valueOf(get()));
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
et plus exactement ici : textField.setText(String.valueOf(get()));

Je comprends qu'il veut que la valeur renvoyé à la fin de doInBackground() soit entre 0 et 100 alors que j'ai plus de 100 fichiers dans le répertoire scanné. Mais la valeur renvoyée par doInBackground() doit-elle toujours être entre 0 et 100 (ça me parait bizarre) et sinon quelle méthode permet de donner des limite à ce que renvoie doInBackground().
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2013, 13h41   #2
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
En fait l'erreur se situe au niveau de setProgress((int) progressStart); dans doInBackground().
En effet setProgress indique où l'on en est dans le processus et doit avoir donc une valeur entre 0 et 100 %
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2013, 14h38   #3
wax78
Modérateur
 
Avatar de wax78
 
Homme Renaud Warnotte
Développeur informatique
Inscription : août 2006
Messages : 2 131
Détails du profil
Informations personnelles :
Nom : Homme Renaud Warnotte
Âge : 32
Localisation : Belgique

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : août 2006
Messages : 2 131
Points : 4 070
Points : 4 070
Envoyer un message via MSN à wax78
Quelle erreur ?

Ca doit renvoyer 0 a 100 c'est tout

Un simple calcul devrait régler ca...

Si tu as 15356 fichiers alors le progress vaut

Code :
progressValue = Valeur*100/15356;
ou quelque chose du même accabit.
wax78 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2013, 16h21   #4
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
En fait il semble que le problème se situe dans la récursivité au moment où on ajoute step à progressStart. A un moment progressStart dépasse 100, je ne sais pas pourquoi ?

En fait, comme l'indiquait l'auteur du tutoriel, ce calcul n'était pas l'objectif donc j'ai simplifié en supprimant la récursivité en ne gardant que le premier niveau de répertoire et il n'y a plus de problèmes.
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2013, 16h38   #5
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
J'ai essayé d'adapter le programme proposé dans le tutoriel http://rom.developpez.com/java-swingworker/
Je rappelle le principe de ce programme : on remplit un JTextArea au fur et à mesure que l'on lit un répertoire.
J'ai voulu faire la même chose mais avec un composant personnel et cela ne marche pas.
Pour simplifier j'ai préféré faire deux classes : une pour la JFrame et une pour le SwingWorker (plus bien sûr les classes pour les composants personnels).
Malheureusement cela ne marche pas : au lieu de se remplir au fur et à mesure, il ne se remplit qu'à la fin et encore à la condition que j'oblige la fenêtre à se redessiner.
Il y a sûrement quelque chose que j'ai oublié.
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2013, 18h14   #6
sinok
Modérateur
 
Avatar de sinok
 
Inscription : août 2004
Messages : 8 633
Détails du profil
Informations personnelles :
Âge : 33
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : août 2004
Messages : 8 633
Points : 12 433
Points : 12 433
On ne pourra certainement pas te dire quoi sans que tu nous montre le code associé.
__________________
Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.
sinok est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2013, 19h15   #7
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
OK. Donc voilà.
La classe Galerie qui contient la méthode main() équivalente à la classe SwingWorkerDemo
Code :
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
 
package fr.oiseaux;
 
import java.awt.BorderLayout ;
import java.awt.Dimension ;
import java.awt.FlowLayout ;
import javax.swing.JFrame ;
import javax.swing.JPanel ;
import javax.swing.JProgressBar ;
import javax.swing.JScrollPane ;
import javax.swing.ScrollPaneConstants ;
 
public class Galerie extends JFrame
{
    private GestionDonnees gd;
    private JPanel galerie;
    private JProgressBar barre;
 
    public Galerie(GestionDonnees gd)
    {
        //construction de l'interface graphique
        super("Galerie");
        this.setExtendedState (MAXIMIZED_BOTH);
 
        this.gd = gd;
        String listeImages;
 
//le panneau galerie est mis à la place du JTextArea, j'en attends le même comportement.
        this.galerie = new JPanel(new ModifiedFlowLayout());
        this.barre = new JProgressBar();
        this.barre.setPreferredSize (new Dimension(400,25));
 
 
        JPanel panneauPrincipal = new JPanel(new BorderLayout());
        panneauPrincipal.add (new JScrollPane(galerie,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED));
        JPanel sud = new JPanel(new FlowLayout());
        sud.add (barre);
        panneauPrincipal.add (sud,BorderLayout.SOUTH);
        setContentPane(panneauPrincipal);
 
        setVisible(true);
    }
 
    /**
     * @return the galerie
     */
    public JPanel getGalerie ()
    {
        return this.galerie ;
    }
 
    /**
     * @return the barre
     */
    public JProgressBar getBarre ()
    {
        return this.barre ;
    }
 
    /**
     * @return the gd
     */
    public GestionDonnees getGd ()
    {
        return this.gd ;
    }
 
    public static void main(String... args) 
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                Galerie galerie = new Galerie(new GestionDonnees());
                SwingWorkerGalerie sw = new SwingWorkerGalerie(galerie);
                sw.execute();
            }
        });
    }
}
La classe SwingWorkerGalerie à la place de MonSwingWorker
Code :
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
 
package fr.oiseaux;
 
import java.beans.PropertyChangeEvent ;
import java.beans.PropertyChangeListener ;
import java.util.List ;
import javax.swing.JPanel ;
import javax.swing.JProgressBar ;
import javax.swing.SwingWorker ;
 
public class SwingWorkerGalerie extends SwingWorker<Integer,Images>
{
    private JPanel galerie;
    private GestionDonnees gd;
    private JProgressBar barre;
 
    public SwingWorkerGalerie(Galerie fenetreGalerie)
    {
        this.galerie = fenetreGalerie.getGalerie ();
        this.gd = fenetreGalerie.getGd ();
        this.barre = fenetreGalerie.getBarre ();
 
        //ajout d'un écouteur pour la barre de progression 
        addPropertyChangeListener(new PropertyChangeListener()
        {
            public void propertyChange (PropertyChangeEvent evt)
            {
                if("progress".equals (evt.getPropertyName ()))
                {
                    System.out.println("je suis dans le listener");
                    barre.setValue ((Integer) evt.getNewValue ());
                }
            }
        });
    }
 
    @Override
    protected Integer doInBackground () throws Exception
    {
         return traitementImages() ;
    }
 
    private int traitementImages ()
    {
        int nb = 0;
        int nbDonnees = this.gd.getNbDonnees ();
        if (nbDonnees > 0)
        {
 
            for(int i = 0 ; i < nbDonnees ; i++)
            {
                setProgress((int) (100 * i / nbDonnees));
                String listeImages = this.gd.getListeImages(i);
                try
                {
                        Thread.sleep (50);
                 }
                 catch (InterruptedException e)
                 {
                        e.printStackTrace();
                 }
                 String nom = listeImages.split (";")[0];
                 nom = this.gd.getNom (nom);
                 Images images = new Images(nom,listeImages);
                 publish(images);
            }
        }
        return nbDonnees ;
    }
 
    @Override
    protected void done()
    {
        setProgress(100);
    }
 
    @Override
    protected void process(List<Images> images)
    {
         for (Images i : images) 
            this.galerie.add (i);
     }
}
Les classes nécessaires au projet.

Le flowLayout personnalisé
Code :
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
 
package fr.oiseaux;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
 
/**
 * Dans un JScrollPane les composants prennent leur preferredSize. Si on met un FlowLayout
 * pour un JPanel par exemple, les composants que l'on met dans ce JPanel sont disposés sur
 * une ligne puis passent à la la ligne suivante quand on arrive au bord droit du contenant
 * du JPanel. Si on place JPanel dans un JScrollPane, il n'y a plus de bord droit puisqu'il
 * peut s'étendre aussi loin que l'on veut. les JScrollBar ne sont là que pour permettre 
 * d'accéder à la partie invisible.  
 * On modifie le FlowLayout pour répondre à ce besoin : permettre au JPanel insclus dans un
 * JScrollPanne de s'afficher ligne par ligne et de voir ce qui est hors écran (en bas) grâce
 * au JScrollBar vertical.
 * 
 * A modified version of FlowLayout that allows containers using this Layout to
 * behave in a reasonable manner when placed inside a JScrollPane
 * @author Babu Kalakrishnan
 * Modifications by greearb and jzd
 * Francisation et adaptation : Henrio Patrice
 */
 
public class ModifiedFlowLayout extends FlowLayout 
{
    /**
     * Construit un FlowLayout avec les valeurs par défaut. 
     * Equivalent à new FlowLayout(FlowLayout.CENTER,5,5)
     */
    public ModifiedFlowLayout() 
    {
        super();
    }
 
    /**
     * On calcule la taille préférée du conteneur lié au FlowLayout
     * @param target le conteneur
     * @return sa taille préférée
     */
    public Dimension preferredLayoutSize(Container target) 
    {
        return computeSize(target);
    }
 
    //on calcule la taille du container pour que tous les composants tiennent
    //sur plusieurs lignes.
    //on précise les dimensions du rectangle contenant les composants au fur et à mesure du placement
    private Dimension computeSize(Container target) 
    {
        synchronized (target.getTreeLock()) 
        {
            int hgap = getHgap();
            int vgap = getVgap();
            int w = target.getWidth();
 
            //si le composant n'a pas de taille on lui donne la valeur maximum d'un Integer
            //Integer.MAX_VALUE = 2^31-1
            if (w == 0) 
            {
                w = Integer.MAX_VALUE;
            }
 
            //si les marges ne sont pas déterminées, elles sont nulles (0 pixel)
            Insets insets = target.getInsets();
            if (insets == null) 
            {
                insets = new Insets(0, 0, 0, 0);
            }
 
            //la largeur que l'on calcule
            int reqdWidth = 0;
 
            //la largeur maximale c'est la largeur moins les marges gauches et droites
            //et 2 espacements horizontaux.
            int maxwidth = w - (insets.left + insets.right + hgap * 2);
            //le nombre de composants
            int n = target.getComponentCount();
            //au début le rectangle contenant les composants est 0 x (marge haut + 1 espacement vertical)
            int x = 0;
            int y = insets.top + vgap; 
            //la hauteur d'une ligne est initialisée à 0                            
            int rowHeight = 0;
            //pour chaque composant
            for (int i = 0; i < n; i++) 
            {
                //le composant i
                Component c = target.getComponent(i);
                //on ne calcule la place qu'il occupe que s'il est visible
                if (c.isVisible()) 
                {
                    //ses dimensions préférées 
                    Dimension d = c.getPreferredSize();
                    //si le composant tient sur la ligne ou si c'est le premier
                    if ((x == 0) || ((x + d.width) <= maxwidth)) 
                    {
                        //si ce n'est pas le premier composant de la ligne on ajoute 
                        //un espace horizontal
                        if (x > 0) 
                        {
                            x += hgap;
                        }
                        //on ajoute la largeur du composant
                        x += d.width;
                        //la hauteur d'une ligne c'est la hauteur du plus haut composant de la ligne
                        rowHeight = Math.max(rowHeight, d.height);
                    } 
                    // sinon on démarre une nouvelle ligne de composants
                    else 
                    {
                        // x est la largeur du composant
                        x = d.width;
                        // on ajoute un espace et la hauteur de la ligne 
                        y += vgap + rowHeight;
                        //la hauteur de la nouvelle ligne c'est la hauteur du premier
                        //composant de cette ligne
                        rowHeight = d.height;
                    }
                    //la largeur du container est agrandie si nécessaire
                    reqdWidth = Math.max(reqdWidth, x);
                }
            }
            //on ajoute un espace ne bas
            y += rowHeight;
            //et la marge du bas du container
            y += insets.bottom;
            //la nouvelle dimension c'est la largeur calculée + les marges gauche 
            //et droite, la hauteur calculée
            return new Dimension(reqdWidth + insets.left + insets.right, y);
        }
    }
}
Celle pour obtenir les données
Code :
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
package fr.oiseaux;
 
import java.io.File ;
import java.io.IOException ;
 
public class GestionDonnees
{
    //le nom du fichier des données
    private static String donnees = "." + File.separator + "langues" + File.separator + "francais.txt";
    //le nombre de données
    private int nbDonnees;
    //les images
    private String images[];
    /**
     * Constructeur
     */
    public GestionDonnees()
    {
        File fichier = new File(donnees);
        try
        {
            //les données
            String contenu = Fichier.chargerContenuTexte (fichier);
            //les lignes de données
            this.images = contenu.split ("\n");
            //le nombre de données
            this.nbDonnees = images.length;
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
 
    /**
     * @return le nombre de donnees
     */
    public int getNbDonnees ()
    {
        return this.nbDonnees;
    }
 
    /**
     * @param i l'index pour obtenir la liste des images
     * @return la liste des images correspondante
     * exemple : Bruant des roseaux;bruant.des.roseaux.jpg;bruant.des.roseaux2.jpg
     * la première partie de la chaîne est le nom en fançais puis viennent les images correspondantes
     * (ici il y en a deux)
     */
    public String getListeImages (int i)
    {
        return this.images[i];
    }
}
Celle pour créer les images
Code :
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
package fr.oiseaux;
 
import java.awt.BorderLayout ;
import java.awt.Color ;
import java.awt.Dimension ;
import java.awt.Image ;
import java.awt.Insets ;
import java.io.File ;
import java.util.ArrayList ;
import java.util.List ;
 
import javax.swing.BorderFactory ;
import javax.swing.ImageIcon ;
import javax.swing.JLabel ;
import javax.swing.JPanel ;
import javax.swing.SwingConstants ;
import javax.swing.border.Border ;
import javax.swing.border.TitledBorder ;
 
public class Images extends JPanel
{
    JLabel nom = new JLabel();
    List<JLabel> images = new ArrayList();
 
    /**
     * Constructeur
     * @param listeImages est une String <nom>;<image1>;<image2>;...
     */
    public Images (String nom,String listeImages)
    {
        String[] infos = listeImages.split (";");
        //pour déterminer la largeur préférée
        int l = 5;
        for(int i = 1 ; i < infos.length ; i++)
        {
            String image = "." + File.separator + "images" + File.separator + infos[i];
            ImageIcon imageIcon = new ImageIcon(image) ;
 
            int largeur = imageIcon.getIconWidth ();
            int hauteur = imageIcon.getIconHeight ();
            int largeurImage = 100 ; 
            if (largeur > hauteur) 
            {
                hauteur = (hauteur * largeurImage)/largeur;
                largeur = largeurImage ;
            }
            else
            {
                largeur = (largeur * largeurImage)/hauteur;
                hauteur = largeurImage;
            }
            l += largeur + 5;  
 
            imageIcon = new ImageIcon(imageIcon.getImage().getScaledInstance(largeur,hauteur,Image.SCALE_DEFAULT));
            this.add (new JLabel(imageIcon));
        }
 
        Border bf = BorderFactory.createLineBorder(Color.black);
        TitledBorder bordure = BorderFactory.createTitledBorder(bf,nom);
        bordure.setTitleJustification(TitledBorder.CENTER);
        this.setBorder (bordure);
 
        Insets insets = bordure.getBorderInsets(this);
        //pour que les images tiennent bien.
        this.setPreferredSize (new Dimension(l + insets.left + insets.right,110 + insets.top + insets.bottom));
    }
}
Je pense n'avoir rien oublié.

Je rappelle le problème : dans le JTextArea on voit apparaître au fur et à mesure les noms des fichiers et le JScrollPane se met à jour, dans mon programme il n'y a pas de mise à jour de l'affichage. C'est sans doute tout con mais j'y arrive pas.
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2013, 15h45   #8
sinok
Modérateur
 
Avatar de sinok
 
Inscription : août 2004
Messages : 8 633
Détails du profil
Informations personnelles :
Âge : 33
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : août 2004
Messages : 8 633
Points : 12 433
Points : 12 433
Tu as mal saisi les règles de l'EDT.

Les composants Swing doivent être créés et manipulés dans l'EDT, et non dans le doInBackround.

Or, c'est exactement ce que tu fais ton
Code :
Images images = new Images(nom,listeImages);
Dans ton cas d'utilisation, il serait préférable que ton doInBackground ne fasse que charger les images (sous forme d'ImageIcon ou de BufferedImage via ImageIO), puis que la liste d'images, et non un composant swing les utilisant, soit envoyée via le publish. Puis, dans le process, créer ton composant Image et l'ajouter à ta galerie.

De plus, le scale de ton image ne devrait pas être fait dans le constructeur de ta classe image.
En effet, c'est une opération lourde, et, de fait, elle bloque l'EDT.


Donc l'idée est de charger les images dans le doInBackround, de les redimensionner puis de les publier. Afin que l'opération du process soit la moins couteuse possible.
__________________
Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.
sinok est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2013, 16h53   #9
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
Citation:
Envoyé par sinok Voir le message
Tu as mal saisi les règles de l'EDT.

Les composants Swing doivent être créés et manipulés dans l'EDT, et non dans le doInBackround.

Or, c'est exactement ce que tu fais ton
Code :
Images images = new Images(nom,listeImages);
Dans ton cas d'utilisation, il serait préférable que ton doInBackground ne fasse que charger les images (sous forme d'ImageIcon ou de BufferedImage via ImageIO), puis que la liste d'images, et non un composant swing les utilisant, soit envoyée via le publish. Puis, dans le process, créer ton composant Image et l'ajouter à ta galerie.

De plus, le scale de ton image ne devrait pas être fait dans le constructeur de ta classe image.
En effet, c'est une opération lourde, et, de fait, elle bloque l'EDT.


Donc l'idée est de charger les images dans le doInBackround, de les redimensionner puis de les publier. Afin que l'opération du process soit la moins couteuse possible.
Mercci beaucoup. Je vais examiner tout cela. je me doutais bien que mon problème venait du fait que j'avais mal compris quelque chose.
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2013, 18h32   #10
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
J'ai essayé de modifier mon code comme me l'a indiqué Sinok. Malheureusement ça ne marche toujours pas. D'après ce qu'il dit je pense que le problème vient du temps nécessaire pour créer mes images. Voici mes modifications. Pour les classes non modifiées se reporter à mon
message du 7 février 19h15
SwingWorkerGalerie est modifié, Images est remplacé par ListeImages et Cartouche.
La nouvelle classe SwingWorker
Code :
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
package fr.oiseaux;
 
import java.awt.Image ;
import java.beans.PropertyChangeEvent ;
import java.beans.PropertyChangeListener ;
import java.io.File ;
import java.util.ArrayList ;
import java.util.List ;
 
import javax.swing.ImageIcon ;
import javax.swing.JLabel ;
import javax.swing.JPanel ;
import javax.swing.JProgressBar ;
import javax.swing.SwingWorker ;
 
public class SwingWorkerGalerie extends SwingWorker<Integer,ListeImages>
{
    private JPanel galerie;
    private GestionDonnees gd;
    private JProgressBar barre;
 
    public SwingWorkerGalerie(Galerie fenetreGalerie)
    {
        //on doit afficher au fur et à mesure les images
        this.galerie = fenetreGalerie.getGalerie ();
        this.gd = fenetreGalerie.getGd ();
        this.barre = fenetreGalerie.getBarre ();
 
        //ajout d'un écouteur pour la barre de progression 
        addPropertyChangeListener(new PropertyChangeListener()
        {
            public void propertyChange (PropertyChangeEvent evt)
            {
                if("progress".equals (evt.getPropertyName ()))
                {
                    System.out.println("je suis dans le listener");
                    barre.setValue ((Integer) evt.getNewValue ());
                }
            }
        });
    }
 
    @Override
    protected Integer doInBackground () throws Exception
    {
        return traitementImages() ;
    }
 
    private int traitementImages ()
    {
        int nb = 0;
        int nbDonnees = this.gd.getNbDonnees ();
        if (nbDonnees > 0)
        {
 
            for(int i = 0 ; i < nbDonnees ; i++)
            {
                setProgress((int) (100 * i / nbDonnees));
                String listeImages = this.gd.getListeImages(i);
                String nom = listeImages.split (";")[0];
                ListeImages images = new ListeImages(listeImages);
                publish(images);
 
            }
        }
        return nbDonnees ;
    }
 
 
    @Override
    protected void done()
    {
        setProgress(100);
    }
 
    @Override
    protected void process(List<ListeImages> images)
    {
        if (images != null)
        {
            System.out.println(images.size ());
            for (ListeImages listeImages : images) 
            {
                if (listeImages != null)
                {
                    System.out.println(listeImages.getNom () + " : " + listeImages.nbImage () + " image(s)");
                    this.galerie.add (new Cartouche(listeImages));
                }
            }
        }
    }
}
Les affichage dans la console viennent du fait que j'ai des java.lang.NullPointerException

La classe ListeImages qui se contente de charger les images et de les mettre à l'échelle.
Code :
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
 
package fr.oiseaux;
import java.awt.Image ;
import java.io.File ;
import java.util.ArrayList ;
import java.util.List ;
import javax.swing.ImageIcon ;
 
public class ListeImages
{
    private String nom;
    private List<ImageIcon> listeImages;
 
    public ListeImages(String liste)
    {
        List<ImageIcon> images = new ArrayList();
        String[] infos = liste.split (";");
        this.nom = infos[0];
        for(int j = 1 ; j < infos.length ; j++)
        {
            String image = "." + File.separator + "images" + File.separator + infos[j];
            ImageIcon imageIcon = new ImageIcon(image) ;
            //mise à l'échelle            
            int largeur = imageIcon.getIconWidth ();
            int hauteur = imageIcon.getIconHeight ();
 
            int largeurImage = 100 ;
            if (largeur > hauteur) 
            {
                hauteur = (hauteur * largeurImage)/largeur;
                largeur = largeurImage;
            }
            else
            {
                largeur = (largeur * largeurImage)/hauteur;
                hauteur = largeurImage;
            }
            imageIcon = new ImageIcon(imageIcon.getImage().getScaledInstance(largeur,hauteur,Image.SCALE_DEFAULT));
            images.add (imageIcon);
        }
    }
 
    public String getNom ()
    {
        return this.nom ;
    }
 
    public List<ImageIcon> getListeImages ()
    {
        return this.listeImages ;
    }
 
    public int nbImage ()
    {
        return ((listeImages==null)? 0 : this.listeImages.size ()) ;
    }
}
La classe Cartouche qui remplace en fait l'ancienne classe Images
Code :
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
package fr.oiseaux;
 
import java.awt.Color ;
import java.awt.Dimension ;
import java.awt.FlowLayout ;
import java.awt.FontMetrics ;
 
import javax.swing.BorderFactory ;
import javax.swing.ImageIcon ;
import javax.swing.JLabel ;
import javax.swing.JPanel ;
import javax.swing.border.Border ;
import javax.swing.border.TitledBorder ;
 
public class Cartouche extends JPanel
{
    public Cartouche (ListeImages listeImages)
    {
        //les images
        for (ImageIcon image : listeImages.getListeImages ())
        {
            this.add (new JLabel(image));
        }
 
        //le titre du cartouche
        String nom = listeImages.getNom ();
 
        //la bordure
        Border bf = BorderFactory.createLineBorder(Color.black);
        TitledBorder bordure = BorderFactory.createTitledBorder(bf,nom);
        bordure.setTitleJustification(TitledBorder.CENTER);
        this.setBorder (bordure);
 
        //la taille du composant
        FontMetrics fm = this.getFontMetrics (bordure.getTitleFont());
        int largeurNom = fm.stringWidth (nom) + 20;
        Dimension d = this.getPreferredSize ();
        int largeur =  d.width;
        int hauteur = d.height;
        largeur = Math.max (largeurNom, largeur);
 
        this.setPreferredSize (new Dimension(largeur,hauteur));
    }
}
Et voici l'erreur (les erreurs plutôt) que j'obtiens

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at fr.oiseaux.Cartouche.<init>(Cartouche.java:27)
at fr.oiseaux.SwingWorkerGalerie.process(SwingWorkerGalerie.java:152)
at javax.swing.SwingWorker$3.run(Unknown Source)

Je pense comprendre qu'on fait appel aux objets ListeImages avant qu'ils aient fini de se construire.
Le problème est je pense basique et qu'il faut interdire l'accès à un objet ListeImages tant que la construction n'est pas finie mais je crois avoir suffisamment prouvé que je n'y connaissais rien pour ce qui concerne les thread.
Peut-être une histoire de synchronized ... mais sur quoi ?
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2013, 21h25   #11
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
J'ai trouvé pourquoi il y avait une erreur. C'était vraiment tout con .
Dans la classe ListeImages il faut remplacer la dernière ligne du constructeur par listeImages.add (imageIcon) au lieu de images.add (imageIcon);
Code :
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
 
package fr.oiseaux;
import java.awt.Image ;
import java.io.File ;
import java.util.ArrayList ;
import java.util.List ;
import javax.swing.ImageIcon ;
 
public class ListeImages
{
    private String nom;
    private List<ImageIcon> listeImages;
 
    public ListeImages(String liste)
    {
        String[] infos = liste.split (";");
        this.nom = infos[0];
        for(int j = 1 ; j < infos.length ; j++)
        {
            String image = "." + File.separator + "images" + File.separator + infos[j];
            ImageIcon imageIcon = new ImageIcon(image) ;
            //mise à l'échelle            
            int largeur = imageIcon.getIconWidth ();
            int hauteur = imageIcon.getIconHeight ();
 
            int largeurImage = 100 ;
            if (largeur > hauteur) 
            {
                hauteur = (hauteur * largeurImage)/largeur;
                largeur = largeurImage;
            }
            else
            {
                largeur = (largeur * largeurImage)/hauteur;
                hauteur = largeurImage;
            }
            imageIcon = new ImageIcon(imageIcon.getImage().getScaledInstance(largeur,hauteur,Image.SCALE_DEFAULT));
            listeImages.add (imageIcon);
        }
    }
 
    public String getNom ()
    {
        return this.nom ;
    }
 
    public List<ImageIcon> getListeImages ()
    {
        return this.listeImages ;
    }
 
    public int nbImage ()
    {
        return ((listeImages==null)? 0 : this.listeImages.size ()) ;
    }
}
Malheureusement une autre erreur est apparue. Mais comme j'ai fait d'autres modifications il faut que je regarde de plus près.
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2013, 21h56   #12
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
Le résultat est identique à ce que j'avais avant : les images n'apparaissent toujours pas au fur et à mesure du chargement. La seule chose que j'ai réussi à améliorer c'est qu'à la fin de tous les chargements la fenêtre affiche toutes les images une fois que j'ai ajouté un repaint de la JFrame dans la méthode done().
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2013, 00h54   #13
sinok
Modérateur
 
Avatar de sinok
 
Inscription : août 2004
Messages : 8 633
Détails du profil
Informations personnelles :
Âge : 33
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : août 2004
Messages : 8 633
Points : 12 433
Points : 12 433
Dans ta méthode process, après le add au panel, ajoute un appel à revalidate pour notifier au panel que son agencement a changé.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
    @Override
    protected void process(List<ListeImages> images)
    {
        if (images != null)
        {
            System.out.println(images.size ());
            for (ListeImages listeImages : images) 
            {
                if (listeImages != null)
                {
                    System.out.println(listeImages.getNom () + " : " + listeImages.nbImage () + " image(s)");
                    this.galerie.add (new Cartouche(listeImages));
                    this.galerie.revalidate();
                }
            }
        }
    }
__________________
Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.
sinok est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2013, 08h59   #14
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
Impeccable.
Merci beaucoup Sinok, sans ton aide j'y serai jamais arrivé.

Je vais abuser en core un peu. Pour lemoement les images apparaissent bien mais le JScrollPane ne descend pas ua fur et à mesure comme dans l'exemple avec un JTextArea. Il faut peut-être lui notifier de se positionner vers le bas ?

En tout cas encore merci.
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2013, 12h27   #15
sinok
Modérateur
 
Avatar de sinok
 
Inscription : août 2004
Messages : 8 633
Détails du profil
Informations personnelles :
Âge : 33
Localisation : France, Paris (Île de France)

Informations forums :
Inscription : août 2004
Messages : 8 633
Points : 12 433
Points : 12 433
Code :
1
2
3
4
5
6
 
System.out.println(listeImages.getNom () + " : " + listeImages.nbImage () + " image(s)");
Cartouche c = new Cartouche(listeImages);
this.galerie.add (c);
this.galerie.revalidate();
this.galerie.scrollRectToVisible(c.getBounds());
__________________
Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.
sinok est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/02/2013, 00h11   #16
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
Citation:
Envoyé par sinok Voir le message
Code :
1
2
3
4
5
6
 
System.out.println(listeImages.getNom () + " : " + listeImages.nbImage () + " image(s)");
Cartouche c = new Cartouche(listeImages);
this.galerie.add (c);
this.galerie.revalidate();
this.galerie.scrollRectToVisible(c.getBounds());
Hélas ça ne marche pas. Ca fait exactement comme avant. J'ai tracé l'évènement et en fait ça doit encore être un problème de thread et d'EDT. Au moment ou on crée le cartouche et qu'on revalidate la galerie, on transmets à EDT qui va placer le cartouche et donc définir le rectangle qui l'englobe mais par contre le thread lui continue par c.getBounds qui renvoie (0,0,0,0) et donc le JScrollPane reste en haut. Peut être un invokeAndWait ?
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2013, 09h09   #17
Patrice Henrio
Membre du Club
 
Inscription : janvier 2004
Messages : 250
Détails du profil
Informations forums :
Inscription : janvier 2004
Messages : 250
Points : 63
Points : 63
J'ai fini par trouver. Il suffisait d'un peu de réflexions et de bien comprendre ce que fait this.galerie.scrollRectToVisible(rectangle);
Cela déplace les ScrollBars pour que le rectangle soit visible, au moins son coin en haut à gauche.
Je rappelle l'enjeu : il s'agissait de remplir une JFrame avec des images dans un JScrollBar et que celui adapte son comportement pour que la dernière image placée soit toujours visible. Il suffisait donc de créer un rectangle dont le coin bas à droite soit celui du panneau et le coin haut gauche soit nécessairement visible dans le JScrollPane.
Donc pour ceux que cela intéresse voici le code :
(les cartouches sont des panneaux sur lesquels des images sont regroupées par thème.)
Code :
1
2
3
4
5
6
7
 
Cartouche c = new Cartouche(listeImages);
this.galerie.add (c);
this.galerie.revalidate();
int x = 0, y = galerie.getHeight()-300, w = galerie.getWidth(), h = 300;
Rectangle r = new Rectangle(x,y,w,h);
galerie.scrollRectToVisible (r);
__________________
C'est en respectant les autres que l'on se fait respecter.
Patrice Henrio est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 02h50.


 
 
 
 
Partenaires

Hébergement Web