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 :

SwingWorker et repaint()


Sujet :

EDT/SwingWorker Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Par défaut SwingWorker et repaint()
    Bonjour,

    Je travaille sur un modèle de simulation numérique, avec des calculs d'un côté et un affichage à l'écran de la simulation de l'autre. J'utilise pour cela un SwingWorker().
    J'ai deux objets :
    * Simulation() qui execute les calculs
    * SimulationUI() qui dérive d'un JPanel sur lequel je dessine les étapes de la simulation, en redéfinissant paintComponent()

    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
     
    class MonSwingWorker extends SwingWorker {
           @Override
           public Object doInBackground() throws Exception {
               while(time < simulationDuration) {
                  simulation.step(time); //je lance une étape
                  publish(time);
               }
           }
     
           @Override
           protected void process(List<Long>times) {
              for (long time:times)
                 if (time % dt_refresh == 0) {
                    slider.setValue(step++); // je fais avancer un slider
                    simulationUI.repaint(); //je rafraichis l'affichage 
                 }
           }
       }
    Le problème : ça marche sans aucun problème mais le code appelle deux fois la méthode simulationUI.paintComponent() ...
    Le premier est sûrement dû à l'utilisation de la méthode publish() (qui ajoute une nouvelle tache dans l'EDT, je le dis mal mais c'est l'idée, non ?) et l'autre qui correspond à mon repaint()

    J'ai refais tourner en supprimant la ligne simulationUI.repaint().La méthode paintComponent() est appelée une fois, mais je n'observe plus de rafraichissment à l'écran ...

    Bref je comprends pas bien ce qui se passe

    J'ai dis que le code marchait bien et que je pourrais m'en tenir là. Mais un double appel à la méthode paintComponent() est très gênant parce que je fais beaucoup de calculs dedans et ça ralentit l'application.

    D'avance merci pour vos éclaircissments.
    Philippe.

  2. #2
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Par défaut
    Mon problème ne suscite pas de réponses. C'est que je l'ai mal posé. Reprenons.

    J'essaie de comprendre :
    1. Pourquoi la méthode MonSwingWorker.process() exécute simulationUI.paintComponent() sans que j'appelle simulationUI.repaint() (je fais tourner en mettant la ligne en commentaire) ?

    2. Pourquoi il n'y a pas de rafraichissement de mon composant SimulationUI alors que la méthode paintComponent() est exécutée. (J'observe un rafraichissement si je redimensionne la fenêtre, par exemple).

  3. #3
    Gfx
    Gfx est déconnecté
    Expert confirmé
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Par défaut
    Le slider.setValue() doit en être la cause.

  4. #4
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Par défaut
    Bonjour,

    Merci pour ta réponse.
    En effet, il faut sûrement chercher de ce côté puisque c'est la seule autre action que j'exécute dans l'EDT ...

    La modification du Slider entrainerait l'appel des méthodes paintComponent() de tous les components de la JFrame ? Pourtant le composant simulationUI n'est pas redessiné. C'est sûrement normal puique rien n'indique qu'il doit être rafraichi.

    Je vois pas trop comment gérer ça ...
    Ce que je veux exactement :
    * simulationUI redessiné à chaque fois que la condition if (time % dt_refresh == 0) est vérifiée
    * garantir que simulationUI.paintComponent() ne sera appelée qu'une seule fois.

    Si vous pouvez m'aider à avancer là dessus c'est cool.
    Mon problème vient aussi, à n'en pas douter, d'une maigre connaissance des mécanisme de l'EDT. N'hésitez pas à me renvoyer à mes cahiers

    Philippe

  5. #5
    Gfx
    Gfx est déconnecté
    Expert confirmé
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Par défaut
    C'est d'autant plus douteux que le RepaintManager est censé combiner les dirty regions et plusieurs appels à repaint(). Toujours est-il que ton slider peut faire repeindre la fenêtre dans plusieurs situations assez particulières (notamment si tu utilises un glass pane ou des composants non opaques, etc.).

    Es-tu certain que ton paintComponent() est appelé deux fois ? Ton simulation.step() ne provoque-t'il pas un repaint() ?

    Bref, plus de code aiderait

  6. #6
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Février 2007
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Février 2007
    Messages : 80
    Par défaut
    Yep,

    Bon, le problème c'est le programmeur, pas le programme... en réfléchissant à quel code te poster pour illustrer le propose j'ai compris mon erreur :
    Dans la méthode process() j'appelle aussi une méthode simulationUI().getImage() qui contient un paintAll() (d'où le 2ème appel à paintComponent())
    Grosse erreur de ma part. Je t'ai fais perdre ton temps, mes excuses les plus plattes.

    Ca m'a quand même permis de voir que le programme appelle deux fois paintComponent() ...
    En fait je stocke dans un tableau de BufferedImage[] toutes les étapes de la simulation pour que l'utilisateur puisse la rejouer à la fin. Pour les stocker j'ai écris une méthode getImage(component) comme suggéré dans la FAQ avec un paintAll()

    En passant : c'est peut-être pas très efficace de stocker des BufferedImage en mémoire vive ? Existe-t'il une façon standard de procéder pour les animations ?

    Encore merci pour ton aide.
    Allez, délestage !!

Discussions similaires

  1. [JPanel] paint, paintComponent et repaint ?
    Par Pill_S dans le forum Composants
    Réponses: 8
    Dernier message: 08/02/2013, 17h38
  2. Lancer repaint() en synchrone
    Par Higestromm dans le forum Interfaces Graphiques en Java
    Réponses: 11
    Dernier message: 06/10/2005, 13h40
  3. [MouseEvent] arret de souris = repaint() ?
    Par n00bi dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 08/06/2005, 11h38
  4. Comment geler le repaint d'un TPageControl ?
    Par qi130 dans le forum Composants VCL
    Réponses: 19
    Dernier message: 20/12/2004, 22h30
  5. [Graphisme][Débutant(e)] Problème sur repaint()
    Par Katyucha dans le forum AWT/Swing
    Réponses: 6
    Dernier message: 08/10/2004, 17h12

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