Changing the icons of a JTree

Just use the methods setOpenIcon, setClosedIcon and setLeafIcon defined in the DefaultCellRenderer class.

Here’s an example.

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
      DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child 1");
      root.add(child1);
      DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child 2");
      root.add(child2);
      JTree tree = new JTree(root);
 
      DefaultTreeCellRenderer cr = new DefaultTreeCellRenderer();
      cr.setOpenIcon(new ImageIcon("openicon.jpg"));
      cr.setClosedIcon(new ImageIcon("closedicon.jpg"));
      cr.setLeafIcon(new ImageIcon("leaficon.jpg"));
  
      tree.setCellRenderer(cr);
 
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

The icons used in this program:


Displaying a popup menu when right-clicking on a JTree node

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = createNodes();
      JTree tree = new JTree(root);
 
      final TreePopup treePopup = new TreePopup(tree);
      tree.addMouseListener(new MouseAdapter() {
         public void mouseReleased (MouseEvent e) {
            if (e.isPopupTrigger()) {
               treePopup.show(e.getComponent(), e.getX(), e.getY());
            }
         }
      });
  
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static DefaultMutableTreeNode createNodes() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Java");
      
      DefaultMutableTreeNode j2se = new DefaultMutableTreeNode("J2SE");
      DefaultMutableTreeNode j2ee = new DefaultMutableTreeNode("J2EE");
      DefaultMutableTreeNode j2me = new DefaultMutableTreeNode("J2ME");
 
      j2se.add(new DefaultMutableTreeNode("http://java.sun.com/j2se/"));
      j2ee.add(new DefaultMutableTreeNode("http://java.sun.com/j2ee/"));
      j2me.add(new DefaultMutableTreeNode("http://java.sun.com/j2me/"));
 
      root.add(j2se);
      root.add(j2ee);
      root.add(j2me);
 
      return root;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}
 
class TreePopup extends JPopupMenu {
   public TreePopup(JTree tree) {
      JMenuItem itemDelete = new JMenuItem("Delete");
      JMenuItem itemAdd = new JMenuItem("Add");
      itemDelete.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.out.println("Delete child");
         }
      });
      itemAdd.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            System.out.println("Add child");
         }
      });
 
      add(itemDelete);
      add(new JSeparator());
      add(itemAdd);
   }
}

Getting an event when a selection on my JTree changes

Implement a TreeSelectionListener and add it using addTreeSelectionListener.

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = createNodes();
      JTree tree = new JTree(root);
 
      tree.addTreeSelectionListener(new TreeSelectionListener() {
         public void valueChanged(TreeSelectionEvent e) {         
            TreePath path = e.getPath();
            System.out.println(path.getLastPathComponent());     
         }
      });
 
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static DefaultMutableTreeNode createNodes() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Java");
      
      DefaultMutableTreeNode j2se = new DefaultMutableTreeNode("J2SE");
      DefaultMutableTreeNode j2ee = new DefaultMutableTreeNode("J2EE");
      DefaultMutableTreeNode j2me = new DefaultMutableTreeNode("J2ME");
 
      j2se.add(new DefaultMutableTreeNode("http://java.sun.com/j2se/"));
      j2ee.add(new DefaultMutableTreeNode("http://java.sun.com/j2ee/"));
      j2me.add(new DefaultMutableTreeNode("http://java.sun.com/j2me/"));
 
      root.add(j2se);
      root.add(j2ee);
      root.add(j2me);
 
      return root;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Adding a background image to a JTree

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
      for (int i=0; i<10; i++) {
         DefaultMutableTreeNode child = new DefaultMutableTreeNode("Child " + (i+1));
         root.add(child);
      }
      JTree tree = new JTree(root) {
         ImageIcon icon = new ImageIcon("mong.jpg");
 
         public void paint( Graphics g ) 
         { 
            // tile it
            Dimension d = this.getSize(); 
            for(int i=0; i<d.width; i+=icon.getIconWidth()) { 
               for(int j=0; j<d.height; j+=icon.getIconHeight()) { 
                  g.drawImage(icon.getImage(), i, j, null, null); 
               }
            }
 
            super.paint(g); 
         } 
      }; 
 
      tree.setOpaque( false );
  
 
      DefaultTreeCellRenderer cr = new DefaultTreeCellRenderer();
      cr.setOpaque(false);
      cr.setBackground(new Color(0, 0, 0, 0));  
      cr.setBackgroundNonSelectionColor(null);
      tree.setCellRenderer(cr);
 
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Image used: http://www.esus.com/images/mong.jpg

