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

 Java Discussion :

PaintComponent() et scrolling


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Août 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 13
    Par défaut PaintComponent() et scrolling
    Bonsoir,

    C'est la première fois que je viens solliciter votre aide après de nombreuses heures à parcourir toute l'aide fournir par sur développez.com (Merci pour cela au passage, c'est un vrai plaisir de voir pas mal d'astuces pour apprendre à développer).

    Je rencontre aujourd'hui un problème avec la méthode paintComponent() couplée à du scrolling.

    Actuellement, j'essaie de développer un "mini-programme", permettant de m'aider à mieux calculer des temps pour un jeu. Pour cela j'ai un panel principal, nommé panel (qui est mon content pane de ma JFrame).

    Ce panel principal est découpé en 3 panels :
    - Header
    - Contenu
    - ListeActions

    Contenu contient un ensemble de boutons qui lorsque l'on clique sur l'un d'entre eux ajoute une ligne dans listeActions (cf pièce jointe)

    Mes problèmes sont les suivants :

    1. Question majeure :

    Lorsque je bouge mon scroll, la fonction paintComponent() est appelée à gogo et repeint tout (les bords du scrolls notamment). C'est moche et très lent (cf pièce jointe numéro 2.

    Ma question est donc la suivante :
    - Comment faire pour qu'à chaque clique mes lignes continuent d'apparaitre et que je puisse scroller sans avoir ces soucis en permanence ?

    Actuellement j'ai fait hériter mon JPanel d'une classe où j'ai rédéfinie ma fonction paintComponentn().

    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 jeu;
     
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
     
    import javax.imageio.ImageIO;
    import javax.swing.JPanel;
     
    import unites.Unite;
     
    import batiments.Batiment;
     
    public class PanelRefresh extends JPanel 
    {
    	public ArrayList collection ;
     
    	//Initialisation de notre PanelRefresh
    	public PanelRefresh()
    	{
    		collection = new ArrayList() ;
    	}
     
    	//Redéfinition de paintComponent
        public void paintComponent(Graphics g)
        {
        	//Tant que la collection n'est pas vide, on l'affiche
        	for(int i = 0; i < collection.size(); i++)
            {   
        		//**********************************
        		//On commence par faire le rectangle
        		//**********************************
     
        		g.drawRect(0, 40 + 40*i , 180, 30) ;
     
        		//**********************************************
        		//On s'occupe après d'afficher l'image miniature
        		//**********************************************
        		BufferedImage image;
    			try
    			{
    				//On charge l'image
    				if(collection.get(i) instanceof Batiment)
    					image = ImageIO.read( getClass().getResource("/" + ((Batiment)collection.get(i)).caracteristiques.nomAnglais + ".png") );
    				else if(collection.get(i) instanceof Unite)
    					image = ImageIO.read( getClass().getResource("/" + ((Unite)collection.get(i)).caracteristiques.nomAnglais + ".jpg") );
    				else
    					image = null ;
     
    					//Affichage de l'image
    				g.drawImage(image, 0, 40 + 40*i, 30, 30, this);
    			} catch (IOException e)
    			{
    				e.printStackTrace();
    			}
     
    			//**************************************
    			// Enfin on s'occupe d'afficher le temps
    			//**************************************
    			int heures, minutes, secondes ;
     
    			if(collection.get(i) instanceof Batiment)
    			{
    				heures = (int) Math.floor(((Batiment)collection.get(i)).tempsFinal / 3600) ; 
    				minutes = (int) Math.floor((((Batiment)collection.get(i)).tempsFinal - (heures * 3600)) / 60) ;
    				secondes = ((Batiment)collection.get(i)).tempsFinal - heures*3600 - minutes*60 ;
    			}
    			else if(collection.get(i) instanceof Unite)
    			{
    				heures = (int) Math.floor(((Unite)collection.get(i)).tempsFinal / 3600) ; 
    				minutes = (int) Math.floor((((Unite)collection.get(i)).tempsFinal - (heures * 3600)) / 60) ;
    				secondes = ((Unite)collection.get(i)).tempsFinal - heures*3600 - minutes*60 ;
    			}
    			else
    			{
    				heures = 0  ;
    				minutes = 0 ;
    				secondes = 0 ;
    			}
     
    			g.drawString(heures + "h" + minutes + "m" + secondes + "s", 50, 60 + 40*i) ;
            }
        }     
     
        public void setCollection(ArrayList collection)
        {
        	this.collection = collection ;
        }
    }
    Je fais un repaint à chaque fois que j'appuie sur l'un des boutons comme le montre l'un des boutons (pris au hasard, mais ils ont tous la même structure)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //Classe interne d'écoute du Canon à Golems
    		class CanonListener  implements ActionListener
    		{
    	        public void actionPerformed(ActionEvent arg0) 
    	        {
    	        	//On créé un objet Maison
    	        	CanonAGolem canon = new CanonAGolem(ileMere) ;
     
    	        	canon.ecoute(ileMere, collection, listeActions) ;
     
            		//On rafraichit
                    repaint() ;       
    	        }
    		}
    Bref, j'ai un vrai problème actuellement à gérer les deux... Help, please


    ----

    2. Question subsidiaire

    Petite question subsidiaire. Actuellement mon JPanel en question fait 200x600 pour la taille. Lorsque j'ai plus d'objets que possible, je ne peux pas scroller vers le bas pour voir les autres objets. Ils ne semblent ne pas être affichés ou tenus en compte par le scroll. Une idée ?

    Je vous remercie par avance à ceux qui pourront m'aider. Si vous pouvez être clairs et me considérer comme un bon gros noob dans vos explications, je vous en serai reconnaissant...

    Cordialement,

    Shad.
    Images attachées Images attachées   

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Pour ton problème graphique, je pense qu'il faudrait soulager un peu ton paintComponent() : tu y charges les images ce qui peut "alourdir" le traitement et donc gêner l'affichage !

    Il serait préférable d'utiliser un cache et de charger les images en tâches de fond...


    De même attention au parcours des collections. Il serait préférable d'utiliser un Iterator ou mieux une boucle for-étendu si tu es en Java 5 ou +

    Enfin, plutôt que de multiplier les instanceof et les duplications de code, il serait préférable d'utiliser une interface commune avec des méthodes getter approprié...



    En ce qui concerne ton problème de scrollbar, il faut que tu calcules la "preferred size" de ton composant dynamiquement selon son contenu, afin que le scrollpane puissent déterminer s'il doit afficher ou non les scrollbar...



    Pour un tel composant, il serait surement préférable de se tourner vers une JList avec un CellRenderer personnalisé !


    a++

  3. #3
    Membre averti
    Inscrit en
    Août 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 13
    Par défaut
    Bonjour,

    Merci pour cette première panoplie de réponses (et merci pour le déplacement de topic).

    Cependant, j'ai encore quelques questions car je ne comprends pas tout (C'est souvent le cas avec les )

    Citation Envoyé par adiGuba Voir le message
    Salut,


    Pour ton problème graphique, je pense qu'il faudrait soulager un peu ton paintComponent() : tu y charges les images ce qui peut "alourdir" le traitement et donc gêner l'affichage !

    Il serait préférable d'utiliser un cache et de charger les images en tâches de fond...
    Pourrais tu prendre le temps de m'expliquer comment réaliser un tel cache ou bien m'indiquer un tutorial ou une aide vers lequel me rediriger svp ?

    J'ai eu effectivement l'occasion de lire une fois déjà quelqu'un proposer une solution du genre, mais je n'avais pas vraiment saisie comment faire.


    De même attention au parcours des collections. Il serait préférable d'utiliser un Iterator ou mieux une boucle for-étendu si tu es en Java 5 ou +
    Soit, je vais changer cela. Mais pour info, qu'est ce que cela change ?

    Enfin, plutôt que de multiplier les instanceof et les duplications de code, il serait préférable d'utiliser une interface commune avec des méthodes getter approprié...
    Pourrais tu, svp, m'indiquer quelques pistes afin de m'éclairer sur le sens de cette phrase ? Car j'avoue ne pas tout comprendre


    En ce qui concerne ton problème de scrollbar, il faut que tu calcules la "preferred size" de ton composant dynamiquement selon son contenu, afin que le scrollpane puissent déterminer s'il doit afficher ou non les scrollbar...
    Heu... Actuellement je défini statiquement en utilisant setPreferedSize pour gérer la taille de mon JPanel. Est-ce que ca veut dire que si mon JPanel fait 200x600 par exemple, le contenu que je vais afficher qui va "dépasser" ses mensurations va "disparaitre" et donc ne pas être scrollable ?

    Si je comprends bien le sens de la phrase, il faut que la taille de mon JPanel augmente en conséquence de mes ajouts, même si mon affichage reste inchangé, ceci afin que ma ScrollBar prenne effet, c'est ça ?

    Comment déterminer dynamiquement sa taille?

    Pour un tel composant, il serait surement préférable de se tourner vers une JList avec un CellRenderer personnalisé !
    Je ne sais pas encore de quoi tu me parles là, mais je vais gratter sur ces deux choses pour comprendre


    Merci !

    P.S: J'en profite pour poser une question qui me turlupine. On m'a parlé de validate() mais impossible de trouver des renseignements dessus (Soit je suis nul en google, soit y'a vraiment pas grand chose dessus.) A quoi ça sert ?

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    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 482
    Par défaut
    Pour le cache, le plus simple serait d'avoir une List<Image> que tu charge dans ton constructeur et non dans paintComponent(). Il n'y a pas de raison de recharger les images à chaque fois. Les méthodes paint dans les environnement graphique sont appelées très souvant. Quand une fenetre "glisse" au dessus d'un autre, le fenetre arriere peut recevoir une centaine d'ordre de type 'paintComponent' en une seconde. Ton code a donc intérêt à etre rapide. Comme mentionné, l'utilisation d'un listcellrenderer serait plus approprié dans ton cas. Aussi, évite de redessiner les image que ne font pas partie de la zone à redessiner. Dans ton Graphics, tu une methode getClipRect() qui mentionne la zone à redessiner. Pas la peine de faire du boulot pour ce qui est hors-zone.

  5. #5
    Membre Expert
    Avatar de slim_java
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2008
    Messages
    2 272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2008
    Messages : 2 272
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Dans ton Graphics, tu une methode getClipRect() qui mentionne la zone à redessiner. Pas la peine de faire du boulot pour ce qui est hors-zone.
    je rajoute la méthode repaint(x,y,L,H) et paintImmediately(x,y,L,H)

Discussions similaires

  1. Fenetre sans Scroll Bar
    Par nicolas78986 dans le forum MFC
    Réponses: 15
    Dernier message: 01/06/2007, 03h15
  2. [TP]Scroll in 320x200
    Par Jagaraujo dans le forum Turbo Pascal
    Réponses: 5
    Dernier message: 07/08/2003, 13h46
  3. le fameux scrolling
    Par tanmieu dans le forum DirectX
    Réponses: 4
    Dernier message: 27/05/2003, 23h25
  4. scrolling vertical et horizontal
    Par myriam dans le forum MFC
    Réponses: 2
    Dernier message: 24/01/2003, 17h06
  5. scroll dans un label
    Par Pretender dans le forum Composants VCL
    Réponses: 9
    Dernier message: 27/09/2002, 17h06

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