2010-02-04 3 views
4

J'utilise un CustomCellRenderer pour afficher les nœuds d'un JTree pour afficher l'image avec un noeud comme ci-dessous: -Changer l'image de nœud d'un JTree dynamique

class CustomTreeCellRenderer extends DefaultTreeCellRenderer{ 

    public Component getTreeCellRendererComponent(JTree tree, 
     Object value, boolean selected, boolean expanded, 
     boolean leaf, int row, boolean hasFocus){ 

     super.getTreeCellRendererComponent(tree, value, 
     selected, expanded, leaf, row, hasFocus); 

     JLabel label = (JLabel) this ; 

     label.setIcon(new ImageIcon("white.png")) ; 

     return this; 
    } 
} 

Mon exigence est de changer l'image du noeud sur certaines actions externes. Je suis en train de recharger le modèle de DTree, mais il ne fonctionne pas comme indiqué ci-dessous: -

public void actionPerformed(ActionEvent ae) { 

     DefaultTreeModel model = (DefaultTreeModel) tree.getModel() ; 

     JLabel label = (JLabel) tree.getCellRenderer() ; 
     System.out.println(label.getIcon()); //displaying white.png 

     label.setIcon(new ImageIcon("black.gif")) ; 


     model.reload() ; 
    } 

Où que je fais mal ?????? Ajoutez votre icône à la classe de votre moteur de rendu en tant que champ.

Répondre

1

Modifiez la valeur de ce champ et repeignez le JTree.

class CustomTreeCellRenderer extends DefaultTreeCellRenderer{ 


    ImageIcon rendererIcon; 


    public void setRendererIcon(ImageIcon myIcon){ 
     this.rendererIcon = myIcon; 
    }; 


    public Component getTreeCellRendererComponent(JTree tree, 
     Object value, boolean selected, boolean expanded, 
     boolean leaf, int row, boolean hasFocus){ 

     super.getTreeCellRendererComponent(tree, value, 
     selected, expanded, leaf, row, hasFocus); 

     JLabel label = (JLabel) this ; 

     label.setIcon(rendererIcon) ; 

     return this; 
    } 
} 

Edit: explications

Dans votre cas, il est inutile de changer le modèle. L'icône utilisée pour afficher chacun des nœuds fait partie du moteur de rendu.

L'objet de rendu du JTree n'est pas obligatoirement un JComponent. Il doit être un objet fournissant un JComponent lorsque le code appelle getTreeCellRendererComponent.

Dans votre cas, la conversion de getCellRenderer() en JLabel est simplement une chance car l'implémentation par défaut du DefaultTreeCellRenderer est une extension de JLabel. Et, en fait, comme votre moteur de rendu a appelé setIcon sur lui-même, il est normal que vos méthodes getIcon vous donnent la dernière icône que vous avez placée dans le moteur de rendu.

Code de travail complet:

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTree; 
import javax.swing.SwingUtilities; 
import javax.swing.tree.DefaultTreeCellRenderer; 

public class TestJTree { 

    private static ImageIcon iconWhite = new ImageIcon("white.jpg"); 

    private static ImageIcon iconBlack = new ImageIcon("black.jpg");; 

    public static void main(String[] args) { 
     TestJTree me = new TestJTree(); 
     me.process(); 
    } 

    private void process() { 
     SwingUtilities.invokeLater(new Runnable() { 

      public void run() { 
       initGui(); 

      } 

     }); 

    } 

    protected void initGui() { 
     JFrame frame = new JFrame("Test JTree"); 
     frame.setContentPane(new JPanel(new BorderLayout())); 

     final JTree tree = new JTree(); 
     frame.getContentPane().add(tree); 

     final CustomTreeCellRenderer renderer = new CustomTreeCellRenderer(); 
     renderer.setRendererIcon(iconWhite); 
     tree.setCellRenderer(renderer); 

     JPanel panelButtons = new JPanel(); 

     JButton buttonWhite = new JButton(""); 
     buttonWhite.setIcon(iconWhite); 
     JButton buttonBlack = new JButton(""); 
     buttonBlack.setIcon(iconBlack); 

     buttonBlack.addActionListener(new ActionListener(){ 

      public void actionPerformed(ActionEvent e) { 
       renderer.setRendererIcon(iconBlack); 
       tree.repaint(); 
      } 

     }); 

     panelButtons.add(buttonBlack); 
     panelButtons.add(buttonWhite); 
     frame.getContentPane().add(panelButtons,BorderLayout.SOUTH); 

     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(500,500); 
     frame.setVisible(true); 


    } 

    @SuppressWarnings("serial") 
    private static class CustomTreeCellRenderer extends DefaultTreeCellRenderer{ 


     ImageIcon rendererIcon; 


     public void setRendererIcon(ImageIcon myIcon){ 
      this.rendererIcon = myIcon; 
     }; 


     public Component getTreeCellRendererComponent(JTree tree, 
      Object value, boolean selected, boolean expanded, 
      boolean leaf, int row, boolean hasFocus){ 

      Component ret = super.getTreeCellRendererComponent(tree, value, 
      selected, expanded, leaf, row, hasFocus); 

      JLabel label = (JLabel) ret ; 

      label.setIcon(rendererIcon) ; 

      return ret; 
     } 
    } 
} 
+0

J'ai essayé, mais cela ne fonctionne pas. – mogli

+0

@rits Le code que j'ai ajouté fonctionne pour moi –

+0

Oui, l'icône change pour l'ensemble de l'arborescence, pas pour le nœud sélectionné. – mogli

1

un couple de points:

  1. accaparement du de la table renderer dans une méthode comme actionPerformed et modifier ce n'est pas pratique courante. Vous devez noter que le rendu est partagé, donc vous affecterez toutes les cellules de la colonne qui utilisent ce rendu
  2. même si vous définissez le Icon sur votre instance de rendu pendant actionPerformed, le rendu est toujours accessible pour peindre via la méthode getTreeCellRendererComponent , et que vous définissez toujours l'icône sur "white.png", vous n'obtiendrez jamais le "black.gif" à afficher.

Une option que vous avez est de mettre en état sur le modèle dans votre méthode actionPerformed, puis à partir du getTreeCellRendererComponent vous pouvez interroger votre modèle pour l'icône à afficher.

par exemple:

public void actionPerformed(ActionEvent ae) { 

    MyCustomTreeModel model = (MyCustomTreeModel) tree.getModel() ; 
    ... 
    model.setMyState(state); //set the state based on the action 
} 

dans le moteur de rendu:

public Component getTreeCellRendererComponent(JTree tree, 
    Object value, boolean selected, boolean expanded, 
    boolean leaf, int row, boolean hasFocus) 
{ 
    MyCustomTreeModel model = (MyCustomTreeModel) tree.getModel(); 
    .... 
    setIcon(model.getMyIconBasedOnTheStateISetInActionPerformed()); 
    return this;  
} 
+0

alors comment résoudre ce problème. l'explication avec le code est appréciée. :) – mogli