Java Tutorial/Swing/JTree Node
Содержание
- 1 Adding a Node to a JTree Component
- 2 A JTree subclass that displays the tree of AWT or Swing component that make up a GUI
- 3 CheckBox Tree node
- 4 Converting All Nodes in a JTree Component to a TreePath Array
- 5 Delete tree node
- 6 Expanding or Collapsing All Nodes in a JTree Component
- 7 Expression Tree
- 8 Get child count, depth, leaf count
- 9 Get path for all expanded or not expanded tree pathes
- 10 JTree node mouse click event
- 11 JTree root cannot be removed with removeNodeFromParent(), use DefaultTreeModel.setRoot() to remove the root
- 12 Removing a Node to a JTree Component
- 13 Searching node in a JTree
- 14 Swing Tree
- 15 Tree with custom icon
Adding a Node to a JTree Component
<source lang="java">
import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; public class Main {
public static void main(String[] argv) throws Exception { JTree tree = new JTree(); DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); TreePath path = tree.getSelectionPath(); MutableTreeNode node = (MutableTreeNode) path.getLastPathComponent(); MutableTreeNode newNode = new DefaultMutableTreeNode("green"); model.insertNodeInto(newNode, node, node.getChildCount()); }
}</source>
A JTree subclass that displays the tree of AWT or Swing component that make up a GUI
<source lang="java">
/*
* Copyright (c) 2004 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 3nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose, * including teaching and use in open-source projects. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book, * please visit http://www.davidflanagan.ru/javaexamples3. */
import java.awt.BorderLayout; import java.awt.ruponent; import java.awt.Container; import java.awt.Font; import java.awt.Point; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.event.TreeModelListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; /**
* This class is a JTree subclass that displays the tree of AWT or Swing * component that make up a GUI. */
public class ComponentTree extends JTree {
/** * All this constructor method has to do is set the TreeModel and * TreeCellRenderer objects for the tree. It is these classes (defined below) * that do all the real work. */ public ComponentTree(Component c) { super(new ComponentTreeModel(c)); setCellRenderer(new ComponentCellRenderer(getCellRenderer())); } /** * The TreeModel class puts hierarchical data in a form that the JTree can * display. This implementation interprets the containment hierarchy of a * Component for display by the ComponentTree class. Note that any kind of * Object can be a node in the tree, as long as the TreeModel knows how to * handle it. */ static class ComponentTreeModel implements TreeModel { Component root; // The root object of the tree // Constructor: just remember the root object public ComponentTreeModel(Component root) { this.root = root; } // Return the root of the tree public Object getRoot() { return root; } // Is this node a leaf? (Leaf nodes are displayed differently by JTree) // Any node that isn"t a container is a leaf, since they cannot have // children. We also define containers with no children as leaves. public boolean isLeaf(Object node) { if (!(node instanceof Container)) return true; Container c = (Container) node; return c.getComponentCount() == 0; } // How many children does this node have? public int getChildCount(Object node) { if (node instanceof Container) { Container c = (Container) node; return c.getComponentCount(); } return 0; } // Return the specified child of a parent node. public Object getChild(Object parent, int index) { if (parent instanceof Container) { Container c = (Container) parent; return c.getComponent(index); } return null; } // Return the index of the child node in the parent node public int getIndexOfChild(Object parent, Object child) { if (!(parent instanceof Container)) return -1; Container c = (Container) parent; Component[] children = c.getComponents(); if (children == null) return -1; for (int i = 0; i < children.length; i++) { if (children[i] == child) return i; } return -1; } // This method is only required for editable trees, so it is not // implemented here. public void valueForPathChanged(TreePath path, Object newvalue) { } // This TreeModel never fires any events (since it is not editable) // so event listener registration methods are left unimplemented public void addTreeModelListener(TreeModelListener l) { } public void removeTreeModelListener(TreeModelListener l) { } } /** * A TreeCellRenderer displays each node of a tree. The default renderer * displays arbitrary Object nodes by calling their toString() method. The * Component.toString() method returns long strings with extraneous * information. Therefore, we use this "wrapper" implementation of * TreeCellRenderer to convert nodes from Component objects to useful String * values before passing those String values on to the default renderer. */ static class ComponentCellRenderer implements TreeCellRenderer { TreeCellRenderer renderer; // The renderer we are a wrapper for // Constructor: just remember the renderer public ComponentCellRenderer(TreeCellRenderer renderer) { this.renderer = renderer; } // This is the only TreeCellRenderer method. // Compute the string to display, and pass it to the wrapped renderer public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { String newvalue = value.getClass().getName(); // Component type String name = ((Component) value).getName(); // Component name if (name != null) newvalue += " (" + name + ")"; // unless null // Use the wrapped renderer object to do the real work return renderer.getTreeCellRendererComponent(tree, newvalue, selected, expanded, leaf, row, hasFocus); } } /** * This main() method demonstrates the use of the ComponentTree class: it puts * a ComponentTree component in a Frame, and uses the ComponentTree to display * its own GUI hierarchy. It also adds a TreeSelectionListener to display * additional information about each component as it is selected */ public static void main(String[] args) { // Create a frame for the demo, and handle window close requests JFrame frame = new JFrame("ComponentTree Demo"); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); // Create a scroll pane and a "message line" and add them to the // center and bottom of the frame. JScrollPane scrollpane = new JScrollPane(); final JLabel msgline = new JLabel(" "); frame.getContentPane().add(scrollpane, BorderLayout.CENTER); frame.getContentPane().add(msgline, BorderLayout.SOUTH); // Now create the ComponentTree object, specifying the frame as the // component whose tree is to be displayed. Also set the tree"s font. JTree tree = new ComponentTree(frame); tree.setFont(new Font("SansSerif", Font.BOLD, 12)); // Only allow a single item in the tree to be selected at once tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); // Add an event listener for notifications when // the tree selection state changes. tree.addTreeSelectionListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { // Tree selections are referred to by "path" // We only care about the last node in the path TreePath path = e.getPath(); Component c = (Component) path.getLastPathComponent(); // Now we know what component was selected, so // display some information about it in the message line if (c.isShowing()) { Point p = c.getLocationOnScreen(); msgline.setText("x: " + p.x + " y: " + p.y + " width: " + c.getWidth() + " height: " + c.getHeight()); } else { msgline.setText("component is not showing"); } } }); // Now that we"ve set up the tree, add it to the scrollpane scrollpane.setViewportView(tree); // Finally, set the size of the main window, and pop it up. frame.setSize(600, 400); frame.setVisible(true); }
}</source>
CheckBox Tree node
<source lang="java">
import java.awt.ruponent; import javax.swing.DefaultCellEditor; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; class TrueFalseTreeNodeData {
protected final String value; protected boolean booleanValue; public TrueFalseTreeNodeData(String quest) { value = quest; } public String getQuestion() { return value; } public boolean getAnswer() { return booleanValue; } public void setAnswer(boolean ans) { booleanValue = ans; } public String toString() { return value + " = " + booleanValue; }
} public class TreeTest extends JFrame {
protected final static String[] questions = { "A","B","C" }; public static void main(String[] args) { TreeTest tt = new TreeTest(); tt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); tt.setSize(500, 200); tt.setVisible(true); } public TreeTest() { super(); JTree tree = new JTree(getRootNode()) { public boolean isPathEditable(TreePath path) { Object comp = path.getLastPathComponent(); if (comp instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) comp; Object userObject = node.getUserObject(); if (userObject instanceof TrueFalseTreeNodeData) { return true; } } return false; } }; QuestionCellRenderer renderer = new QuestionCellRenderer(); tree.setCellRenderer(renderer); QuestionCellEditor editor = new QuestionCellEditor(); tree.setCellEditor(editor); tree.setEditable(true); JScrollPane jsp = new JScrollPane(tree); getContentPane().add(jsp); } protected MutableTreeNode getRootNode() { DefaultMutableTreeNode root, child; TrueFalseTreeNodeData question; root = new DefaultMutableTreeNode("Root"); for (int i = 0; i < questions.length; i++) { question = new TrueFalseTreeNodeData(questions[i]); child = new DefaultMutableTreeNode(question); root.add(child); } return root; }
} class QuestionCellRenderer extends DefaultTreeCellRenderer {
protected JCheckBox checkBoxRenderer = new JCheckBox(); public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { if (value instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; Object userObject = node.getUserObject(); if (userObject instanceof TrueFalseTreeNodeData) { TrueFalseTreeNodeData question = (TrueFalseTreeNodeData) userObject; prepareQuestionRenderer(question, selected); return checkBoxRenderer; } } return super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); } protected void prepareQuestionRenderer(TrueFalseTreeNodeData tfq, boolean selected) { checkBoxRenderer.setText(tfq.getQuestion()); checkBoxRenderer.setSelected(tfq.getAnswer()); if (selected) { checkBoxRenderer.setForeground(getTextSelectionColor()); checkBoxRenderer.setBackground(getBackgroundSelectionColor()); } else { checkBoxRenderer.setForeground(getTextNonSelectionColor()); checkBoxRenderer.setBackground(getBackgroundNonSelectionColor()); } }
} class QuestionCellEditor extends DefaultCellEditor {
protected TrueFalseTreeNodeData nodeData; public QuestionCellEditor() { super(new JCheckBox()); } public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) { JCheckBox editor = null; nodeData = getQuestionFromValue(value); if (nodeData != null) { editor = (JCheckBox) (super.getComponent()); editor.setText(nodeData.getQuestion()); editor.setSelected(nodeData.getAnswer()); } return editor; } public static TrueFalseTreeNodeData getQuestionFromValue(Object value) { if (value instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; Object userObject = node.getUserObject(); if (userObject instanceof TrueFalseTreeNodeData) { return (TrueFalseTreeNodeData) userObject; } } return null; } public Object getCellEditorValue() { JCheckBox editor = (JCheckBox) (super.getComponent()); nodeData.setAnswer(editor.isSelected()); return nodeData; }
}</source>
Converting All Nodes in a JTree Component to a TreePath Array
<source lang="java">
import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class Main {
public TreePath[] getPaths(JTree tree, boolean expanded) { TreeNode root = (TreeNode) tree.getModel().getRoot(); List<TreePath> list = new ArrayList<TreePath>(); getPaths(tree, new TreePath(root), expanded, list); return (TreePath[]) list.toArray(new TreePath[list.size()]); } public void getPaths(JTree tree, TreePath parent, boolean expanded, List<TreePath> list) { if (expanded && !tree.isVisible(parent)) { return; } list.add(parent); TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration e = node.children(); e.hasMoreElements();) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); getPaths(tree, path, expanded, list); } } }
}</source>
Delete tree node
<source lang="java">
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; public class DeleteNodes extends JFrame {
protected JTree tree; public static void main(String[] args) { DeleteNodes dn = new DeleteNodes(new JTree()); dn.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); dn.setSize(400, 300); dn.setVisible(true); } public DeleteNodes(JTree jt) { super(); tree = jt; getContentPane().add(tree); tree.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent event) { if (((event.getModifiers() & InputEvent.BUTTON3_MASK) != 0) && (tree.getSelectionCount() > 0)) { showMenu(event.getX(), event.getY()); } } }); } protected void showMenu(int x, int y) { JPopupMenu popup = new JPopupMenu(); JMenuItem mi = new JMenuItem("Delete"); TreePath path = tree.getSelectionPath(); Object node = path.getLastPathComponent(); if (node == tree.getModel().getRoot()) { mi.setEnabled(false); } popup.add(mi); mi.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { deleteSelectedItems(); } }); popup.show(tree, x, y); } protected void deleteSelectedItems() { DefaultMutableTreeNode node; DefaultTreeModel model = (DefaultTreeModel) (tree.getModel()); TreePath[] paths = tree.getSelectionPaths(); for (int i = 0; i < paths.length; i++) { node = (DefaultMutableTreeNode) (paths[i].getLastPathComponent()); model.removeNodeFromParent(node); } }
}</source>
Expanding or Collapsing All Nodes in a JTree Component
<source lang="java">
import java.util.Enumeration; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class Main {
public void expandAll(JTree tree) { TreeNode root = (TreeNode) tree.getModel().getRoot(); expandAll(tree, new TreePath(root)); } private void expandAll(JTree tree, TreePath parent) { TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration e = node.children(); e.hasMoreElements();) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); expandAll(tree, path); } } tree.expandPath(parent); // tree.collapsePath(parent); }
}</source>
Expression Tree
<source lang="java">
import java.util.Enumeration; import java.util.Stack; import javax.swing.JFrame; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; public class ExpressionTree extends JFrame {
public ExpressionTree() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); DefaultMutableTreeNode root = new DefaultMutableTreeNode("+"); root.add(new DefaultMutableTreeNode(new Integer(3))); DefaultMutableTreeNode node = new DefaultMutableTreeNode("*"); node.add(new DefaultMutableTreeNode(new Integer(4))); node.add(new DefaultMutableTreeNode(new Integer(5))); root.add(node); JTree tree = new JTree(root); getContentPane().add(tree); pack(); setVisible(true); Stack stack = new Stack(); Enumeration e = root.postorderEnumeration(); while (e.hasMoreElements()) { DefaultMutableTreeNode node1 = (DefaultMutableTreeNode) (e.nextElement()); Object obj = node1.getUserObject(); if (obj instanceof Integer) { stack.push(obj); } else { String operator = (String) obj; Integer v1 = (Integer) stack.pop(); Integer v2 = (Integer) stack.pop(); if (operator.equals("+")) { stack.push(new Integer(v2.intValue() + v1.intValue())); } else { stack.push(new Integer(v2.intValue() * v1.intValue())); } } } System.out.println(stack.pop()); } public static void main(String[] args) { ExpressionTree t = new ExpressionTree(); }
}</source>
Get child count, depth, leaf count
<source lang="java">
import javax.swing.JFrame; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; public class MainClass extends JFrame {
public MainClass() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); DefaultMutableTreeNode root = new DefaultMutableTreeNode("+"); root.add(new DefaultMutableTreeNode(new Integer(3))); DefaultMutableTreeNode node = new DefaultMutableTreeNode("*"); node.add(new DefaultMutableTreeNode(new Integer(4))); node.add(new DefaultMutableTreeNode(new Integer(5))); root.add(node); JTree tree = new JTree(root); getContentPane().add(tree); pack(); setVisible(true); System.out.println("The root has " + root.getChildCount() + " children"); System.out.println("The tree"s depth is " + root.getDepth()); System.out.println("The tree has " + root.getLeafCount() + " leaves"); System.out.println(""Root" is really a root? " + root.isRoot()); System.out.println("Root"s userObject: " + root.toString()); } public static void main(String[] args) { MainClass t = new MainClass(); }
}</source>
Get path for all expanded or not expanded tree pathes
<source lang="java">
import java.util.Enumeration; import java.util.List; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class Main {
public void getPaths(JTree tree, TreePath parent, boolean expanded, List<TreePath> list) { if (expanded && !tree.isVisible(parent)) { return; } list.add(parent); TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration e = node.children(); e.hasMoreElements();) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); getPaths(tree, path, expanded, list); } } }
}</source>
JTree node mouse click event
<source lang="java">
import java.awt.BorderLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.ScrollPaneConstants; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; public class MainClass {
public static void main(String[] a) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(new JTreeEvents()); f.setSize(500, 500); f.setVisible(true); }
} class JTreeEvents extends JPanel {
JTree tree; JTextField jtf; public JTreeEvents() { setLayout(new BorderLayout()); DefaultMutableTreeNode top = new DefaultMutableTreeNode("Options"); DefaultMutableTreeNode a = new DefaultMutableTreeNode("A"); top.add(a); a.add(new DefaultMutableTreeNode("A1")); a.add(new DefaultMutableTreeNode("A2")); DefaultMutableTreeNode b = new DefaultMutableTreeNode("B"); top.add(b); b.add(new DefaultMutableTreeNode("B1")); b.add(new DefaultMutableTreeNode("B2")); b.add(new DefaultMutableTreeNode("B3")); tree = new JTree(top); int v = ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; int h = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED; JScrollPane jsp = new JScrollPane(tree, v, h); add(jsp, BorderLayout.CENTER); jtf = new JTextField("", 20); add(jtf, BorderLayout.SOUTH); tree.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { doMouseClicked(me); } }); } void doMouseClicked(MouseEvent me) { TreePath tp = tree.getPathForLocation(me.getX(), me.getY()); if (tp != null) jtf.setText(tp.toString()); else jtf.setText(""); }
}</source>
JTree root cannot be removed with removeNodeFromParent(), use DefaultTreeModel.setRoot() to remove the root
<source lang="java">
import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultTreeModel; public class TreeRootRemove {
public static void main(String[] argv) { JTree tree = new JTree(); DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); model.setRoot(null); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(tree)); frame.setSize(380, 320); frame.setLocationRelativeTo(null); frame.setVisible(true); }
}</source>
Removing a Node to a JTree Component
<source lang="java">
import javax.swing.JTree; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; public class Main {
public static void main(String[] argv) throws Exception { JTree tree = new JTree(); DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); TreePath path = tree.getSelectionPath(); MutableTreeNode node = (MutableTreeNode) path.getLastPathComponent(); model.removeNodeFromParent(node); model.setRoot(null); }
}</source>
Searching node in a JTree
<source lang="java">
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Enumeration; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class EditableTree extends JFrame {
private DefaultMutableTreeNode m_rootNode = new DefaultMutableTreeNode("AA"); private DefaultTreeModel m_model = new DefaultTreeModel(m_rootNode); private JTree m_tree = new JTree(m_model); private JButton m_addButton = new JButton("Add Node"); private JButton m_delButton = new JButton("Delete Node"); private JButton m_searchButton = new JButton("Search Node"); private JButton m_searchAndDeleteButton = new JButton("Search and Delete Node"); private JTextField m_searchText; public EditableTree() { DefaultMutableTreeNode forums = new DefaultMutableTreeNode("A"); forums.add(new DefaultMutableTreeNode("B")); DefaultMutableTreeNode articles = new DefaultMutableTreeNode("E"); articles.add(new DefaultMutableTreeNode("F")); DefaultMutableTreeNode examples = new DefaultMutableTreeNode("G"); examples.add(new DefaultMutableTreeNode("H")); m_rootNode.add(forums); m_rootNode.add(articles); m_rootNode.add(examples); m_tree.setEditable(true); m_tree.setSelectionRow(0); JScrollPane scrollPane = new JScrollPane(m_tree); getContentPane().add(scrollPane, BorderLayout.CENTER); JPanel panel = new JPanel(); m_addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree .getLastSelectedPathComponent(); if (selNode == null) { return; } DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New Node"); m_model.insertNodeInto(newNode, selNode, selNode.getChildCount()); TreeNode[] nodes = m_model.getPathToRoot(newNode); TreePath path = new TreePath(nodes); m_tree.scrollPathToVisible(path); m_tree.setSelectionPath(path); m_tree.startEditingAtPath(path); } }); panel.add(m_addButton); m_delButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree .getLastSelectedPathComponent(); removeNode(selNode); } }); panel.add(m_delButton); JPanel searchPanel = new JPanel(); searchPanel.setBorder(BorderFactory.createEtchedBorder()); m_searchText = new JTextField(10); searchPanel.add(m_searchText); m_searchButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode node = searchNode(m_searchText.getText()); if (node != null) { TreeNode[] nodes = m_model.getPathToRoot(node); TreePath path = new TreePath(nodes); m_tree.scrollPathToVisible(path); m_tree.setSelectionPath(path); } else { System.out.println("Node with string " + m_searchText.getText() + " not found"); } } }); searchPanel.add(m_searchButton); m_searchAndDeleteButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode node = searchNode(m_searchText.getText()); if (node != null) { removeNode(node); } else { System.out.println("Node with string " + m_searchText.getText() + " not found"); } } }); searchPanel.add(m_searchAndDeleteButton); panel.add(searchPanel); getContentPane().add(panel, BorderLayout.SOUTH); setSize(700, 400); setVisible(true); } public DefaultMutableTreeNode searchNode(String nodeStr) { DefaultMutableTreeNode node = null; Enumeration e = m_rootNode.breadthFirstEnumeration(); while (e.hasMoreElements()) { node = (DefaultMutableTreeNode) e.nextElement(); if (nodeStr.equals(node.getUserObject().toString())) { return node; } } return null; } public void removeNode(DefaultMutableTreeNode selNode) { if (selNode == null) { return; } MutableTreeNode parent = (MutableTreeNode) (selNode.getParent()); if (parent == null) { return; } MutableTreeNode toBeSelNode = getSibling(selNode); if (toBeSelNode == null) { toBeSelNode = parent; } TreeNode[] nodes = m_model.getPathToRoot(toBeSelNode); TreePath path = new TreePath(nodes); m_tree.scrollPathToVisible(path); m_tree.setSelectionPath(path); m_model.removeNodeFromParent(selNode); } private MutableTreeNode getSibling(DefaultMutableTreeNode selNode) { MutableTreeNode sibling = (MutableTreeNode) selNode.getPreviousSibling(); if (sibling == null) { sibling = (MutableTreeNode) selNode.getNextSibling(); } return sibling; } public static void main(String[] arg) { EditableTree editableTree = new EditableTree(); }
}</source>
Swing Tree
<source lang="java">
import java.awt.BorderLayout; import java.awt.ruponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreePath; public class SwingTree extends JFrame {
JTextField textField = new JTextField(); JScrollPane scrollPane = new JScrollPane(); JTree tree; Renderer renderer = new Renderer(); DefaultMutableTreeNode nba = new DefaultMutableTreeNode("National Basketball Association"); DefaultMutableTreeNode western = new DefaultMutableTreeNode("Western Conference"); DefaultMutableTreeNode pacific = new DefaultMutableTreeNode("Pacific Division Teams");
DefaultMutableTreeNode midwest = new DefaultMutableTreeNode("Midwest Division Teams"); DefaultMutableTreeNode denver = new DefaultMutableTreeNode("Denver"); DefaultMutableTreeNode eastern = new DefaultMutableTreeNode("Eastern Conference"); DefaultMutableTreeNode atlantic = new DefaultMutableTreeNode("Atlantic Division Teams"); DefaultMutableTreeNode central = new DefaultMutableTreeNode("Central Division Teams"); public SwingTree() { nba.add(western); nba.add(eastern); western.add(pacific); western.add(midwest); eastern.add(atlantic); eastern.add(central); pacific.add(new DefaultMutableTreeNode("Los Angeles (Lakers)")); pacific.add(new DefaultMutableTreeNode("Los Angeles (Clippers)")); pacific.add(new DefaultMutableTreeNode("San Francisco")); pacific.add(new DefaultMutableTreeNode("Seattle")); pacific.add(new DefaultMutableTreeNode("Phoenix")); pacific.add(new DefaultMutableTreeNode("Portland")); pacific.add(new DefaultMutableTreeNode("Sacramento")); midwest.add(new DefaultMutableTreeNode("Utah")); midwest.add(new DefaultMutableTreeNode("San Antonio")); midwest.add(new DefaultMutableTreeNode("Houston")); midwest.add(new DefaultMutableTreeNode("Minnesota")); midwest.add(new DefaultMutableTreeNode("Vancouver")); midwest.add(new DefaultMutableTreeNode("Dallas")); midwest.add(denver); atlantic.add(new DefaultMutableTreeNode("Miami")); atlantic.add(new DefaultMutableTreeNode("New York")); atlantic.add(new DefaultMutableTreeNode("New Jersey")); atlantic.add(new DefaultMutableTreeNode("Washington")); atlantic.add(new DefaultMutableTreeNode("Orlando")); atlantic.add(new DefaultMutableTreeNode("Boston")); atlantic.add(new DefaultMutableTreeNode("Philadelphia")); central.add(new DefaultMutableTreeNode("Chicago")); central.add(new DefaultMutableTreeNode("Indiana")); central.add(new DefaultMutableTreeNode("Charlotte")); central.add(new DefaultMutableTreeNode("Atlanta")); central.add(new DefaultMutableTreeNode("Cleveland")); central.add(new DefaultMutableTreeNode("Detroit")); central.add(new DefaultMutableTreeNode("Milwaukee")); central.add(new DefaultMutableTreeNode("Toronto")); tree = new JTree(nba); getContentPane().setLayout(new BorderLayout()); tree.setCellRenderer(renderer); tree.addTreeSelectionListener(new TreeHandler()); scrollPane.getViewport().add(tree); getContentPane().add("Center", scrollPane); getContentPane().add("South", textField); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(500, 500); setVisible(true); } public static void main(String[] args) { SwingTree app = new SwingTree(); } public class TreeHandler implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent e) { TreePath path = e.getPath(); String text = path.getPathComponent(path.getPathCount() - 1).toString(); if (path.getPathCount() > 3) { text += ": "; text += Integer.toString((int) (Math.random() * 50)) + " Wins "; text += Integer.toString((int) (Math.random() * 50)) + " Losses"; } textField.setText(text); } }
} class Renderer extends JLabel implements TreeCellRenderer {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { setText(value.toString() + " "); return this; }
}</source>
Tree with custom icon
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/**
* A 1.4 application that requires the following additional files: * TreeDemoHelp.html * arnold.html * bloch.html * chan.html * jls.html * swingtutorial.html * tutorial.html * tutorialcont.html * vm.html */
import java.awt.ruponent; import java.awt.Dimension; import java.awt.GridLayout; import java.io.IOException; import java.net.URL; 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 TreeIconDemo2 extends JPanel implements TreeSelectionListener {
private JEditorPane htmlPane; private JTree tree; private URL helpURL; private static boolean DEBUG = false; public TreeIconDemo2() { super(new GridLayout(1, 0)); // Create the nodes. DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Java Series"); createNodes(top); // Create a tree that allows one selection at a time. tree = new JTree(top); tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION); // Enable tool tips. ToolTipManager.sharedInstance().registerComponent(tree); // Set the icon for leaf nodes. ImageIcon tutorialIcon = createImageIcon("images/middle.gif"); if (tutorialIcon != null) { tree.setCellRenderer(new MyRenderer(tutorialIcon)); } else { System.err.println("Tutorial icon missing; using default."); } // Listen for when the selection changes. tree.addTreeSelectionListener(this); // Create the scroll pane and add the tree to it. JScrollPane treeView = new JScrollPane(tree); // Create the HTML viewing pane. htmlPane = new JEditorPane(); htmlPane.setEditable(false); initHelp(); 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); // XXX: ignored in some releases // of Swing. bug 4101306 // workaround for bug 4101306: // treeView.setPreferredSize(new Dimension(100, 100)); splitPane.setPreferredSize(new Dimension(500, 300)); // Add the split pane to this panel. add(splitPane); } /** Required by TreeSelectionListener interface. */ public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree .getLastSelectedPathComponent(); if (node == null) return; Object nodeInfo = node.getUserObject(); if (node.isLeaf()) { BookInfo book = (BookInfo) nodeInfo; displayURL(book.bookURL); if (DEBUG) { System.out.print(book.bookURL + ": \n "); } } else { displayURL(helpURL); } if (DEBUG) { System.out.println(nodeInfo.toString()); } } private class BookInfo { public String bookName; public URL bookURL; public BookInfo(String book, String filename) { bookName = book; bookURL = TreeIconDemo2.class.getResource(filename); if (bookURL == null) { System.err.println("Couldn"t find file: " + filename); } } public String toString() { return bookName; } } private void initHelp() { String s = "TreeDemoHelp.html"; helpURL = TreeIconDemo2.class.getResource(s); if (helpURL == null) { System.err.println("Couldn"t open help file: " + s); } else if (DEBUG) { System.out.println("Help URL is " + helpURL); } displayURL(helpURL); } private void displayURL(URL url) { try { if (url != null) { htmlPane.setPage(url); } else { // null url htmlPane.setText("File Not Found"); if (DEBUG) { System.out.println("Attempted to display a null URL."); } } } catch (IOException e) { System.err.println("Attempted to read a bad URL: " + url); } } private void createNodes(DefaultMutableTreeNode top) { DefaultMutableTreeNode category = null; DefaultMutableTreeNode book = null; category = new DefaultMutableTreeNode("Books for Java Programmers"); top.add(category); // original Tutorial book = new DefaultMutableTreeNode(new BookInfo( "The Java Tutorial: A Short Course on the Basics", "tutorial.html")); category.add(book); // Tutorial Continued book = new DefaultMutableTreeNode( new BookInfo("The Java Tutorial Continued: The Rest of the JDK", "tutorialcont.html")); category.add(book); // JFC Swing Tutorial book = new DefaultMutableTreeNode(new BookInfo( "The JFC Swing Tutorial: A Guide to Constructing GUIs", "swingtutorial.html")); category.add(book); // Bloch book = new DefaultMutableTreeNode(new BookInfo( "Effective Java Programming Language Guide", "bloch.html")); category.add(book); // Arnold/Gosling book = new DefaultMutableTreeNode(new BookInfo( "The Java Programming Language", "arnold.html")); category.add(book); // Chan book = new DefaultMutableTreeNode(new BookInfo( "The Java Developers Almanac", "chan.html")); category.add(book); category = new DefaultMutableTreeNode("Books for Java Implementers"); top.add(category); // VM book = new DefaultMutableTreeNode(new BookInfo( "The Java Virtual Machine Specification", "vm.html")); category.add(book); // Language Spec book = new DefaultMutableTreeNode(new BookInfo( "The Java Language Specification", "jls.html")); category.add(book); } /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL = TreeIconDemo2.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn"t find file: " + path); return null; } } /** * Create the GUI and show it. For thread safety, this method should be * invoked from the event-dispatching thread. */ private static void createAndShowGUI() { // Create and set up the window. JFrame frame = new JFrame("TreeIconDemo2"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Create and set up the content pane. TreeIconDemo2 newContentPane = new TreeIconDemo2(); newContentPane.setOpaque(true); // content panes must be opaque frame.setContentPane(newContentPane); // Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { // Schedule a job for the event-dispatching thread: // creating and showing this application"s GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } private class MyRenderer extends DefaultTreeCellRenderer { Icon tutorialIcon; public MyRenderer(Icon icon) { tutorialIcon = 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 && isTutorialBook(value)) { setIcon(tutorialIcon); setToolTipText("This book is in the Tutorial series."); } else { setToolTipText(null); // no tool tip } return this; } protected boolean isTutorialBook(Object value) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; BookInfo nodeInfo = (BookInfo) (node.getUserObject()); String title = nodeInfo.bookName; if (title.indexOf("Tutorial") >= 0) { return true; } return false; } }
}</source>