Swing provides support for hierarchies using a tree structure implemented via the Swing class JTree. A tree is a collection of one or more nodes. Each node is the parent of zero or more children, which are also nodes. The node that is at the base of the tree is called the root.
A node with no children is a leaf. A tree may consist of many subtrees, in which each node acts as the root for its own subtree.
A tree can be expanded (expanded nodes show their children) or collapsed (children are hidden). The way in which a collapsed or expanded node is displayed depends on the Look and Feel. When a tree expansion event occurs, the method treeExpanded() is called, identifying the node that was expanded. When a tree collapse event occurs, treeCollapsed() is called instead.
A node is selected by clicking it; this click generates a TreeSelectionEvent. Likewise, expanding or collapsing a tree generates a TreeExpansionEvent. Selecting a new node causes all nodes in a previous selection to be deselected. When a tree selection event occurs, the method valueChanged() is called. Note that this method is called for both node selection and deselection.
A node’s path is represented by an object of type TreePath. A path is an array of Object components which together uniquely identify the path from the root of the tree to a specific node. The elements are stored in the array in order from the hierarchy’s root.
Java Swing JTree Examples
Simple Jtree
[sourcecode language='java']
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
public class JTreeDemo extends JPanel implements TreeSelectionListener {
private JEditorPane htmlPane;
private JTree tree;
public JTreeDemo() {
super(new GridLayout(1, 0)); //1 row, 0 Columns
//Create the nodes.
DefaultMutableTreeNode root = new DefaultMutableTreeNode(
“Hot Java Tutorial Sites”);
createChildNodes(root);
//Create a jtree
tree = new JTree(root);
// allows one jtree node selection at a time.
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(this);
//Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(tree);
//Create the HTML viewing Editor pane.
htmlPane = new JEditorPane();
htmlPane.setEditable(false);
JScrollPane htmlView = new JScrollPane(htmlPane);
//Add the scroll panes to a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(htmlView);
Dimension minimumSize = new Dimension(100, 50);
htmlView.setMinimumSize(minimumSize);
treeView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(100);
splitPane.setPreferredSize(new Dimension(500, 300));
//Add the split pane to this panel.
add(splitPane);
}
/** Overridden valueChanged method by TreeSelectionListener interface. */
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
.getLastSelectedPathComponent();
if (node == null)
return;
Object nodeInfo = node.getUserObject();
if (node.isLeaf()) {
SiteInfo site = (SiteInfo) nodeInfo;
displayURL(site.siteURL);
}else{
displayURL(”Please select a Site Name”);
}
}
private class SiteInfo {
public String siteName;
public String siteURL;
public SiteInfo(String nameOfSite, String urlAddress) {
siteName = nameOfSite;
siteURL = urlAddress;
}
public String toString() {
return siteName;
}
}
private void displayURL(String url) {
if (url != null) {
htmlPane.setText(url);
} else { //null url
htmlPane.setText(”Page Not Found”);
}
}
private void createChildNodes(DefaultMutableTreeNode root) {
DefaultMutableTreeNode category = null;
DefaultMutableTreeNode sites = null;
category = new DefaultMutableTreeNode(”Java Certification Sites”);
root.add(category);
sites = new DefaultMutableTreeNode(new SiteInfo(”Java Rabbit”,
“http://www.javarabbit.com”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”Dan Chisholm”,
“www.danchisholm.net”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”Java Prepare”,
“www.javaprepare.com”));
category.add(sites);
category = new DefaultMutableTreeNode(”Java Resources Sites”);
root.add(category);
sites = new DefaultMutableTreeNode(new SiteInfo(”Java World”,
“http://www.javaworld.com/”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”Jaggle”,
“http://www.jaagle.com/”));
category.add(sites);
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event dispatch thread.
*/
private static void createAndShowGUI() {
JFrame frame = new JFrame(”JTree Demo”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JTreeDemo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application’s GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
[/sourcecode]
JTree DefaultTreeCellRenderer Usage
The below jtree program demonstrates Addition of a custom Icon to the leaf nodes
[sourcecode language='java']
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;
public class JTreeIconDemo extends JPanel implements TreeSelectionListener {
private JEditorPane htmlPane;
private JTree tree;
public JTreeIconDemo() {
super(new GridLayout(1, 0)); //1 row, 0 Columns
//Create the nodes.
DefaultMutableTreeNode root = new DefaultMutableTreeNode(
“Hot Java Tutorial Sites”);
createChildNodes(root);
//Create a jtree
tree = new JTree(root);
// allows one jtree node selection at a time.
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
// Set the icon for leaf nodes.
ImageIcon leafIcon = createImageIcon(”leaf.gif”);
if (leafIcon != null) {
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
renderer.setLeafIcon(leafIcon);
tree.setCellRenderer(renderer);
} else {
System.err.println(”Leaf icon missing; using default.”);
}
tree.addTreeSelectionListener(this);
//Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(tree);
//Create the HTML viewing Editor pane.
htmlPane = new JEditorPane();
htmlPane.setEditable(false);
JScrollPane htmlView = new JScrollPane(htmlPane);
//Add the scroll panes to a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(htmlView);
Dimension minimumSize = new Dimension(100, 50);
htmlView.setMinimumSize(minimumSize);
treeView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(100);
splitPane.setPreferredSize(new Dimension(500, 300));
//Add the split pane to this panel.
add(splitPane);
}
/** Returns an ImageIcon, or null if the path was invalid. */
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = JTreeIconDemo.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println(”Couldn’t find file: ” + path);
return null;
}
}
/** Overridden valueChanged method by TreeSelectionListener interface. */
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
.getLastSelectedPathComponent();
if (node == null)
return;
Object nodeInfo = node.getUserObject();
if (node.isLeaf()) {
SiteInfo site = (SiteInfo) nodeInfo;
displayURL(site.siteURL);
}else{
displayURL(”Please select a Site Name”);
}
}
private class SiteInfo {
public String siteName;
public String siteURL;
public SiteInfo(String nameOfSite, String urlAddress) {
siteName = nameOfSite;
siteURL = urlAddress;
}
public String toString() {
return siteName;
}
}
private void displayURL(String url) {
if (url != null) {
htmlPane.setText(url);
} else { //null url
htmlPane.setText(”Page Not Found”);
}
}
private void createChildNodes(DefaultMutableTreeNode root) {
DefaultMutableTreeNode category = null;
DefaultMutableTreeNode sites = null;
category = new DefaultMutableTreeNode(”Java Certification Sites”);
root.add(category);
sites = new DefaultMutableTreeNode(new SiteInfo(”Java Rabbit”,
“http://www.javarabbit.com”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”Dan Chisholm”,
“www.danchisholm.net”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”Java Prepare”,
“www.javaprepare.com”));
category.add(sites);
category = new DefaultMutableTreeNode(”Java Resources Sites”);
root.add(category);
sites = new DefaultMutableTreeNode(new SiteInfo(”Java World”,
“http://www.javaworld.com/”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”Jaggle”,
“http://www.jaagle.com/”));
category.add(sites);
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event dispatch thread.
*/
private static void createAndShowGUI() {
JFrame frame = new JFrame(”JTree Demo”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JTreeIconDemo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application’s GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
[/sourcecode]
The Icon for the Above JTree Source Code is : ![]()
JTree getTreeCellRendererComponent Usage
The below jtree program demonstrates Addition of a custom Icon to the leaf nodes based on the Node value and setting jtree tooltip text
[sourcecode language='java']
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeSelectionModel;
public class JTreeIconDemo2 extends JPanel implements TreeSelectionListener {
private JEditorPane htmlPane;
private JTree tree;
public JTreeIconDemo2() {
super(new GridLayout(1, 0)); // 1 row, 0 Columns
// Create the nodes.
DefaultMutableTreeNode root = new DefaultMutableTreeNode(
“Hot Java Tutorial Sites”);
createChildNodes(root);
// Create a jtree
tree = new JTree(root);
// allows one jtree node selection at a time.
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
// Enable tool tips.
ToolTipManager.sharedInstance().registerComponent(tree);
// Set the icon for leaf nodes.
ImageIcon leafIcon = createImageIcon(”leaf.gif”);
if (leafIcon != null) {
CustomTreeCellRenderer renderer = new CustomTreeCellRenderer(
leafIcon);
tree.setCellRenderer(renderer);
} else {
System.err.println(”Leaf icon missing; using default.”);
}
tree.addTreeSelectionListener(this);
// Create the scroll pane and add the tree to it.
JScrollPane treeView = new JScrollPane(tree);
// Create the HTML viewing Editor pane.
htmlPane = new JEditorPane();
htmlPane.setEditable(false);
JScrollPane htmlView = new JScrollPane(htmlPane);
// Add the scroll panes to a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(htmlView);
Dimension minimumSize = new Dimension(100, 50);
htmlView.setMinimumSize(minimumSize);
treeView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(100);
splitPane.setPreferredSize(new Dimension(300, 300));
// Add the split pane to this panel.
add(splitPane);
}
/** Returns an ImageIcon, or null if the path was invalid. */
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = JTreeIconDemo2.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println(”Couldn’t find file: ” + path);
return null;
}
}
/** Overridden valueChanged method by TreeSelectionListener interface. */
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
.getLastSelectedPathComponent();
if (node == null)
return;
Object nodeInfo = node.getUserObject();
if (node.isLeaf()) {
SiteInfo site = (SiteInfo) nodeInfo;
displayURL(site.siteURL);
} else {
displayURL(”Please select a Site Name”);
}
}
private class SiteInfo {
public String siteName;
public String siteURL;
public SiteInfo(String nameOfSite, String urlAddress) {
siteName = nameOfSite;
siteURL = urlAddress;
}
public String toString() {
return siteName;
}
public String getSiteName() {
return siteName;
}
}
private void displayURL(String url) {
if (url != null) {
htmlPane.setText(url);
} else { // null url
htmlPane.setText(”Page Not Found”);
}
}
private void createChildNodes(DefaultMutableTreeNode root) {
DefaultMutableTreeNode category = null;
DefaultMutableTreeNode sites = null;
category = new DefaultMutableTreeNode(”Java Certification Sites”);
root.add(category);
sites = new DefaultMutableTreeNode(new SiteInfo(”SCJP – Java Rabbit”,
“http://www.javarabbit.com”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”SCJP – Dan Chisholm”,
“www.danchisholm.net”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”SCJP – Java Prepare”,
“www.javaprepare.com”));
category.add(sites);
category = new DefaultMutableTreeNode(”Java Resources Sites”);
root.add(category);
sites = new DefaultMutableTreeNode(new SiteInfo(”Java World”,
“http://www.javaworld.com/”));
category.add(sites);
sites = new DefaultMutableTreeNode(new SiteInfo(”Jaggle”,
“http://www.jaagle.com/”));
category.add(sites);
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event dispatch thread.
*/
private static void createAndShowGUI() {
JFrame frame = new JFrame(”JTree Demo”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JTreeIconDemo2());
// Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Schedule a job for the event dispatch thread:
// creating and showing this application’s GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private class CustomTreeCellRenderer extends DefaultTreeCellRenderer {
Icon leafIcon;
public CustomTreeCellRenderer(Icon icon) {
leafIcon = icon;
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded,
leaf, row, hasFocus);
if (leaf && isSCJPSite(value)) { // You can have any condition
// Here on the value (node)
setIcon(leafIcon);
setToolTipText(”This is an SCJP Site”);
} else {
setToolTipText(null); // no tool tip
}
return this;
}
protected boolean isSCJPSite(Object value) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
SiteInfo siteNode = (SiteInfo) (node.getUserObject());
String title = siteNode.getSiteName();
if (title.indexOf(”SCJP”) >= 0) {
return true;
}
return false;
}
}
}
[/sourcecode]
The Icon for the Above JTree Code is : ![]()
Custom Models and Dynamic Tree
A JSplitPane contains two components separated by a horizontal or vertical divider. The divider’s appearance depends on the Look and Feel. A divider can be dragged to the desired position. Typically, a split pane consists of two components and either or both of those can also be a split pane.
[sourcecode language='java']
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
public class DynamicJTreeDemo extends JFrame implements ActionListener {
private static int newNodeCounter;
private static String ADD_ACTION = “add”;
private static String REMOVE_ACTION = “remove”;
private static String CLEAR_ACTION = “clear”;
private DefaultMutableTreeNode rootNode;
private DefaultTreeModel defaultTreeModel;
private JTree jtree;
public DynamicJTreeDemo() {
// Creates the JTree
rootNode = new DefaultMutableTreeNode(”Root Node”);
defaultTreeModel = new DefaultTreeModel(rootNode);
jtree = new JTree(defaultTreeModel);
jtree.setEditable(true);
jtree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
jtree.setShowsRootHandles(true);
initializeTree();
JScrollPane jscrollPane = new JScrollPane(jtree);
JPanel treePanel = new JPanel();
treePanel.add(jscrollPane);
JPanel buttonPanel = new JPanel();
JButton jbnAdd = new JButton(”Add”);
jbnAdd.setActionCommand(ADD_ACTION);
jbnAdd.addActionListener(this);
buttonPanel.add(jbnAdd, BorderLayout.WEST);
JButton jbnRemove = new JButton(”Remove”);
jbnRemove.setActionCommand(REMOVE_ACTION);
jbnRemove.addActionListener(this);
buttonPanel.add(jbnRemove, BorderLayout.SOUTH);
JButton jbnClear = new JButton(”Clear”);
jbnClear.setActionCommand(CLEAR_ACTION);
jbnClear.addActionListener(this);
buttonPanel.add(jbnClear, BorderLayout.EAST);
JSplitPane jsplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
treePanel, buttonPanel);
//Lay everything out.
// setPreferredSize(new Dimension(300, 150));
getContentPane().add(jsplitPane);
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals(ADD_ACTION)) {
DefaultMutableTreeNode parentNode = null;
TreePath treePath = jtree.getSelectionPath();
if (treePath == null) {
parentNode = rootNode;
} else {
parentNode = (DefaultMutableTreeNode) (treePath
.getLastPathComponent());
}
newNodeCounter++;
addObject(parentNode, “New Node ” + newNodeCounter, true);
} else if (command.equals(REMOVE_ACTION)) {
TreePath treePath = jtree.getSelectionPath();
if (treePath != null) {
DefaultMutableTreeNode curNode = (DefaultMutableTreeNode) (treePath
.getLastPathComponent());
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) (curNode
.getParent());
if (parent != null) {
defaultTreeModel.removeNodeFromParent(curNode);
return;
}
}
} else if (command.equals(CLEAR_ACTION)) {
rootNode.removeAllChildren();
defaultTreeModel.reload();
}
}
private static void createAndShowGUI() {
DynamicJTreeDemo dynamicJTreeDemo = new DynamicJTreeDemo();
dynamicJTreeDemo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dynamicJTreeDemo.setTitle(”Dynamic JTree Demo”);
dynamicJTreeDemo.pack();
dynamicJTreeDemo.setVisible(true);
}
public void initializeTree() {
String p1 = new String(”Parent 1″); //p1 = Parent 1
String p2 = new String(”Parent 2″);
String c1 = new String(”Child 1″);
String c2 = new String(”Child 2″);
DefaultMutableTreeNode p1Node = null, p2Node = null;
p1Node = addObject(null, p1, false);
p2Node = addObject(null, p2, false);
addObject(p1Node, c1, false);
addObject(p1Node, c2, false);
addObject(p2Node, c1, false);
addObject(p2Node, c2, false);
}
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
Object child, boolean isVisible) {
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);
if (parent == null) {
parent = rootNode;
}
defaultTreeModel.insertNodeInto(childNode, parent, parent
.getChildCount());
if (isVisible) {
jtree.scrollPathToVisible(new TreePath(childNode.getPath()));
}
return childNode;
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
[/sourcecode]











I tried to compile your example and basically everything is fine except for the variable
“amp” which is in your JTreeIconDemo2 class? This must be a typo.
Thanks for the example
Dennis
@Dennis : hi dennis. The amp’s in the code are basically the “&” symbol. Sometimes html treats & symbol as & when rendering the code using the Syntax Highlighter plugin. PLease replace the amp with a logical operator &.
For example,
In line 203 of JTreeIconDemo2,
if (leaf && isSCJPSite(value)) {
becomes
if (leaf && isSCJPSite(value)) {
Sorry for the Inconvenience caused.
Leave a Reply