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
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());
}
}
A JTree subclass that displays the tree of AWT or Swing component that make up a GUI
/*
* 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);
}
}
CheckBox Tree node
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;
}
}
Converting All Nodes in a JTree Component to a TreePath Array
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);
}
}
}
}
Delete tree node
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);
}
}
}
Expanding or Collapsing All Nodes in a JTree Component
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);
}
}
Expression Tree
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();
}
}
Get child count, depth, leaf count
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();
}
}
Get path for all expanded or not expanded tree pathes
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);
}
}
}
}
JTree node mouse click event
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("");
}
}
JTree root cannot be removed with removeNodeFromParent(), use DefaultTreeModel.setRoot() to remove the root
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);
}
}
Removing a Node to a JTree Component
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);
}
}
Searching node in a JTree
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();
}
}
Swing Tree
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;
}
}
Tree with custom icon
/*
* 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;
}
}
}