Adding a background image to a JTree that does not scroll

(1.3+)

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
      for (int i=0; i<100; i++) {
         DefaultMutableTreeNode child = new DefaultMutableTreeNode("Child " + (i+1));
         root.add(child);
      }
      JTree tree = new JTree(root);
 
      tree.setOpaque( false );
  
 
      DefaultTreeCellRenderer cr = new DefaultTreeCellRenderer();
      cr.setOpaque(false);
      cr.setBackground(new Color(0, 0, 0, 0));  
      cr.setBackgroundNonSelectionColor(null);
      tree.setCellRenderer(cr);
 
      ImageJScrollPane scrollpane = new ImageJScrollPane(tree);
      scrollpane.setBackgroundImage(new ImageIcon("mong.jpg"));
 
      getContentPane().add(scrollpane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}
 
class ImageJScrollPane extends JScrollPane
{
   private ImageIcon image = null;
 
   public ImageJScrollPane() {
      this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
   }
 
   public ImageJScrollPane(Component view) {
      this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
   }
 
   public ImageJScrollPane(Component view, int vsbPolicy, int hsbPolicy) {
      super(view, vsbPolicy, hsbPolicy);
      if (view instanceof JComponent) {
         ((JComponent) view).setOpaque(false);
      }
      setOpaque(false);
      getViewport().setOpaque(false);
      getViewport().setScrollMode(JViewport.BLIT_SCROLL_MODE);
   }
 
   public ImageJScrollPane(int vsbPolicy, int hsbPolicy) {
      this(null, vsbPolicy, hsbPolicy);
   }
 
   public void setBackgroundImage(ImageIcon image) {
      this.image = image;
   }
 
   public void paint(Graphics g) {
      if (image != null) {
         Rectangle rect = getViewport().getViewRect();
         for (int x=0; x<rect.width; x+=image.getIconWidth()) {
            for (int y=0; y<rect.height; y+=image.getIconHeight()) {
               g.drawImage(image.getImage(), x, y, null, null);
            }
         }
         super.paint(g);
      }
 
   }
}

Image used:

Creating a JTree without node icons

Set the OpenIcon, ClosedIcon and LeafIcon to null in a DefaultTreeCellRenderer.

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = createNodes();
      JTree tree = new JTree(root);
 
      DefaultTreeCellRenderer cr = new DefaultTreeCellRenderer();
      cr.setOpenIcon(null);
      cr.setClosedIcon(null);
      cr.setLeafIcon(null);
  
      tree.setCellRenderer(cr);
 
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static DefaultMutableTreeNode createNodes() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Java");
      
      DefaultMutableTreeNode j2se = new DefaultMutableTreeNode("J2SE");
      DefaultMutableTreeNode j2ee = new DefaultMutableTreeNode("J2EE");
      DefaultMutableTreeNode j2me = new DefaultMutableTreeNode("J2ME");
 
      j2se.add(new DefaultMutableTreeNode("http://java.sun.com/j2se/"));
      j2ee.add(new DefaultMutableTreeNode("http://java.sun.com/j2ee/"));
      j2me.add(new DefaultMutableTreeNode("http://java.sun.com/j2me/"));
 
      root.add(j2se);
      root.add(j2ee);
      root.add(j2me);
 
      return root;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Have dotted lines in a JTree

That appends on your Look & Feel – you can use three lineStyle’s:

// show hierarchy-lines
JTree#putClientProperty(“JTree.lineStyle”, “Angled”);

