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 :

Double appel à paintComponent()


Sujet :

AWT/Swing Java

  1. #1
    Membre régulier
    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
    Points : 76
    Points
    76
    Par défaut Double appel à paintComponent()
    Bonjour,

    Je transport des particules (une particule = un pixel et des coordonnées géographiques) à l'écran, que je dessine sur un JPanel à chaque pas de temps de ma simulation :
    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
     
    public void paintComponent(Graphics g) {
     
        int h = getHeight();
        int w = getWidth();
     
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHints(hints);
        g2.clearRect(0, 0, w, h);
     
        /** Redessine l'arrière plan si la fenêtre est redimensionnée */
        if (hi != h || wi != w) {
          drawBackground(g2, w, h);
          hi = h;
          wi = w;
        }
        /** Remplis le graphics avec l'arrière plan */
        g2.drawImage(background, 0, 0, this);
     
        /** Dessine mes particules dans le graphics */
        if (population != null) {
          ParticleUI particleUI = new ParticleUI(MainFrame.getValMin(),
              MainFrame.getValMax(), MainFrame.getDisplayColor());
          Iterator<Particle> iter = population.iterator();
          Particle particle;
          while (iter.hasNext()) {
            particle = iter.next();
            if (particle.isLiving()) {
              particleUI.draw(particle, w, h);
              g2.setColor(particleUI.getColor());
              g2.fill(particleUI);
            }
          }
        }
      }
    Dans mon code principal, à chaque pas de temps, je lance un monPanelSimulation.repaint()
    Pour pouvoir rejouer la simulation à la fin du run, sans refaire les calculs, je fais aussi à chaque pas de temps un getImage() comme suggéré dans la FAQ, pour stocker les étapes sous forme de BufferedImage.

    Le problème : entre le repaint() et le paintAll() de getImage(), j'appelle deux fois la méthode paintComponent pour un même pas de temps. Pas de problème quand je transporte 3 particules, plus gênant quand il y en a 50000

    Le but : un seul appel à paintComponent() par pas de temps.

    Début de solution : créer la BufferedImage qui correspond à mon pas de temps directement dans paintComponent() (plus de méthode getImage() dans le code principal).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public void paintComponent(Graphics g) {
        /** Le même que précédemment */
        if (population != null) {
            // je dessine mes particles dans le graphics
        }
        /** là il me faudrait un bout de code du genre : */
        BufferedImage step = g2.createImage(w, h);
        listSteps.add(step); // je garde l'image step en mémoire pour la rejouer plus tard
        g2.dispose();
    }
    Mais cette instruction createImage comme je le voudrais ici n'existe pas. La question a déjà été abordé dans le forum mais je n'y vois pas beaucoup plus clair... peut-être parce que c'est vendredi fin d'après midi...

    Merci d'avance si qqn peut m'aider à avancer un peu !
    a+

    Philippe.

  2. #2
    Membre émérite
    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
    Points : 2 582
    Points
    2 582
    Par défaut
    Mon opinion est que tu devrais réfléchir à ton modèle de particules, de façon à le dessiner de façon plus rapide, et non pas enregistrer des séries d'images ; peut être, faire un modèle intermédiaire, optimisé pour l'affichage ?

    Sinon, autant que je comprends ta méthode, tu vas te retrouver pour rejouer la simulation avec la liste des images, mais plus la liste des modèles ?... ou alors, tu comptes mémoriser images et modèles ?
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  3. #3
    Membre régulier
    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
    Points : 76
    Points
    76
    Par défaut
    Bonjour,

    Merci gifffftane pour ta réponse.
    C'est tout à fait possible qu'il y ait un problème de conception au départ... Je t'explique comment je procède actuellement :
    Je simule le transport de particules et rafraichis à l'écran en temps réel. A chaque pas de temps, je calcule les nouvelles coordonnées des particules et je les affiches à l'écran en utilisant la méthode paintComponent() décrite au 1er message.
    A la fin de la simulation, je laisse la possibilité à l'utilisateur de revisualiser le run, mais sans refaire aucun calcul. C'est pour cette raison que je stoque chaque état de la simulation sous forme d'une BufferedImage : une fois la simulation terminée, je n'ai plus qu'à faire redéfiler les images stoquées en mémoire vive (l'utilisateur actionne un slider "défilement du temps").

    Tu me suggères de repenser la conception pour ne pas stoquer des images. Intéressant ! Si je veux pouvoir redessiner le parcours des particules à chaque pas de temps de ma simulation, il faudra donc que je stoque en mémoire vive les coordonées (longitude, latitude, profondeur) de chaque particule à chaque pas de temps...
    Qu'est ce qui prend le plus de place en mémoire vive ?
    * double[time=500][particle=50000][coordonnées=3] --> 75 millions de doubles
    * BufferedImage[time=500] --> 500 BufferedImages

    Pour ce qui est de la rapidité de la fonction paintComponent() ... je pense que je peux difficilement faire mieux à mon petit niveau j'ai pas le code sous la main ce soir, mais je peux le poster lundi matin.

    Encore merci pour le coup de pouce.
    Philippe.

  4. #4
    Membre émérite
    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
    Points : 2 582
    Points
    2 582
    Par défaut
    ... et quelle sera la taille de tes 500 BufferedImages ?...

    Tu es le mieux placé pour voir à quel endroit il est mieux de travailler. S'il s'agit juste de rejouer les images, sans retrouver aucune info sur ces particules, peut être que la forme 500 BufferedImages est la meilleure. Mais s'il faut donner des infos sur les particules pendant la simulation, cela risque d'être plus difficile.

    Bref ça dépend s'il faut seulement rejouer, ou s'il faut vraiment re-simuler.

    Ensuite, comment sont ces images ? Si les particules sont en blanc sur fond noir, tu peux optimiser avec le format du BufferedImage. Un BufferedImage en noir et blanc, c'est plus petit qu'un en couleur.

    Si tu ne t'interesses qu'à rejouer, peut être carrément envisager de travailler avec un format type mp3 ?

    Si tu t'interesses au modèle et à re-simuler, alors il te faudra une base de données.

    Bref, tu as un projet intéressant
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  5. #5
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Une maniere assez simple d'obtenir un debut d'optimisation rapide est de restreindre la zone a redessiner (ca marche en dessin direct ou en dessin sur une image offscreen) via :

    - la verification de la zone de clip et se restreindre uniquement a dessiner ce qui est dedans ou intersecte la zone de clip (attention cependant dans ton cas comme il y a, j'imagine, egalement une profondeur des atomes dans la visu, ca peut demander plus de caculs et au final revenir a tout reafficher).

    - restreindre les appels a repaints a une zone de l'ecran, soit (dans les faits, les deux methodes sont identiques) :

    - repaint(zone de depart) suivit de repaint(zone d'arrivee).

    - repaint(union de la zone de depart et de la zone d'arrivee).

    Une autre maniere d'avoir un peu plus de rapidite :

    - eviter d'utiliser la transparence quand ce n'est pas necessaire.

    - utiliser des images compatibles avec l'affichage.

    De maniere plus general tu peux desormais achete le livre "Filthy Rich Clients", chez Addison Wesley de notre ami Gfx (Roman Guy) pour avoir plus de details. Sinon tu peux egalement aller frequenter les forums de jeux (javagaming.org par exemple) pour avoir des infos sur l'optimisation d'affichage 2D (puisque ce sont egalement des techniques tres utilisees en jeu 2D, nottament les jeux de platformes).

    Sinon sans idee de ce qui est affiche ou de la maniere dont tu procedes difficile de pouvoir en dire plus.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  6. #6
    Membre régulier
    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
    Points : 76
    Points
    76
    Par défaut
    Bonjour,

    Merci pour vos éléments de réponse !

    ==> En réponse à giffftane.
    Citation Envoyé par gifffftane
    ... et quelle sera la taille de tes 500 BufferedImages ?...
    Graphics.getHeigth() de l'ordre de 500, idem pour width
    Citation Envoyé par giffftane
    Si tu ne t'interesses qu'à rejouer, peut être carrément envisager de travailler avec un format type mp3 ?
    Oui je suis tout à fait dans cette optique : je ne cherche qu'à rejouer. Il faut que je regarde de ce côté là. Je n'ai encore jamais manipulé ce format en java, mais il y a surement des API.

    ==> En réponse à Bouye.
    Merci à toi pour ces conseils, mais je n'en suis pas vraiment à optimiser mon code de dessin... il marche "vite" comparé à la partie IO (je manipule des fichiers netcdf de plusieurs centaines de Mo et c'est le véritable goulot d'étranglement du programme).
    Tu suggères de limiter les repaint aux seules zones qui doivent être redéfinies ! Oui, c'est le bon sens qui parle et pourtant je ne le fais pas...
    Je ne vois pas bien encore comment on détermine la zone d'union des zones arrivées et départ des particules, mais à réfléchir !

    Je te mets en pièce jointe le fichier SimulationUI.java qui gère toute le partie graphique du modèle. J'ai défini deux objets :
    * un CellUI qui hérite d'un poligone (une cellule de maillage n'est rien d'autre qu'un quadrilatère coloré)
    * un ParticleUI qui est une Ellipse2D (un centre + une couleur + une position)

    Citation Envoyé par Bouye
    De maniere plus general tu peux desormais achete le livre "Filthy Rich Clients", chez Addison Wesley de notre ami Gfx (Roman Guy) pour avoir plus de details. Sinon tu peux egalement aller frequenter les forums de jeux (javagaming.org par exemple) pour avoir des infos sur l'optimisation d'affichage 2D (puisque ce sont egalement des techniques tres utilisees en jeu 2D, nottament les jeux de platformes).
    Yebo ! J'ai pas le livre, mais je suis déjà sur les exemples des chapitres pour voir comment le chief travaille

    A +
    Philippe
    Fichiers attachés Fichiers attachés

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Citation Envoyé par pverley Voir le message
    Merci à toi pour ces conseils, mais je n'en suis pas vraiment à optimiser mon code de dessin... il marche "vite" comparé à la partie IO (je manipule des fichiers netcdf de plusieurs centaines de Mo et c'est le véritable goulot d'étranglement du programme).
    Du NetCDF, hein, comment charges-tu tes variables ? Lis-tu tes Array d'un seul bloc ou est-ce que tu les charges par morceaux ? Ici on commence a taper dans les fichiers NetCDF oceanographiques de 3Go+, ce qui fait que meme les outils prevus pour les gros cdf (Ferret, NCbrowse, etc...) ne suivent plus, de meme que nous outils d'extraction qui fonctionnaient plutot bien pour des fichiers de taille 50~600 Mo. Je pense que je vais finir par extraire les donnees dans un format de fichier intermediaire plus petit et contenant uniquement une plage de dates "realistes" visibles par l'utilisateur. Mais a partir de l'an prochain, il est clair qu'il va nous falloir completement repenser nos outils pour traiter ce format. Mais bon la on sort completement de la partie affichage...

    Tu suggères de limiter les repaint aux seules zones qui doivent être redéfinies ! Oui, c'est le bon sens qui parle et pourtant je ne le fais pas...
    Je ne vois pas bien encore comment on détermine la zone d'union des zones arrivées et départ des particules, mais à réfléchir !
    Le plus simple est d'appeler repaint(x, y, w, h) sur chacune des deux regions, le repaint manager fera l'union de lui-meme (et puisque tu es pendant l'EDT tu es sur qu'il n'y a pas de raffraichissement entre les 2 apppels concecutifs), sinon il y a les methodes qu'il faut dans la classe Rectangle2D et bon l'union de deux rectangles ce n'est pas non-plus tres complique a faire manuellement.
    Puisque tu manipules des Shape, tu as acces a leur boite englobante rectangulaire (getBounds() et getBounds2D()) ce qui permet de simplifier bien des calculs de colisition, detection/restriction des zones a rafraichir, etc..
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  8. #8
    Membre régulier
    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
    Points : 76
    Points
    76
    Par défaut
    Bonjour,

    Merci pour les tuyaux sur la façon de repeindre efficacement mes zones. J'ai besoin d'y réfléchir. C'est encore un peu nouveau pour moi et mon petit cerveau va pas très vite

    Citation Envoyé par Bouye
    Du NetCDF, hein, comment charges-tu tes variables ? Lis-tu tes Array d'un seul bloc ou est-ce que tu les charges par morceaux ?
    Je travaille sur des fichiers ROMS (simu océano), donc en gros, à chaque pas de temps, j'extraie les champs u(time=current_rank, :, :, : ) et pareil pour v. C'est clair que je n'optimise pas mon extraction dans l'espace, mais j'ai pas vraiment le choix parce que j'ai besoin des champs u et v complet pour lancer une routine de recalcul de la vitesse verticale. Je referme la parenthèse (que je rouvrirai peut-être ailleurs, car je pense qu'une discussion avec toi, à ce sujet, serait fort intéressante !)

    Cheers,
    Merci

    Philippe.

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

Discussions similaires

  1. [AJAX] Double appel javascript
    Par sliderman dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 25/11/2008, 09h42
  2. src="" et double appel HTTP
    Par stefdefifoot dans le forum Apache
    Réponses: 1
    Dernier message: 20/01/2007, 11h08
  3. double appel du script quand balise <img src vide
    Par zamanika dans le forum Langage
    Réponses: 8
    Dernier message: 16/11/2006, 12h21
  4. [Servlet] double appel de la méthode init()
    Par nin2 dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 07/06/2006, 08h09
  5. [POO] double appel de méthode
    Par nako dans le forum Langage
    Réponses: 4
    Dernier message: 18/04/2006, 15h59

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