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

2D Java Discussion :

[JFreeChart] Dessiner par dessus un graphique


Sujet :

2D Java

  1. #1
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut [JFreeChart] Dessiner par dessus un graphique
    Bonjour,
    dans mon application en java, j'affiche un graphique avec JFreeChart (j'affiche un ChartPanel donc le comportement est le meme que sur JPanel). Ce que j'aimerais c'est pouvoir dessiner une ellipse en couleur mais légèrement transparente pour qu'on voit encore le graphique par dessus ce graphique afin que l'utilisateur puisse sélectionner une partie des points sur le graphiques.
    Quel est la meilleure solution pour dessiner cette ellipse? superposé des JPanel? utilisé une BufferedImage?
    et si je pouvais avoir un petit exemple pour que je puisse voir rapidement si ça correspond à ce que je recherche, ce serait sympa
    merci

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    la meilleur suggestion, deux panels superposé avec le layout approprié. Le panel du dessus serait transparent, surchargerais paintComponent et intercepterais les évènements souris. Regarde du coté de l'overlaylayout

  3. #3
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    L'overlaylayout fait bien se que je voulais au niveau de l'affichage.
    merci pour ton aide tchize_.
    Par contre le déplacement et le redimensionnement de mon ellipse est très saccadé... environ 500 ms entre chaque passage dans mouseDragged alors que le traitement du dragged se fait dans la meme milliseconde (j'ai fait affiché des new Date().getTime au début et à la fin du mouseDragged).
    Je sais pas s'il y a une astuce pour le rendre plus fluide ou ce qui fait que ce soit si saccadé.
    Est-ce que quelqu'un a une idée?

  4. #4
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Donne ton code, car il n'y a aucune raison que ça saccade. Idéalement, il ne faut faire aucune nouvelle instance dans paintComponent ou tes listener.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  5. #5
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    Voici mon paintComponent qui va peindre mes ellipses:
    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
     public void paintComponent(Graphics g){       
             Graphics2D g2d =(Graphics2D)g;
             super.paintComponent(g);  
             if(this._nbRect==0){
                 return;
             }else{
                 if (this._nbRect==1){
                     if (this._popA){
                        this._rectA.paintRect(g2d);
                     }else if (this._popB){
                         this._rectB.paintRect(g2d);
                     }
                 }else{
                     if (this._nbRect ==2){
                         this._rectA.paintRect(g2d);
                         this._rectB.paintRect(g2d);
                     }
                 }
             }
        }
    La fonction painRect appelé dans le 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
    public void paintRect(Graphics2D g2d){
            Color tmp = g2d.getColor();
            Font font = new Font("Arial",Font.BOLD,20);
             g2d.setFont(font);
             g2d.setColor(this._color);
             g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)0.2F));
             g2d.fillOval((int)this._rect.x,(int)this._rect.y,(int)this._rect.width,(int)this._rect.height);
             g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)0.5F));
             g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
             g2d.drawString(this._name,(int)(_rect.getMaxX()),(int)(_rect.getMaxY()));
             g2d.setColor(tmp);
             if(this._selected){
                 this.paintRectSelected(g2d);
             }
             g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)1F));
        }
    et mon mouseDragged (this._selected représente l'objet ChartRectangle (ellipse + son nom) selectionné par la souris :
    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
    public void mouseDragged(MouseEvent e) {
             int xT = e.getX();
             int yT = e.getY();
             if (e.getModifiers() == 16){
            	 if(_curs != 0){
                     int i = _point.x - xT;
                     int j = _point.y - yT;
                     this._selected.deplace(_curs, i, j);
                 }else{
                     if (_selected.isResizable()){
                         this._selected._rect.x += xT - _point.x;
                         this._selected._rect.y += yT - _point.y;
                     }
                 }
                 if(this._dataArea.contains(new Point2D.Double(this._selected._rect.getMinX(),this._selected._rect.getMinY())) &&this._dataArea.contains(new Point2D.Double(this._selected._rect.getMaxX(),this._selected._rect.getMaxY())) && !this._selected._rect.intersects(this._selected != this._rectA ? this._rectA._rect : this._rectB._rect)) 
                 {
                     if (_selected == this._rectA){
                         this._rectA = tmpR;
                     }else if (_selected == this._rectB){
                         this._rectB = tmpR;
                     }
                 this._point = e.getPoint();
                 this.repaint();
                 }
             }             
        }

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    vu que çà fait de l'antialisaing, du compositing et tout le toutim, t'as vérifié que le composant en dessous (jfreechart) ne recalcule pas à chaque fois tout le graphe? (si c'est disponible, active y le doublebuffering)

    Met aussi des Date() dans tes méthodes pour voir lesquelles sont les plus longues.

  7. #7
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    il fait effectivement un paint du graphique à chaque passage dans mouseDragged et c'est ça qui prends 500 millisecondes.
    Il faut que j'utilise le DoubleBuffering pour éviter ça? Comment ça marche?
    J'ai mis setDoubleBuffering(true) sur mon ChartPanel mais ça n'a rien changé...

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    essaie déjà avec un panel simple en fond pour voir si c'est plus rapide ou pas. Pour ce qui est du double buffering, c'est à voir avec JFreeChart comment le faire, je ne connais pas cette librairie.

  9. #9
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    j'ai essayé avec juste le panel sur lequel je dessine de mettre setDoubleBuffering(true), ça n'a rien changé. J'ai meme essayé en mettant les 2 panels en doubleBuffering et c'est pas mieux.
    Est-ce que l'utilisation d'une bufferedImage sur laquelle je dessinerais mes ellipses changerais quelque chose?
    Comment pourrais-je éviter de faire le paint() de mon panel où il y a le graphique pendant le draggedMouse (car mon graphique ne change pas à ce moment là)?

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    je proposais de mettre un panel vide plutot qu'un chart derrière, histoire de voir si c'est le chart qui est en cause dans les performances. Faire du buffering sur le panel du haut n'a aucun sens, si l'on considère que, lors du mouse dragged, l'image du haut change justement.

  11. #11
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Août 2005
    Messages : 6 913
    Billets dans le blog
    54
    Par défaut
    Citation Envoyé par jeanGuignol Voir le message
    Comment pourrais-je éviter de faire le paint() de mon panel où il y a le graphique pendant le draggedMouse (car mon graphique ne change pas à ce moment là)?
    Au lieu juste d'appeler repaint(), peux-tu essayer en appelant sa variante qui prend une zone rectangulaire (il te faudra conserver les coordonnees de l'evenement precedent) ? Il est possible qu'il te faille alors egalement modifier ta methode de rendu pour prendre en compte la zone de clip du Graphics de maniere a ne redessiner que le strict minimum.
    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

  12. #12
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    sinon, je sais pas si çà te conviens mais ... ne pas jouer avec le composite?

  13. #13
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    j'ai surchargé la méthode paint de mon ChartPanel pour ne pas qu'il se repeigne et effectivement c'est plus fluide donc le problème de lenteur viens bien de ce paint.
    Donc à la place du du repaint() dans mon mouseDragged, j'ai mis un paintComponent dans lequel j'ai ajouté l'utilisation d'une BufferedImage pour que l'on ne voit que le dernier dessin des ellipses et non pas tout le tracé du déplacer.
    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
     public void paintComponent(Graphics g){   
             Graphics2D g2d =(Graphics2D)g;
             super.paintComponent(g);  
             g2d.drawImage(_bufferedChart, this.getX(), this.getY(),this);
             if(this._nbRect==0){
                 return;
             }else{
                 if (this._nbRect==1){
                     if (this._popA){
                        this._rectA.paintRect(g2d);
                     }else if (this._popB){
                         this._rectB.paintRect(g2d);
                     }
                 }else{
                     if (this._nbRect ==2){
                         this._rectA.paintRect(g2d);
                         this._rectB.paintRect(g2d);
                     }
                 }
             }
        }
    Le mouvement est beaucoup plus fluide. J'ai seulement un léger clignotement à chaque paintComponent. Est-ce que ça peut être éviter?

  14. #14
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    setOpaque(false), sinon l'appel à super.paintComponent va dessiner l'arrière plan gris uni à chaque fois -> effet de clignotement

  15. #15
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    le panel sur lequel je dessine est déjà en setOpaque(false).
    j'ai essayé en true et effectivement, on voit que l'arrière plan se dessine.
    En fait j'ai juste mes 2 ellipses que je redessine qui clignote

  16. #16
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    est-ce que tu ferais par hasard ceci directement sur le Graphics de l'écran

    dessin de la copie du graphe
    dessin de l'ellipse 1
    dessin de l'ellipse 2

    Dans ce cas, le clignotement est du au dessin du graphe qui 'efface' temporairement les ellipse. Fait ton dessin final dans un bufferedimage et ensuite copie le à l'écran.

  17. #17
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    C'est effectivement ce que je faisais.
    Donc maintenant je dessine mes ellipses avec le Graphics dans ma bufferedImage et le mouvement est beaucoup plus fluide.
    Par contre vu que ma bufferedImage contient maintenant le graphique et les ellipses, j'ai un problème lorsque je déplace mon ellipse. Elle est redessiné à chaque déplacement, donc je vois toute les ellipses tracées lors de son déplacement.


    voici le code du paintComponent où je redessine mes ellipses:
    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
    /** PaintComponent override, draw the bounds of the ellipse if it is selected */
    	public void paintComponent(Graphics g) {
    		Graphics2D g2dBuffered = (Graphics2D) _bufferedChart.getGraphics();
    		if (this._nbRect == 0) {
    			return;
    		} else {
    			if (this._nbRect == 1) {
    				if (this._popA) {
    					this._rectA.paintRect(g2dBuffered);
    				} else if (this._popB) {
    					this._rectB.paintRect(g2dBuffered);
    				}
    			} else {
    				if (this._nbRect == 2) {
    					this._rectA.paintRect(g2dBuffered);
    					this._rectB.paintRect(g2dBuffered);
    				}
    			}
    		}
    		Graphics2D g2d = (Graphics2D) g;
    		g2d.drawImage(_bufferedChart, this.getX(), this.getY(), this);
    	}
    Serait-il possible de garder en mémoire l'image du graphique sans les ellipses puis de rajouter les ellipses à chaque paintComponent?

  18. #18
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    avant de tracer ton ellipse, tu dois commencer par redessiner au dessus du dessin précédent, le graphique. Ensuite tu dessine l'image. Le but du bufferedimage c'est de faire cette décomposition en arrière plan plutot qu'à l'écran, évitant l'effet clignotement.

  19. #19
    Membre confirmé
    Inscrit en
    Septembre 2008
    Messages
    61
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 61
    Par défaut
    le fait de redessiné le graphique plus les ellipses à chaque dans le mouseDragged me prends une demi-seconde donc on revient au problème de mouvement saccadé.
    L'idéal serait de posé le graphique une fois pour toute et ne plus y touché car sinon ça ralentit tout et de seulement redessiner le panel par dessus où se trouve les ellipses. C'est possible?

  20. #20
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Citation Envoyé par jeanGuignol Voir le message
    le fait de redessiné le graphique plus les ellipses à chaque dans le mouseDragged me prends une demi-seconde donc on revient au problème de mouvement saccadé.
    L'idéal serait de posé le graphique une fois pour toute et ne plus y touché car sinon ça ralentit tout et de seulement redessiner le panel par dessus où se trouve les ellipses. C'est possible?
    Tu peux utiliser une seconde BufferedImage qui contient uniquement le graphique. Tu le fais une fois pour toute au début. Et c'est ce second buffer que tu vas utiliser pour réinitialiser la BufferedImage que tu utilises déjà.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [API HTML5] <Video> Dessiner par dessus une vidéo
    Par cjacquel dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 14/12/2013, 01h57
  2. Dessiner par-dessus une texture 2D
    Par dream_of_australia dans le forum OpenGL
    Réponses: 5
    Dernier message: 03/10/2009, 20h31
  3. Dessiner par dessus une image
    Par bakaneko dans le forum C++Builder
    Réponses: 9
    Dernier message: 14/07/2007, 06h25
  4. [jtable][jpanel] dessiner par dessus une jtable
    Par tuxor dans le forum Composants
    Réponses: 4
    Dernier message: 22/04/2007, 15h37
  5. [Dx9] Dessiner un curseur par dessus une texture
    Par SteelBox dans le forum DirectX
    Réponses: 16
    Dernier message: 25/04/2005, 21h38

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