// show horizontal lines
JTree#putClientProperty( “JTree.lineStyle”, “Horitontal” );

// do not show any lines
JTree#putClientProperty(“JTree.lineStyle”, “None”);

Example of TreeTable

The example program about TreeTable discussed in Sun’s article Creating TreeTables: Part 2 adds unnecessary complexity. The following is a much simpler one and will get you started much quicker.

Prerequisite: Download src.zip from the above url and compile the with both programs presented here.

Main.java:

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
 
public class Main extends JFrame {
   protected MyTreeTableModel  model;
   protected JTreeTable        treeTable;
 
   public Main() {
      super("Main");
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      model     = new MyTreeTableModel();
      treeTable = new JTreeTable(model);
 
      getContentPane().add(new JScrollPane(treeTable));
 
      try {
         UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
         SwingUtilities.updateComponentTreeUI(this);
      }
      catch(Exception e) {
         e.printStackTrace();
      }
 
      pack();
      show();
   }
 
   public static void main(String[] args) {
      new Main();
   }
}

MyTreeTableModel.java:

import java.io.IOException;
import java.io.File;
import java.util.Date;
import java.util.Stack;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
import java.util.*;
 
public class MyTreeTableModel extends AbstractTreeTableModel {
 
   // Names of the columns.
   static protected String[] cNames = {"Column 1", "Column 2", 
                                       "Column 3", "Column 4"};
   // Types of the columns.
   static protected Class[]  cTypes = { TreeTableModel.class, String.class, 
                                        String.class, String.class };
   static Entry rootEntry;  
 
   /******** Entry class represents the parent and leaf nodes **********/
   static class Entry {
      private String name; 
      private boolean isLeaf;
      private Vector children = new Vector();
 
      public Entry(String name, boolean isLeaf) {
         this.name = name;
         this.isLeaf = isLeaf;
      }
 
      public Vector getChildren() {
         return children;
      }
 
      public boolean isLeaf() {
         return isLeaf;
      }
 
      public String getName() {
         return name;
      }
 
      public String toString() {
         return name;
      }
   }
 
   static {
      rootEntry = new Entry("rootentry", false);
      rootEntry.getChildren().addElement(new Entry("test1", true));
      rootEntry.getChildren().addElement(new Entry("test2", true));

      Entry subEntry1 = new Entry("subentry1", false);
      subEntry1.getChildren().addElement(new Entry("test3", true));
      subEntry1.getChildren().addElement(new Entry("test4", true));
      Entry subEntry2 = new Entry("subentry2", false);
      subEntry2.getChildren().addElement(new Entry("test5", true));
      subEntry2.getChildren().addElement(new Entry("test6", true));
      rootEntry.getChildren().addElement(subEntry1);
      rootEntry.getChildren().addElement(subEntry2); 
   }
   /*************************************/
 
   public MyTreeTableModel() { 
      super(rootEntry);
   }
 
   public int getChildCount(Object node) { 
      if (!((Entry) node).isLeaf()) {
         return ((Entry) node).getChildren().size();
      }
      return 0;
   }
 
   public Object getChild(Object node, int i) { 
      return ((Entry) node).getChildren().elementAt(i);
   }
 
   public boolean isLeaf(Object node) {
      return ((Entry) node).isLeaf();
   }
 
   public int getColumnCount() {
      return cNames.length;
   }
 
   public String getColumnName(int column) {
      return cNames[column];
   } 
 
   public Class getColumnClass(int column) {
      return cTypes[column];
   }
 
   public Object getValueAt(Object node, int column) {
      switch(column) {
         case 0:
            return node;
         case 1:
            return "value1";
         case 2:
            return "value2";
         case 3:
            return "value3";
      }
   
      return null; 
   }
}

Having a JTextArea as a node of a JTree

Main.java:

