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 :

Problème d'affichage surperposition de JPanel


Sujet :

AWT/Swing Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 45
    Par défaut Problème d'affichage surperposition de JPanel
    Bonjour,

    J’ai une appli qui affiche plusieurs Jpanel.
    Il y a une tâche de fond (calcul) à la fin il y a un nouvel affichage (repaint) puis un nouveau calcul.
    J'ai 2 problèmes :
    le premier sur l'affichage direct : il y a des panels qui se chevauchent de temps en temps ou des backgrounds qui sont à moitié rempli
    le deuxième et que j'enregistre de temps en temps mon interface et là les images enregistrées ont les mêmes problèmes. Etrangement, si la fenêtre reste en icone il y a beaucoup moins de problèmes.
    J'ai lu dans le forum que cela pouvait venir d'une mauvaise utilisation de la methode repaint. Donc j'ai passé toute l'appli au peigne fin pour éliminer tous les repaint superflue. Mais cela continu....
    Y a t il d'autre piste ?

    Merci d'avance

  2. #2
    Membre Expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Par défaut
    Tu modifies l'interface graphique dans des threads utilisateur?

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 45
    Par défaut
    Bonjour,

    Je ne sais pas très bien ce tu appelle thread utilisateur. Mais si c'est, par exmple la possibilité de changer le background d'un panel par l'intermédiaire d'un bouton de l'interface graphique, c'est oui. Sachant que les action des boutons sont mis dans un thread.
    Il y a aussi pour quelque panel une petite anim (une image qui clignote)

  4. #4
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Il faut te renseigner sur les threads utilisateurs, que l'on appelle aussi Event Dispatching Thread, car cela peut venir de là : voir Threads et performance avec Swing ou Concurrency in Swing.

    Sinon, d'autres questions pour chercher :
    • Est-ce que la tâche de fond fait d'autres choses qu'un repaint sur l'interface graphique ?
    • Quel type de layout utilises-tu ?
    • Est ce que tu as des paintXXs perso ?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 45
    Par défaut
    Bonjour,

    Ma tâche de fond affiche des données quelle reçoit après les avoir traitées.
    Layout utilisés sont des BorderLayout.
    Non j'utilise pas de paintXXs perso (je ne sais pas ce que s'est ). J'ai juste surcharger la méthode paintComponent.

    Je n'est presque plus de problème d'affichage depuis ma traque des repaint. Il y en a encore quand j'exécute un grand nombre d'action utilisateur via des boites de dialog qui modifie les graphiques.
    Par contre, j'ai un phénomène étrange : si ma fenêtre est en icone les enregistrements sont correct, mais si la fenêtre est ouverte alors il y a plien de décalage entre les différents panels.

    voici le code pour l'enregistrement : (il vient du net)
    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
    int w = MonInterface.panelGeneral.getWidth();
                int h = MonInterface.panelGeneral.getHeight();
                BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                Graphics2D graph = image.createGraphics();
                g.G.paint(graph);
                graph.dispose();
                OutputStream out = null; 
     
                try 
                 {
                    out = new BufferedOutputStream(new FileOutputStream(adress+".jpeg"));
                        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 
                        encoder.encode(image); 
                        out.close();
                    }
     
                } 
                catch (Exception exc)
                {exc.printStackTrace();}
                catch (Throwable t) {t.printStackTrace();} 
     
            }
    merci de vos réponses

  6. #6
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Citation Envoyé par marcel72
    Bonjour,

    Ma tâche de fond affiche des données quelle reçoit après les avoir traitées.
    Le fais-tu en faisant attention à l'Event Dispatching Thread ?

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 45
    Par défaut
    Rebonjour,

    Je viens de lire les liens que tu m'as donné. Très intéressant.
    Effectivement je ne faisais pas attention à l'Event Dispatching Thread.
    Je vais arranger cela.
    J'ai tout de même quelques question à ce sujet :
    -Si j'ai bien compris dans mes threads utilisateurs je dois mettre à la fin de toutes mes actions, si elles ont pour but de modifier l'affichage,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                MomAppli.repaint();
              }
    est ce bien celà ?
    -Quand j'utilise un JOptionPane cela ne stop t il pas le thread en cours ?
    si oui, pourquoi utiliser invokeAndWait() dans ce type de cas ?
    -si je crais une JDialog dans un thread y a t il violation de la règle du thread unique ? ou ce thread joura le role de "main application thread" ?

    En revanche pour mon problème d'enregistrement y a t il d'autre piste ?

    Merci d'avance

  8. #8
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Citation Envoyé par marcel72
    -Si j'ai bien compris dans mes threads utilisateurs je dois mettre à la fin de toutes mes actions, si elles ont pour but de modifier l'affichage,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                MomAppli.repaint();
              }
    est ce bien celà ?
    Oui, mais attention qu'il y a peut être un quiproquo sur la notion de thread utilisateur.

    Lorsque tu es dans le Event Dispatching Thread (EDT pour faire plus court), il n'est pas besoin de faire de invokeLater ou assimilé, sauf pour quelques cas particulier. Et, selon ce que tu as modifié dans ta GUI, il n'est pas forcément adapté de faire un repaint.

    Lorsque tu n'es pas dans le EDT, alors il faut t'y mettre, avec les SwingUtilities (ou les équivalents de EventQueue).

    Lorsque tu es dans un thread déclenché par un bouton ou une événement GUI, tu es dans le EDT ; c'est ce que l'on peut (peut être ? ) appeler un événement utilisateur.


    Citation Envoyé par marcel72
    -Quand j'utilise un JOptionPane cela ne stop t il pas le thread en cours ?
    Oui. Mais le EDT peut revenir par ailleurs... C'est un thread subtil...
    Citation Envoyé par marcel72
    si oui, pourquoi utiliser invokeAndWait() dans ce type de cas ?
    Sur une boite modale il faut faire gaffe parce que on peut tout bloquer vite fait, effectivement.

    Citation Envoyé par marcel72
    -si je crais une JDialog dans un thread y a t il violation de la règle du thread unique ? ou ce thread joura le role de "main application thread" ?
    D'abord n'abuse pas des JDialog, ensuite il n'y a pas de violation si tu le fais dans le EDT.

    Citation Envoyé par marcel72
    En revanche pour mon problème d'enregistrement y a t il d'autre piste ?
    Pour l'instant non, et je ne suis même pas sûr que ce travail sur le EDT résolve ton problème ; ce qu'il y a de sûr c'est que, tant que tu ne travailles pas correctement avec le EDT, on ne peut se baser sur rien.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 45
    Par défaut
    Je viens de faire un certain nombre d'essai. Et je pense avoir resolut mon problème.
    Donc merci!

    Pour ma 1ère question :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                MomAppli.repaint();
              }
    ceci est faux. Dans la doc j'ai pu lire que repaint est toujours executer dans l'EDT.

    Pour la 2ème question je ne sais toujours pas...

    Pour l'enregistrement il fallait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                 panelGeneral.paint(graphi);
                 ...
              }
    Ce qui pose un certain nombre de problème :
    car il y a une suite d'action après cela qui n'ont pas forcément leur place dans EDT. Y a t il une astuce ?
    voici à quoi cela ressemble :
    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
     
    dans le traitement de fond
    public void run(){
           ...
           if(enregistre){
           final String adress = Adress;
           SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
     
                         int w = g.G.getWidth();
                         int h = g.G.getHeight();
                         BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                         Graphics2D graph = image.createGraphics();
                         OutputStream out = null;
     
                           g.G.paint(graph);
                           graph.dispose();
     
                           try {
                                 out = new BufferedOutputStream(new FileOutputStream(adress+".jpeg"));
                        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 
                        encoder.encode(image); 
                        out.close();
                        } 
                        catch (Exception exc){exc.printStackTrace();}
                        catch (Throwable t) {exc.printStackTrace();} 
                   }
                   });
          }
    }
    Merci d'avance

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 45
    Par défaut
    Lorsque tu n'es pas dans le EDT, alors il faut t'y mettre, avec les SwingUtilities (ou les équivalents de EventQueue).

    Lorsque tu es dans un thread déclenché par un bouton ou une événement GUI, tu es dans le EDT ; c'est ce que l'on peut (peut être ? ) appeler un événement utilisateur.
    toutes mes action produisent des threads dans les quels il y a les actions voulues.
    D'après ce que j'avais compris de ma lecture, du moment que je faisais un thread je n'étais plus dans EDT. C'est pourquoi mon affachage ne resté pas figué.


    Citation:
    marcel72 a écrit :
    -si je crais une JDialog dans un thread y a t il violation de la règle du thread unique ? ou ce thread joura le role de "main application thread" ?
    D'abord n'abuse pas des JDialog, ensuite il n'y a pas de violation si tu le fais dans le EDT.
    Ok pour les JDialog.
    Comme je le disais precedemment, il m'arrive de faire des choses du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public void actionPerformed(ActionEvent e) {
    new Thread(new Runnable()
           {public void run()
           {
                blabla.....
                new MaJDialog(variable dépendant de blabla);
            }}).start();
    }
    suis je dans l'erreur ?

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

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Citation Envoyé par marcel72
    Comme je le disais precedemment, il m'arrive de faire des choses du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public void actionPerformed(ActionEvent e) {
    new Thread(new Runnable()
           {public void run()
           {
                blabla.....
                new MaJDialog(variable dépendant de blabla);
            }}).start();
    }
    suis je dans l'erreur ?
    Totalement, car en lançant un nouveau thread tu sort de l'EDT, et tu instancies une JDIalog en dehors de l'EDT ce qui est particulièrement dangereux.
    Si le constructeur de MAJdialog réalise une action, c'est dans le constructeur qu'il faut placer le thread, mais surement pas en dehors.

    En tout cas il t'e suffit de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    public void actionPerformed(ActionEvent e) {
     
          new MaJDialog(variable dépendant de blabla);
     
    }

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 45
    Par défaut
    ok merci de ta réponse.

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

Discussions similaires

  1. Problème d'affichage d'un JPanel dans un JFrame.
    Par Patrick95500 dans le forum Agents de placement/Fenêtres
    Réponses: 8
    Dernier message: 18/09/2014, 13h51
  2. Problème d'affichage d'une image [JPanel]
    Par wassim_boy dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 05/05/2012, 19h49
  3. Problème d'affichage de JPanel (et de synchronisation?)
    Par NonoMoreno dans le forum Agents de placement/Fenêtres
    Réponses: 3
    Dernier message: 03/02/2009, 04h12
  4. Réponses: 3
    Dernier message: 07/07/2008, 23h03
  5. Problème d'affichage du contenu de JPanel
    Par Mic75 dans le forum AWT/Swing
    Réponses: 12
    Dernier message: 13/12/2007, 00h53

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