# JTree - Eigene Icons



## ByeBye 31659 (2. Mai 2006)

Hallo,

ich hab mal wieder ein Problem mit dem JTree. Wie kann ich es anstellen, dass ich eigen Icons verwende, anstatt die von Java vorgegebenen? Ausserdem möchte ich die Icons nicht nur nach Ordner und Blatt auseinanderhalten, sondern nach einem Kriterium, das ich in meiner eigenen Node-Klasse festgelegt habe.

Kann mir da jemand helfen?

Ausserdem weiß jemand wie man die Java eigenen Bilder bekommen kann? Also z.B. das Ordnersymbol des JTrees...

Für Hilfe wäre ich sehr dankbar


----------



## illaX (2. Mai 2006)

Stichwort Renderer, aber wahrscheinlich kennst du den schon. Mehr Erfahrung habe ich dort auch nicht. Habe nur einmal die Systemicons benutzt.


----------



## ByeBye 31659 (2. Mai 2006)

Gehört hab ich von Renderern schon und mich auch ein bisschen versucht, bekomme da aber nichts anständiges zustande :-(

Hat da vielleicht jemand ein Beispiel?


----------



## Thomas Darimont (2. Mai 2006)

Hallo!

Schau mal hier:
http://www.tutorials.de/forum/java/183181-jtree-plus-minus-ausblenden.html?highlight=JTree

Gruss Tom


----------



## ByeBye 31659 (2. Mai 2006)

Danke für den Link, aber der brintg mich leider nicht viel weiter, da ich auch bei den Leafs noch die Grafiken unterscheiden möchte. Also als letzter Eintrag eines Astes einmal "Auto" und in einem anderen Ast ein letzter Eintrag "Buch" und es sollen nicht beide das LeafIcon haben sondern beide unterschiedliche Icons.

So stelle ich mir das ungefähr vor:


```
tree.setCellRenderer(new DefaultTreeCellRenderer(){
	    	public void setLeafIcon(Icon arg0) {
	    		if(((MyTreeNode)aktuellesNode).isCategory() == true){
	    			super.setLeafIcon(new ImageIcon("folder.gif"));
	    		}
	    		else{
	    			super.setLeafIcon(new ImageIcon("details.gif"));
	    		}
	    	}
	    });
```

Wo der rote Text (aktuellesNode) der Node sein soll, der gerade gezeichnet wird und der blaue Text (isCategory) ist eine Methode meiner MyTreeNode Klasse, die einen Boolean zurückliefert.

Ist mein Problem soweit verständlich?


----------



## javaprogger1987 (2. Mai 2006)

Also ich würde das so lösen:

```
/**
 * <p>Überschrift: Ein TreeRenderer mit variablen Leaf-Icons</p>
 *
 * <p>Beschreibung: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Organisation: None</p>
 *
 * @author Tobias Viehweger
 * @version 1.0
 */

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.Component;

public class IconTreeRenderer extends DefaultTreeCellRenderer
{
  private boolean isCategory = false;
  private Icon leafCategoryIcon = new ImageIcon( "folder.gif" );
  private Icon leadIcon = new ImageIcon("details.gif");
  
  public IconTreeRenderer() 
  {
    
    super();
  }
  
  public Icon getLeafIcon() 
  {
    if ( isCategory )
      return leafIconCategory;
    else
      return leafIcon;
  }
  
  public Component getTreeCellRendererComponent( JTree tree, Object value,
                                                 boolean sel,
                                                 boolean expanded,
                                                 boolean leaf, int row,
                                                 boolean hasFocus ) {
    String stringValue = tree.convertValueToText( value, sel,
                                                  expanded, leaf, row, hasFocus );
    
    if (value instanceof (MyTreeNode)) //Sollte immer erfuellt sein
      isCategory = ((MyTreeNode) value).isCategory();
    
    this.hasFocus = hasFocus;
    setText( stringValue );
    if ( sel )
      setForeground( getTextSelectionColor() );
    else
      setForeground( getTextNonSelectionColor() );
    // There needs to be a way to specify disabled icons.
    if ( !tree.isEnabled() ) {
      setEnabled( false );
      if ( leaf ) {
        setDisabledIcon( getLeafIcon() );
      }
      else if ( expanded ) {
        setDisabledIcon( getOpenIcon() );
      }
      else {
        setDisabledIcon( getClosedIcon() );
      }
    }
    else {
      setEnabled( true );
      if ( leaf ) {
        setIcon( getLeafIcon() );
      }
      else if ( expanded ) {
        setIcon( getOpenIcon() );
      }
      else {
        setIcon( getClosedIcon() );
      }
    }
    setComponentOrientation( tree.getComponentOrientation() );

    selected = sel;

    return this;
  }

}
```

Erklärung:
Ich hab einfach erstmal eine neue Klasse angelegt, ich find das zu unübersichtlich, wenn man das alles in den Methoden Aufruf reinschreibt.. Deinen Code änderst du also in:
	
	
	



```
tree.setCellRenderer(new IconTreeRenderer());
```

Die Methode getTreeCellRendererComponent ist eigentlich komplett aus dem DefaultRenderer übernommen, nur der Teil 
	
	
	



```
if (value instanceof (MyTreeNode)) //Sollte immer erfuellt sein
      isCategory = ((MyTreeNode) value).isCategory();
```
 ist ergänzt, er sorgt dafür, das getLeafIcon() weiß welches Icon genommen werden soll..

Ist vermutlich eher die Q'nD-Lösung, vllt weiß Tom noch was 
Gruß
Tobias


----------



## Thomas Darimont (2. Mai 2006)

Hallo!

Ich haette das ungefaehr so gemacht:

```
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() {
            final ImageIcon CAR_ICON = new ImageIcon("c:/car.jpg");
            final ImageIcon MOTOBIKE_ICON = new ImageIcon("c:/motobike.jpg");
            public Component getTreeCellRendererComponent(JTree tree,
                    Object value, boolean sel, boolean expanded, boolean leaf,
                    int row, boolean hasFocus) {
                DefaultMutableTreeNode currentTreeNode = (DefaultMutableTreeNode) value;
                TreeEntry userObject = (TreeEntry) currentTreeNode
                        .getUserObject();
                if (Vehicle.CAR.equals(userObject.getCategory())) {
                    setLeafIcon(CAR_ICON);
                } else if (Vehicle.MOTO_BIKE.equals(userObject.getCategory())) {
                    setLeafIcon(MOTOBIKE_ICON);
                }
                return super.getTreeCellRendererComponent(tree, value, sel,
                        expanded, leaf, row, hasFocus);
            }
        };
        tree.setCellRenderer(renderer);
```

Gruss Tom


----------



## javaprogger1987 (2. Mai 2006)

Okay.. du lässt den restlichen Methodenrupf weg  
Das ist natrürlich eleganter - geht bei mir aber auch 
Nur warum castet du value erst in einen DefaultMutableTreeNode wenn du das anschließend nur als TreeEntry brauchst?http://www.google.com/search?q=allinurl:DefaultMutableTreeNode+java.sun.com&bntl=1


----------



## incertus (21. April 2011)

Hallo,

ich bin grade zufällig drüber gestolpert per Google und es hat mich mit ein paar Änderungen weitergebracht 
Diese waren leider nötig, da ich (und Netbeans) mit dem TreeEntry nichts anfangen konnten...
Trotzdem  vielen Dank an Tom.


```
private final ImageIcon BELEG_ICON = new ImageIcon("beleg.png");
       private final ImageIcon REISE_ICON = new ImageIcon("reise.png");
       tree = new JTree();
        DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() {
            @Override
            public Component getTreeCellRendererComponent(JTree tree,
                    Object value, boolean sel, boolean expanded, boolean leaf,
                    int row, boolean hasFocus) {
                DefaultMutableTreeNode currentTreeNode = (DefaultMutableTreeNode) value;
                Object userObject = (Object) currentTreeNode.getUserObject();
                if (userObject.getClass() == Beleg.class) {
                    setLeafIcon(BELEG_ICON);
                } else if (userObject.getClass() == Reise.class) {
                    setLeafIcon(REISE_ICON);
                    setClosedIcon(REISE_ICON);
                    setOpenIcon(REISE_ICON);
                }
                return super.getTreeCellRendererComponent(tree, value, sel,
                        expanded, leaf, row, hasFocus);
            }
        };
        tree.setCellRenderer(renderer);
```


----------