import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.net.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = createNodes();
      JTree tree = new JTree(root);
      //tree.setCellEditor(new DefaultCellEditor(new JTextField())); 
      tree.setCellRenderer(new DelegateDefaultCellRenderer());
      tree.setRowHeight(-1);
 
      getContentPane().add(new JScrollPane(tree));
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static DefaultMutableTreeNode createNodes() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode(&amp;amp;quot;Java&amp;amp;quot;);
      
      DefaultMutableTreeNode j2se = new DefaultMutableTreeNode(&amp;amp;quot;J2SE&amp;amp;quot;);
      DefaultMutableTreeNode j2ee = new DefaultMutableTreeNode(&amp;amp;quot;J2EE&amp;amp;quot;);
      DefaultMutableTreeNode j2me = new DefaultMutableTreeNode(&amp;amp;quot;J2ME&amp;amp;quot;);
 
      j2se.add(new DefaultMutableTreeNode(&amp;amp;quot;http://java.sun.com/j2se/&amp;amp;quot;));
      j2ee.add(new DefaultMutableTreeNode(&amp;amp;quot;http://java.sun.com/j2ee/&amp;amp;quot;));
      j2me.add(new DefaultMutableTreeNode(&amp;amp;quot;http://java.sun.com/j2me/&amp;amp;quot;));
 
      root.add(j2se);
      root.add(j2ee);
      root.add(j2me);
 
      return root;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}
 
class DelegateDefaultCellRenderer extends DefaultTreeCellRenderer 
{
   TextAreaRenderer taRenderer = new TextAreaRenderer();
 
   public DelegateDefaultCellRenderer() {
      taRenderer.setBackgroundNonSelectionColor(getBackgroundNonSelectionColor());
      taRenderer.setBackgroundSelectionColor(getBackgroundSelectionColor());
      taRenderer.setTextNonSelectionColor(getTextNonSelectionColor());  
      taRenderer.setTextSelectionColor(getTextSelectionColor()); 
   }
 
   public Component getTreeCellRendererComponent(JTree tree, Object value,
                                  boolean selected, boolean expanded, boolean leaf,
                                  int row, boolean hasFocus)
   {
      if (!leaf) {
         return super.getTreeCellRendererComponent(tree, value, selected, 
                                                   expanded, leaf, row, hasFocus);
      }
      else {
         return taRenderer.getTreeCellRendererComponent(tree, value, selected, 
                                                        expanded, leaf, row, hasFocus);
      }
   }
}   
 
class TextAreaRenderer extends JScrollPane implements TreeCellRenderer
{
   JTextArea textarea;
   Color backgroundNonSelectionColor;
   Color backgroundSelectionColor;
   Color textNonSelectionColor;
   Color textSelectionColor;
 
   public TextAreaRenderer() {
      textarea = new JTextArea(3, 40);
      textarea.setLineWrap(true);
      textarea.setWrapStyleWord(true);
      textarea.setBorder(new TitledBorder(&amp;amp;quot;This is a JTextArea&amp;amp;quot;));
      getViewport().add(textarea);
   }
 
   public void setBackgroundNonSelectionColor(Color c) {
      this.backgroundNonSelectionColor = c;
   }
 
   public void setBackgroundSelectionColor(Color c) {
      this.backgroundSelectionColor = c;
   }
  
   public void setTextNonSelectionColor(Color c) {
      this.textNonSelectionColor = c;
   }
  
   public void setTextSelectionColor(Color c) {
      this.textSelectionColor = c;
   }
 
   public Component getTreeCellRendererComponent(JTree tree, Object value,
                                  boolean selected, boolean expanded, boolean leaf,
                                  int row, boolean hasFocus)
   {
      if (selected) {
         setForeground(textSelectionColor);
         setBackground(backgroundSelectionColor);
         textarea.setForeground(textSelectionColor);
         textarea.setBackground(backgroundSelectionColor);
      } else {
         setForeground(textNonSelectionColor);
         setBackground(backgroundNonSelectionColor);
         textarea.setForeground(textNonSelectionColor);
         textarea.setBackground(backgroundNonSelectionColor);
      }
 
      textarea.setText(&amp;amp;quot;&amp;amp;quot;+((DefaultMutableTreeNode) value).getUserObject()); 
      textarea.setCaretPosition(0);
 
      return this;
   }
}