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

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

EDT/SwingWorker Java Discussion :

Erreur dans le tuto SwingWorker


Sujet :

EDT/SwingWorker Java

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  2. #2
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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.

  3. #3
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 073
    Points : 7 977
    Points
    7 977
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    progressValue = Valeur*100/15356;
    ou quelque chose du même accabit.
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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.

  5. #5
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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.

  6. #6
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    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.

  7. #7
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    OK. Donc voilà.
    La classe Galerie qui contient la méthode main() équivalente à la classe SwingWorkerDemo
    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
     
    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 : 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
     
    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 : 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
     
    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 : 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
    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 : 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
    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.

  8. #8
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  9. #9
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  10. #10
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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 : 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
    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 : 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
     
    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 : 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
    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.

  11. #11
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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 : 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
     
    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.

  12. #12
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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.

  13. #13
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    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 : 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
     
        @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.

  14. #14
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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.

  15. #15
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  16. #16
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par sinok Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  17. #17
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 25/04/2012, 13h46
  2. Erreur dans le tuto de julien-pauli
    Par thebarbarius dans le forum Zend Framework
    Réponses: 7
    Dernier message: 12/07/2011, 11h21

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