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

Composants Java Discussion :

Fonctionnement des renderer


Sujet :

Composants Java

  1. #1
    Membre du Club
    Inscrit en
    Décembre 2008
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 81
    Points : 61
    Points
    61
    Par défaut Fonctionnement des renderer
    Bonjour,
    je suis à la recherche d'explication sur la gestion des renderer en swing. (pas la création de renderer). J'entend par là, la compréhension des instanciations des objets.

    Exemple simple. Pour appliquer son propre renderer, il faut, sur une JTable, faire :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //Set up renderer and editor for the Favorite Color column.
            table.setDefaultRenderer(Color.class,
                                     new ColorRenderer(true));
    qui revient à faire de manière plus précise:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        TableModel model = new ColorTableModel();
        JTable table = new JTable(model);
     
        TableColumn column = table.getColumnModel().getColumn(2);
     
        ColorRenderer renderer = new ColorRenderer(true);
        column.setCellRenderer(renderer);
    source du code ColorRenderer: http://docs.oracle.com/javase/tutori...rRenderer.java

    Dans ces 2 exemples, on voit parfaitement qu'il n'y qu'une seule création de l'objet (par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new ColorRenderer(true)
    ) et dans la classe ColorRenderer qui implemente logiquement TableCellRenderer, on trouve la fonction getTableCellRendererComponent qui retourne this, soit le component créé via le new.

    Hors, plus tard, quand on va fouillé dans la JTable (JTable.class), lors de la récupération du renderer, on va récupérer le même objet pour chaque cellule ! comment est-ce possible ?

    Xpmich

  2. #2
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Le renderer "produit" ce qui va être envoyé au GUI. Il est le même pour toutes les cellules, ce qui ne veut pas dire qu'il renvoie la même chose pour toutes les cellules.
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Xpmich Voir le message
    Hors, plus tard, quand on va fouillé dans la JTable (JTable.class), lors de la récupération du renderer, on va récupérer le même objet pour chaque cellule ! comment est-ce possible ?

    Xpmich
    Dans ce cas là, il faut voir la méthode getTableCellRendererComponent comme une méthode de préparation du composant à l'affichage. Ca se voit d'ailleurs dans le code de l'exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    setBackground(newColor);
              setBorder(selectedBorder);
            setToolTipText("RGB value: " + newColor.getRed() + ", "
                                         + newColor.getGreen() + ", "
                                         + newColor.getBlue());
    A chaque fois, on change les valeurs des données utilisées par l'affichage.

    Le JTable fait en gros:
    pour chaque cellule
    appeler getTableCellRendererComponent
    afficher le rendererComponent obtenu

    Note qu'on peux très bien coder un Renderer qui renvoie un composant différent pour chaque cellule, on ne le fait juste pas. Et c'est aussi pour ça que certains composants ne peuvent pas être utilisés comme renderer, car leur dessin passe par un UI, qui fait des choses asynchrone. Or qui dit asynchorne dit lire un autre état plus tard, correspondant à une autre cellule.

  4. #4
    Membre du Club
    Inscrit en
    Décembre 2008
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 81
    Points : 61
    Points
    61
    Par défaut
    Merci pour vos réponses rapides.

    Avec le mix des deux, si je comprend bien, le même composant est dessiné à chaque fois mais l'UI sait ce qu'elle fait et ne "décale" pas le composant d'une cellule à l'autre.

    Dans mon cas, j'écris une librairie similaire à swing, il est donc préférable comme le dit tchize_ de gérer personnellement chaque renderer comme je gère chaque contenu de cellule (par ex.: has map avec tri...).
    Note qu'on peux très bien coder un Renderer qui renvoie un composant différent pour chaque cellule, on ne le fait juste pas.
    Donc ma 1ere question : est-ce la meilleure méthode ?

    Poussons la réflexion jsuqu'au bout. Dans le cas du renderer classique de Swing, il étend (normalement) un composant (JLabel, JPanel par exemple). Si dans ce renderer on redéfini un paint, est-ce utile ? est-ce cyclique ?

    Xpmich

  5. #5
    Membre du Club
    Inscrit en
    Décembre 2008
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 81
    Points : 61
    Points
    61
    Par défaut
    Je me permet de réagir encore suite au remarque de tchize_ :
    Le JTable fait en gros:
    pour chaque cellule

    appeler getTableCellRendererComponent
    afficher le rendererComponent obtenu
    C'est à dire que :
    pour chaque cellule
    cellule 1 :
    appeler getTableCellRendererComponent ==> soit toto@132f12
    afficher le rendererComponent obtenu ==> pour toto@132f12
    cellule 2 :
    appeler getTableCellRendererComponent ==> soit toto@132f12
    afficher le rendererComponent obtenu ==> pour toto@132f12
    cellule 3 :
    appeler getTableCellRendererComponent ==> soit toto@132f12
    afficher le rendererComponent obtenu ==> pour toto@132f12

    le getTableCellRendererComponent retourne lui aussi le même objet ! donc l'objet dans la cellule 1 est rendu où si il sert à dessiner la cellule 3 ?

    (je me perd tout seul, non ??)

    Xpmich

  6. #6
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Le composant obtenu n'est pas forcément de la même classe à chaque appel, et même s'il est de la même classe ce n'est pas forcément (ou forcément pas ?) la même instance.
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  7. #7
    Membre du Club
    Inscrit en
    Décembre 2008
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 81
    Points : 61
    Points
    61
    Par défaut
    Qu'il ne soit pas de la même classe je le comprend parfaitement, çà pas de soucis (peut varié selon la colonne, la ligne, la couleur du chat de la voisine...)

    mais au niveau de l'instance, je le comprend bien mais ne l'explique pas. Ou sont les lignes de codes prouvant qu'il ne s'agit justement pas de la même instance ?

  8. #8
    Membre éclairé Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Points : 803
    Points
    803
    Par défaut
    Je suppose qu'il y a un "new" quelque part ?
    Sans danger si utilisé conformément au mode d'emploi.

    (anciennement BenWillard, enfin moins anciennement que ... enfin bon c'est une longue histoire... Un genre de voyage dans le temps...)

  9. #9
    Membre du Club
    Inscrit en
    Décembre 2008
    Messages
    81
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 81
    Points : 61
    Points
    61
    Par défaut
    je l'entend bien mais ou ? côté swing c'est sûr ! mais côté table (pas trouvé) ou côté UI ou ailleurs ?

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Xpmich Voir le message

    le getTableCellRendererComponent retourne lui aussi le même objet ! donc l'objet dans la cellule 1 est rendu où si il sert à dessiner la cellule 3 ?


    Xpmich
    Il est rendu immédiatement, c'est ça le truc. Comme je dit, pour chaque cellule: 1) on récupère le renderer
    2) on l'affiche

    Ensuite on passe à la cellule suivante. Du coup, le JComponent est affcihé exactement dans l'état où il sort de la méthode rendererComponent, avant d'être à nouveau modifié/recyclé par l'appel suivant. Il n'y a rien de spécial à mémoriser dans l'histoire.

    Voilà par exemple la méthode paintCell telle qu'on la trouve dans le BasicTableUI
    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
        private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
            if (table.isEditing() && table.getEditingRow()==row &&
                                     table.getEditingColumn()==column) {
                Component component = table.getEditorComponent();
    	    component.setBounds(cellRect);
                component.validate();
            }
            else {
                TableCellRenderer renderer = table.getCellRenderer(row, column);
                Component component = table.prepareRenderer(renderer, row, column);
                rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
                                            cellRect.width, cellRect.height, true);
            }
        }
     
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Object value = getValueAt(row, column);
     
            boolean isSelected = false;
            boolean hasFocus = false;
     
            // Only indicate the selection and focused cell if not printing
            if (!isPaintingForPrint()) {
                isSelected = isCellSelected(row, column);
     
                boolean rowIsLead =
                    (selectionModel.getLeadSelectionIndex() == row);
                boolean colIsLead =
                    (columnModel.getSelectionModel().getLeadSelectionIndex() == column);
     
                hasFocus = (rowIsLead && colIsLead) && isFocusOwner();
            }
     
    	return renderer.getTableCellRendererComponent(this, value,
    	                                              isSelected, hasFocus,
    	                                              row, column);
        }
    comme tu vois, à chaque cellule qu'on veux afficher, on appelle le renderer => Forcément, au moment où l'on dessine la cellule il est dans le bon état.

    Attention que l'effet secondaire, si tu ne l'a pas remarqué, c'est que le getTableCellRendererComponent est appelé très souvent et se doit d'être le plus simple possible => mauvais idée d'aller y faire un new

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Si ça permet d'être plus clair, le composant retourné par getTableCellRendererComponent n'est jamais ajouté à la JTable, c'est plutot comme en faire une photo et afficher cette photo dans la JTable au bon endroit.

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

Discussions similaires

  1. Fonctionnement des comparateurs de prix ?
    Par masseur dans le forum Services
    Réponses: 3
    Dernier message: 22/01/2006, 21h11
  2. Fonctionnement des attributions de droits sur table et bdd ?
    Par shako95 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 28/11/2005, 13h39
  3. Fonctionnement des WeakHashMap
    Par seiryujay dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 03/10/2005, 14h12
  4. Fonctionnement des fichiers.
    Par phoenix440 dans le forum Autres Logiciels
    Réponses: 7
    Dernier message: 29/05/2005, 15h36
  5. [langage] fonctionnement des Processus
    Par GMI3 dans le forum Langage
    Réponses: 3
    Dernier message: 19/09/2003, 11h12

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