Java/Swing JFC/Tree
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 Add and remove tree Node and expand the tree node
- 2 Adding a Node to a JTree Component
- 3 Adding editable nodes to JTree
- 4 Add Tree to JScrollPane
- 5 Allow multiple selections of visible nodes
- 6 Allow only a single node to be selected (default)
- 7 Allow selection to span one vertical contiguous set of visible nodes
- 8 All rows will be given 15 pixels of height
- 9 Ancestor Tree with Icons
- 10 A sample component for dragging and dropping a collection of files into a tree.
- 11 A simple test to see how we can build a tree and populate it
- 12 A tree with component
- 13 Build a tree and customize its icons
- 14 Build a tree and populate it from hashtables
- 15 Build a tree based on DefaultMutableTreeNode
- 16 Changing and Removing the Default Icons in a JTree Component
- 17 Converting All Nodes in a JTree Component to a TreePath Array
- 18 Creating a JTree Component
- 19 DefaultMutableTreeNode and user object
- 20 DefaultMutableTreeNode Node Tree Sample
- 21 Deleting nodes from JTree
- 22 Display a file system in a JTree view
- 23 Displaying Hierarchical Data within a JTree
- 24 Display user object in a tree
- 25 DnD (drag and drop)JTree code
- 26 Drag and drop of a group of files into a tree
- 27 Enabling and Disabling Multiple Selections in a JTree Component
- 28 Expand All for a tree path
- 29 Expanding or Collapsing All Nodes in a JTree Component
- 30 Expansion and Collapse Events in a JTree are fired before a node is expanded or collapsed can be vetoed, thereby preventing the operation.
- 31 File folder Tree with icons
- 32 File System Tree
- 33 File Tree with Popup Menu
- 34 File Tree with Tooltips
- 35 Finding a Node in a JTree Component
- 36 Find the path regardless of visibility that matches the specified sequence of names
- 37 Flush the internal cache of Row height
- 38 Genealogy Tree
- 39 Get path for all expanded or not expanded tree pathes
- 40 Getting the Selected Nodes in a JTree Component
- 41 Get tree path from TreeNode
- 42 Have a popup attached to a JTree
- 43 Have the row height for each row computed individually
- 44 implements TreeSelectionListener to create your own listener
- 45 Installs custom icons
- 46 Install ToolTips for Tree (JTree)
- 47 JTree drag and drop utilites
- 48 JTree.DynamicUtilTreeNode.createChildren
- 49 JTree root cannot be removed with removeNodeFromParent(), use DefaultTreeModel.setRoot() to remove the root
- 50 Listening for Expansion and Collapse Events in a JTree Component
- 51 Listening for Selection Events in a JTree Component
- 52 Preventing Expansion or Collapse of a Node in a JTree: override JTree.setExpandedState()
- 53 Preventing the Expansion or Collapse of a Node in a JTree Component
- 54 Removing a Node to a JTree Component
- 55 Returns a TreePath containing the specified node.
- 56 Search backward from last visible row looking for any visible node whose name starts with prefix.
- 57 Searching node in a JTree
- 58 Set the Tree Line
- 59 Setting the Row Height of a JTree
- 60 Traverse all expanded nodes in tree
- 61 Traverse Tree
- 62 Tree based on Array structure
- 63 Tree: Drag and Drop
- 64 Tree Expand Event Demo
- 65 Tree Expand Event Demo 2
- 66 TreeExpansionListener and TreeExpansionEvent
- 67 Tree Icon Demo
- 68 Tree Lines
- 69 Tree open Icon
- 70 Tree Selection Row
- 71 Tree will Expand event and listener
- 72 Use UIManager to change the default icon for JTree
- 73 Visiting All the Nodes in a JTree Component
Add and remove tree Node and expand the tree node
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class ModelJTree extends JFrame {
private JTree tree;
private DefaultTreeModel model;
private DefaultMutableTreeNode rootNode;
public ModelJTree() {
DefaultMutableTreeNode philosophersNode = getPhilosopherTree();
model = new DefaultTreeModel(philosophersNode);
tree = new JTree(model);
JButton addButton = new JButton("Add Philosopher");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
addPhilosopher();
}
});
JButton removeButton = new JButton("Remove Selected Philosopher");
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
removeSelectedPhilosopher();
}
});
JPanel inputPanel = new JPanel();
inputPanel.add(addButton);
inputPanel.add(removeButton);
Container container = getContentPane();
container.add(new JScrollPane(tree), BorderLayout.CENTER);
container.add(inputPanel, BorderLayout.NORTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 300);
setVisible(true);
}
private void addPhilosopher() {
DefaultMutableTreeNode parent = getSelectedNode();
if (parent == null) {
JOptionPane.showMessageDialog(ModelJTree.this, "Select an era.", "Error",
JOptionPane.ERROR_MESSAGE);
return;
}
String name = JOptionPane.showInputDialog(ModelJTree.this, "Enter Name:");
model.insertNodeInto(new DefaultMutableTreeNode(name), parent, parent.getChildCount());
}
private void removeSelectedPhilosopher() {
DefaultMutableTreeNode selectedNode = getSelectedNode();
if (selectedNode != null)
model.removeNodeFromParent(selectedNode);
}
private DefaultMutableTreeNode getSelectedNode() {
return (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
}
private DefaultMutableTreeNode getPhilosopherTree() {
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Philosophers");
DefaultMutableTreeNode ancient = new DefaultMutableTreeNode("Ancient");
rootNode.add(ancient);
ancient.add(new DefaultMutableTreeNode("Socrates"));
DefaultMutableTreeNode medieval = new DefaultMutableTreeNode("Medieval");
rootNode.add(medieval);
return rootNode;
}
public static void main(String args[]) {
new ModelJTree();
}
}
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());
}
}
Adding editable nodes to JTree
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.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main extends JFrame {
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("J");
DefaultTreeModel model = new DefaultTreeModel(rootNode);
JTree m_tree = new JTree(model);
JButton addButton;
public Main() {
DefaultMutableTreeNode forums = new DefaultMutableTreeNode("F");
forums.add(new DefaultMutableTreeNode("T"));
DefaultMutableTreeNode articles = new DefaultMutableTreeNode("A");
articles.add(new DefaultMutableTreeNode("1"));
DefaultMutableTreeNode examples = new DefaultMutableTreeNode("E");
examples.add(new DefaultMutableTreeNode("2"));
rootNode.add(forums);
rootNode.add(articles);
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();
addButton = new JButton("Add Node");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
.getLastSelectedPathComponent();
if (selNode != null) {
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New Node");
model.insertNodeInto(newNode, selNode, selNode.getChildCount());
TreeNode[] nodes = model.getPathToRoot(newNode);
TreePath path = new TreePath(nodes);
m_tree.scrollPathToVisible(path);
m_tree.setSelectionPath(path);
m_tree.startEditingAtPath(path);
}
}
});
panel.add(addButton);
getContentPane().add(panel, BorderLayout.SOUTH);
setSize(300, 400);
setVisible(true);
}
public static void main(String[] arg) {
new Main();
}
}
Add Tree to JScrollPane
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeSample {
public static void main(String args[]) {
JFrame f = new JFrame("JTree Sample");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = f.getContentPane();
JTree tree = new JTree();
JScrollPane scrollPane = new JScrollPane(tree);
content.add(scrollPane, BorderLayout.CENTER);
f.setSize(300, 200);
f.setVisible(true);
}
}
Allow multiple selections of visible nodes
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;
public class TreeDISCONTIGUOUSSelection {
public static void main(String[] argv) {
JTree tree = new JTree();
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
JFrame frame = new JFrame("tree DISCONTIGUOUS selection");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Allow only a single node to be selected (default)
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;
public class TreeSingleSelection {
public static void main(String[] argv) {
JTree tree = new JTree();
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
JFrame frame = new JFrame("Tree single selection");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Allow selection to span one vertical contiguous set of visible nodes
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;
public class TreeCONTIGUOUSSelection {
public static void main(String[] argv) {
JTree tree = new JTree();
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
JFrame frame = new JFrame("Tree CONTIGUOUS selection");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
All rows will be given 15 pixels of height
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeight15 {
public static void main(String[] argv) {
JTree tree = new JTree();
tree.setRowHeight(15);
JFrame frame = new JFrame("Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Ancestor Tree with Icons
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.tree.*;
public class AncestorTree extends JFrame
{
public static ImageIcon ICON_SELF =
new ImageIcon("myself.gif");
public static ImageIcon ICON_MALE =
new ImageIcon("male.gif");
public static ImageIcon ICON_FEMALE =
new ImageIcon("female.gif");
protected JTree m_tree;
protected DefaultTreeModel m_model;
protected IconCellRenderer m_renderer;
protected IconCellEditor m_editor;
public AncestorTree()
{
super("Ancestor Tree");
setSize(400, 300);
DefaultMutableTreeNode top = new DefaultMutableTreeNode(
new IconData(ICON_SELF, "Myself"));
addAncestors(top);
m_model = new DefaultTreeModel(top);
m_tree = new JTree(m_model);
m_tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
m_tree.setShowsRootHandles(true);
m_tree.setEditable(true);
m_renderer = new IconCellRenderer();
m_tree.setCellRenderer(m_renderer);
m_editor = new IconCellEditor(m_tree);
m_tree.setCellEditor(m_editor);
m_tree.setInvokesStopCellEditing(true);
m_tree.addMouseListener(new TreeExpander());
JScrollPane s = new JScrollPane();
s.getViewport().add(m_tree);
getContentPane().add(s, BorderLayout.CENTER);
WindowListener wndCloser = new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
public boolean addAncestors(DefaultMutableTreeNode node)
{
if (node.getChildCount() > 0)
return false;
Object obj = node.getUserObject();
if (obj == null)
return false;
node.add(new DefaultMutableTreeNode( new IconData(
ICON_MALE, "Father of: "+obj.toString()) ));
node.add(new DefaultMutableTreeNode( new IconData(
ICON_FEMALE, "Mother of: "+obj.toString()) ));
return true;
}
public static void main(String argv[])
{
new AncestorTree();
}
class TreeExpander
extends MouseAdapter
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2)
{
TreePath selPath = m_tree.getPathForLocation(
e.getX(), e.getY());
if (selPath == null)
return;
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)(selPath.
getLastPathComponent());
if (node!=null && addAncestors(node))
{
m_tree.expandPath(selPath);
m_tree.repaint();
}
}
}
}
}
class IconCellRenderer
extends JLabel
implements TreeCellRenderer
{
protected Color m_textSelectionColor;
protected Color m_textNonSelectionColor;
protected Color m_bkSelectionColor;
protected Color m_bkNonSelectionColor;
protected Color m_borderSelectionColor;
protected boolean m_selected;
public IconCellRenderer()
{
super();
m_textSelectionColor = UIManager.getColor(
"Tree.selectionForeground");
m_textNonSelectionColor = UIManager.getColor(
"Tree.textForeground");
m_bkSelectionColor = UIManager.getColor(
"Tree.selectionBackground");
m_bkNonSelectionColor = UIManager.getColor(
"Tree.textBackground");
m_borderSelectionColor = UIManager.getColor(
"Tree.selectionBorderColor");
setOpaque(false);
}
public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean sel, boolean expanded, boolean leaf,
int row, boolean hasFocus)
{
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)value;
Object obj = node.getUserObject();
setText(obj.toString());
if (obj instanceof IconData)
{
IconData idata = (IconData)obj;
if (expanded)
setIcon(idata.getOpenIcon());
else
setIcon(idata.getIcon());
}
else
setIcon(null);
setFont(tree.getFont());
setForeground(sel ? m_textSelectionColor :
m_textNonSelectionColor);
setBackground(sel ? m_bkSelectionColor :
m_bkNonSelectionColor);
m_selected = sel;
return this;
}
public void paint(Graphics g)
{
Color bColor = getBackground();
Icon icon = getIcon();
g.setColor(bColor);
int offset = 0;
if(icon != null && getText() != null)
offset = (icon.getIconWidth() + getIconTextGap());
g.fillRect(offset, 0, getWidth() - 1 - offset,
getHeight() - 1);
if (m_selected)
{
g.setColor(m_borderSelectionColor);
g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
}
super.paint(g);
}
}
class IconData
{
protected Icon m_icon;
protected Icon m_openIcon;
protected Object m_data;
public IconData(Icon icon, Object data)
{
m_icon = icon;
m_openIcon = null;
m_data = data;
}
public IconData(Icon icon, Icon openIcon, Object data)
{
m_icon = icon;
m_openIcon = openIcon;
m_data = data;
}
public Icon getIcon()
{
return m_icon;
}
public Icon getOpenIcon()
{
return m_openIcon!=null ? m_openIcon : m_icon;
}
public Object getObject()
{
return m_data;
}
public String toString()
{
return m_data.toString();
}
}
class IconCellEditor
extends JLabel
implements TreeCellEditor, ActionListener
{
protected JTree m_tree = null;
protected JTextField m_editor = null;
protected IconData m_item = null;
protected int m_lastRow = -1;
protected long m_lastClick = 0;
protected Vector m_listeners = null;
public IconCellEditor(JTree tree)
{
super();
m_tree = tree;
m_listeners = new Vector();
}
public Component getTreeCellEditorComponent(JTree tree,
Object value, boolean isSelected, boolean expanded,
boolean leaf, int row)
{
if (value instanceof DefaultMutableTreeNode)
{
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)value;
Object obj = node.getUserObject();
if (obj instanceof IconData)
{
IconData idata = (IconData)obj;
m_item = idata;
// Reserve some more space...
setText(idata.toString()+" ");
setIcon(idata.m_icon);
setFont(tree.getFont());
return this;
}
}
// We don"t support other objects...
return null;
}
public Object getCellEditorValue()
{
if (m_item != null && m_editor != null)
m_item.m_data = m_editor.getText();
return m_item;
}
public boolean isCellEditable(EventObject evt)
{
if (evt instanceof MouseEvent)
{
MouseEvent mEvt = (MouseEvent)evt;
if (mEvt.getClickCount() == 1)
{
int row = m_tree.getRowForLocation(mEvt.getX(),
mEvt.getY());
if (row != m_lastRow)
{
m_lastRow = row;
m_lastClick = System.currentTimeMillis();
return false;
}
else if (System.currentTimeMillis()-m_lastClick
> 1000)
{
m_lastRow = -1;
m_lastClick = 0;
prepareEditor();
mEvt.consume();
return true;
}
else
return false;
}
}
return false;
}
protected void prepareEditor()
{
if (m_item == null)
return;
String str = m_item.toString();
m_editor = new JTextField(str);
m_editor.addActionListener(this);
m_editor.selectAll();
m_editor.setFont(m_tree.getFont());
add(m_editor);
revalidate();
TreePath path = m_tree.getPathForRow(m_lastRow);
m_tree.startEditingAtPath(path);
}
protected void removeEditor()
{
if (m_editor != null)
{
remove(m_editor);
m_editor.setVisible(false);
m_editor = null;
m_item = null;
}
}
public void doLayout()
{
super.doLayout();
if (m_editor != null)
{
int offset = getIconTextGap();
if (getIcon() != null)
offset += getIcon().getIconWidth();
Dimension cSize = getSize();
m_editor.setBounds(offset, 0, cSize.width - offset,
cSize.height);
}
}
public boolean shouldSelectCell(EventObject evt)
{
return true;
}
public boolean stopCellEditing()
{
if (m_item != null)
m_item.m_data = m_editor.getText();
ChangeEvent e = new ChangeEvent(this);
for (int k=0; k<m_listeners.size(); k++)
{
CellEditorListener l = (CellEditorListener)m_listeners.
elementAt(k);
l.editingStopped(e);
}
removeEditor();
return true;
}
public void cancelCellEditing()
{
ChangeEvent e = new ChangeEvent(this);
for (int k=0; k<m_listeners.size(); k++)
{
CellEditorListener l = (CellEditorListener)m_listeners.
elementAt(k);
l.editingCanceled(e);
}
removeEditor();
}
public void addCellEditorListener(CellEditorListener l)
{
m_listeners.addElement(l);
}
public void removeCellEditorListener(CellEditorListener l)
{
m_listeners.removeElement(l);
}
public void actionPerformed(ActionEvent e)
{
stopCellEditing();
m_tree.stopEditing();
}
}
A sample component for dragging and dropping a collection of files into a tree.
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly
*/
// FSTest.java
//A quick test environment for the FSTree component.
//
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
public class FSTest extends JFrame {
public FSTest() {
super("FSTree Component Test");
setSize(300, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
FSTree fst = new FSTree(new DefaultMutableTreeNode("Starter"));
getContentPane().add(new JScrollPane(fst));
setVisible(true);
}
public static void main(String args[]) {
new FSTest();
}
}
//FSTree.java
//A sample component for dragging & dropping a collection of files
//into a tree.
//
class FSTree extends JTree {
public FSTree() {
super();
init();
}
public FSTree(TreeModel newModel) {
super(newModel);
init();
}
public FSTree(TreeNode root) {
super(root);
init();
}
public FSTree(TreeNode root, boolean asks) {
super(root, asks);
init();
}
private void init() {
// We don"t want to export anything from this tree, only import
setDragEnabled(false);
setTransferHandler(new FSTransfer());
}
public class FSTransfer extends TransferHandler {
public boolean importData(JComponent comp, Transferable t) {
// Make sure we have the right starting points
if (!(comp instanceof FSTree)) {
return false;
}
if (!t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
// Grab the tree, its model and the root node
FSTree tree = (FSTree) comp;
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model
.getRoot();
try {
List data = (List) t
.getTransferData(DataFlavor.javaFileListFlavor);
Iterator i = data.iterator();
while (i.hasNext()) {
File f = (File) i.next();
root.add(new DefaultMutableTreeNode(f.getName()));
}
model.reload();
return true;
} catch (UnsupportedFlavorException ufe) {
System.err.println("Ack! we should not be here.\nBad Flavor.");
} catch (IOException ioe) {
System.out.println("Something failed during import:\n" + ioe);
}
return false;
}
// We only support file lists on FSTrees...
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
if (comp instanceof FSTree) {
for (int i = 0; i < transferFlavors.length; i++) {
if (!transferFlavors[i]
.equals(DataFlavor.javaFileListFlavor)) {
return false;
}
}
return true;
}
return false;
}
}
}
A simple test to see how we can build a tree and populate it
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly
*/
// TestTree.java
//A simple test to see how we can build a tree and populate it. We build
//the tree structure up by hand in this case.
//
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class TestTree extends JFrame {
JTree tree;
DefaultTreeModel treeModel;
public TestTree() {
super("Tree Test Example");
setSize(400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void init() {
// Build up a bunch of TreeNodes. We use DefaultMutableTreeNode because
// the
// DefaultTreeModel can use it to build a complete tree.
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode subroot = new DefaultMutableTreeNode("SubRoot");
DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("Leaf 1");
DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("Leaf 2");
// Build our tree model starting at the root node, and then make a JTree
// out
// of that.
treeModel = new DefaultTreeModel(root);
tree = new JTree(treeModel);
// Build the tree up from the nodes we created.
treeModel.insertNodeInto(subroot, root, 0);
// Or, more succinctly:
subroot.add(leaf1);
root.add(leaf2);
// Display it.
getContentPane().add(tree, BorderLayout.CENTER);
}
public static void main(String args[]) {
TestTree tt = new TestTree();
tt.init();
tt.setVisible(true);
}
}
A tree with component
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Font;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
public class ComponentHier {
public static void main(String args[]) {
JFrame frame = new JFrame("JComponent Hierarchy");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Font font = (Font) UIManager.get("Tree.font");
font = new Font(font.getFontName(), Font.BOLD, font.getSize() - 3);
UIManager.put("Tree.font", font);
Vector jEditorPaneVector = new NamedVector("JEditorPane",
new Object[] { "JTextPane" });
Vector jTextFieldVector = new NamedVector("JTextField",
new Object[] { "JPasswordField" });
Vector jTextComponentVector = new NamedVector(
"JTextComponent",
new Object[] { jEditorPaneVector, "JTextArea", jTextFieldVector });
Vector jLayeredPaneVector = new NamedVector("JLayeredPane",
new Object[] { "JDesktopPane" });
Vector jToggleButtonVector = new NamedVector("JToggleButton",
new Object[] { "JCheckBox", "JRadioButton" });
Vector jMenuItemVector = new NamedVector("JMenuItem", new Object[] {
"JCheckBoxMenuItem", "JMenu", "JRadioButtonMenuItem" });
Vector abstractButtonVector = new NamedVector(
"Abstract Button",
new Object[] { "JButton", jMenuItemVector, jToggleButtonVector });
Object jComponentNodes[] = { abstractButtonVector, "JColorChooser",
"JComboBox", "JFileChooser", "JInternalFrame", "JLabel",
jLayeredPaneVector, "JList", "JMenuBar", "JOptionPane",
"JPanel", "JPopupMenu", "JProgressBar", "JRootPane",
"JScrollBar", "JScrollPane", "JSeparator", "JSlider",
"JSplitPane", "JTabbedPane", "JTable", jTextComponentVector,
"JToolBar", "JTree", "JViewPort" };
Vector jComponentVector = new NamedVector("JComponent", jComponentNodes);
Object rootNodes[] = { jComponentVector };
Vector rootVector = new NamedVector("Root", rootNodes);
JTree tree = new JTree(rootVector);
tree.putClientProperty("JTree.lineStyle", "Angled");
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(250, 480);
frame.setVisible(true);
}
}
class NamedVector extends Vector {
String name;
public NamedVector(String name) {
this.name = name;
}
public NamedVector(String name, Object elements[]) {
this.name = name;
for (int i = 0, n = elements.length; i < n; i++) {
add(elements[i]);
}
}
public String toString() {
return "[" + name + "]";
}
}
Build a tree and customize its icons
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly
*/
// TestTree4.java
//Another test to see how we can build a tree and customize its icons.
//This example does not affect the icons of other trees.
//
import java.awt.BorderLayout;
import java.util.Hashtable;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
public class TestTree4 extends JFrame {
JTree tree1, tree2;
DefaultTreeModel treeModel;
public TestTree4() {
super("Custom Icon Example");
setSize(350, 450);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// Build the hierarchy of containers & objects
String[] schoolyard = { "School", "Playground", "Parking Lot", "Field" };
String[] mainstreet = { "Grocery", "Shoe Shop", "Five & Dime",
"Post Office" };
String[] highway = { "Gas Station", "Convenience Store" };
String[] housing = { "Victorian_blue", "Faux Colonial",
"Victorian_white" };
String[] housing2 = { "Mission", "Ranch", "Condo" };
Hashtable homeHash = new Hashtable();
homeHash.put("Residential 1", housing);
homeHash.put("Residential 2", housing2);
Hashtable cityHash = new Hashtable();
cityHash.put("School grounds", schoolyard);
cityHash.put("Downtown", mainstreet);
cityHash.put("Highway", highway);
cityHash.put("Housing", homeHash);
Hashtable worldHash = new Hashtable();
worldHash.put("My First VRML World", cityHash);
// Build our tree out of our big hashtable
tree1 = new JTree(worldHash);
tree2 = new JTree(worldHash);
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree2
.getCellRenderer();
renderer.setClosedIcon(new ImageIcon("door.closed.gif"));
renderer.setOpenIcon(new ImageIcon("door.open.gif"));
renderer.setLeafIcon(new ImageIcon("world.gif"));
JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tree1,
tree2);
getContentPane().add(pane, BorderLayout.CENTER);
}
public static void main(String args[]) {
TestTree4 tt = new TestTree4();
tt.setVisible(true);
}
}
Build a tree and populate it from hashtables
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly
*/
// ObjectTree.java
//A simple test to see how we can build a tree and populate it. This version
//builds the tree from hashtables.
//
import java.awt.BorderLayout;
import java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JTree;
public class ObjectTree extends JFrame {
JTree tree;
String[][] sampleData = { { "Amy" }, { "Brandon", "Bailey" }, { "Jodi" },
{ "Trent", "Garrett", "Paige", "Dylan" }, { "Donn" },
{ "Nancy", "Donald", "Phyllis", "John", "Pat" }, { "Ron" },
{ "Linda", "Mark", "Lois", "Marvin" } };
public ObjectTree() {
super("Hashtable Test");
setSize(400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void init() {
Hashtable h = new Hashtable();
// Build up the hashtable using every other entry in the String[][] as a
// key
// followed by a String[]"value."
for (int i = 0; i < sampleData.length; i += 2) {
h.put(sampleData[i][0], sampleData[i + 1]);
}
tree = new JTree(h);
getContentPane().add(tree, BorderLayout.CENTER);
}
public static void main(String args[]) {
ObjectTree tt = new ObjectTree();
tt.init();
tt.setVisible(true);
}
}
Build a tree based on DefaultMutableTreeNode
// : c14:Trees.java
// Simple Swing tree. Trees can be vastly more complex.
// <applet code=Trees width=250 height=250></applet>
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
// Takes an array of Strings and makes the first
// element a node and the rest leaves:
class Branch {
private DefaultMutableTreeNode r;
public Branch(String[] data) {
r = new DefaultMutableTreeNode(data[0]);
for (int i = 1; i < data.length; i++)
r.add(new DefaultMutableTreeNode(data[i]));
}
public DefaultMutableTreeNode node() {
return r;
}
}
public class Trees extends JApplet {
private String[][] data = { { "Colors", "Red", "Blue", "Green" },
{ "Flavors", "Tart", "Sweet", "Bland" },
{ "Length", "Short", "Medium", "Long" },
{ "Volume", "High", "Medium", "Low" },
{ "Temperature", "High", "Medium", "Low" },
{ "Intensity", "High", "Medium", "Low" }, };
private static int i = 0;
private DefaultMutableTreeNode root, child, chosen;
private JTree tree;
private DefaultTreeModel model;
public void init() {
Container cp = getContentPane();
root = new DefaultMutableTreeNode("root");
tree = new JTree(root);
// Add it and make it take care of scrolling:
cp.add(new JScrollPane(tree), BorderLayout.CENTER);
// Capture the tree"s model:
model = (DefaultTreeModel) tree.getModel();
JButton test = new JButton("Press me");
test.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (i < data.length) {
child = new Branch(data[i++]).node();
// What"s the last one you clicked?
chosen = (DefaultMutableTreeNode) tree
.getLastSelectedPathComponent();
if (chosen == null)
chosen = root;
// The model will create the appropriate event.
// In response, the tree will update itself:
model.insertNodeInto(child, chosen, 0);
// Puts the new node on the chosen node.
}
}
});
// Change the button"s colors:
test.setBackground(Color.BLUE);
test.setForeground(Color.WHITE);
JPanel p = new JPanel();
p.add(test);
cp.add(p, BorderLayout.SOUTH);
}
public static void main(String[] args) {
run(new Trees(), 250, 250);
}
public static void run(JApplet applet, int width, int height) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(applet);
frame.setSize(width, height);
applet.init();
applet.start();
frame.setVisible(true);
}
} ///:~
Changing and Removing the Default Icons in a JTree Component
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultTreeCellRenderer;
public class Main {
public static void main(String[] argv) throws Exception {
Icon leafIcon = new ImageIcon("leaf.gif");
Icon openIcon = new ImageIcon("open.gif");
Icon closedIcon = new ImageIcon("closed.gif");
JTree tree = new JTree();
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
renderer.setLeafIcon(leafIcon);
renderer.setClosedIcon(closedIcon);
renderer.setOpenIcon(openIcon);
JFrame f = new JFrame();
f.add(new JScrollPane(tree));
f.setSize(300, 300);
f.setVisible(true);
}
}
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);
}
}
}
}
Creating a JTree Component
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
public class Main {
public static void main(String[] argv) throws Exception {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root Label");
root.add(new DefaultMutableTreeNode("Node Label"));
JTree tree = new JTree(root);
JFrame f = new JFrame();
f.add(new JScrollPane(tree));
f.setSize(300,300);
f.setVisible(true);
}
}
DefaultMutableTreeNode and user object
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 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:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution 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, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
/**
* 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 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.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.ToolTipManager;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import java.net.URL;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.ruponent;
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() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//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;
}
}
}
DefaultMutableTreeNode Node Tree Sample
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
public class NodeTreeSample {
public static void main(String args[]) {
JFrame frame = new JFrame("Manual Nodes");
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode mercury = new DefaultMutableTreeNode("Mercury");
root.add(mercury);
DefaultMutableTreeNode venus = new DefaultMutableTreeNode("Venus");
root.add(venus);
DefaultMutableTreeNode mars = new DefaultMutableTreeNode("Mars");
root.add(mars);
JTree tree = new JTree(root);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
Deleting nodes from JTree
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.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 Main extends JFrame {
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("A");
private DefaultTreeModel m_model = new DefaultTreeModel(rootNode);
private JTree m_tree = new JTree(m_model);
private JButton m_addButton;
private JButton m_delButton;
public Main() {
DefaultMutableTreeNode forums = new DefaultMutableTreeNode("B");
forums.add(new DefaultMutableTreeNode("T"));
DefaultMutableTreeNode articles = new DefaultMutableTreeNode("A");
articles.add(new DefaultMutableTreeNode("A"));
DefaultMutableTreeNode examples = new DefaultMutableTreeNode("E");
examples.add(new DefaultMutableTreeNode("E"));
rootNode.add(forums);
rootNode.add(articles);
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 = new JButton("Add Node");
m_addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
.getLastSelectedPathComponent();
if (selNode == null) {
return;
}
DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New");
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);
getContentPane().add(panel, BorderLayout.SOUTH);
m_delButton = new JButton("Delete Node");
m_delButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
.getLastSelectedPathComponent();
if (selNode == null) {
return;
}
MutableTreeNode parent = (MutableTreeNode) (selNode.getParent());
if (parent == null) {
return;
}
MutableTreeNode toBeSelNode = (MutableTreeNode) selNode.getPreviousSibling();
if (toBeSelNode == null) {
toBeSelNode = (MutableTreeNode) selNode.getNextSibling();
}
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);
}
});
panel.add(m_delButton);
getContentPane().add(panel, BorderLayout.SOUTH);
setSize(300, 400);
setVisible(true);
}
public static void main(String[] arg) {
new Main();
}
}
Display a file system in a JTree view
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.io.File;
import java.util.Collections;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
/**
* Display a file system in a JTree view
*
* @version $Id: FileTree.java,v 1.9 2004/02/23 03:39:22 ian Exp $
* @author Ian Darwin
*/
public class FileTree extends JPanel {
/** Construct a FileTree */
public FileTree(File dir) {
setLayout(new BorderLayout());
// Make a tree list with all the nodes, and make it a JTree
JTree tree = new JTree(addNodes(null, dir));
// Add a listener
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
.getPath().getLastPathComponent();
System.out.println("You selected " + node);
}
});
// Lastly, put the JTree into a JScrollPane.
JScrollPane scrollpane = new JScrollPane();
scrollpane.getViewport().add(tree);
add(BorderLayout.CENTER, scrollpane);
}
/** Add nodes from under "dir" into curTop. Highly recursive. */
DefaultMutableTreeNode addNodes(DefaultMutableTreeNode curTop, File dir) {
String curPath = dir.getPath();
DefaultMutableTreeNode curDir = new DefaultMutableTreeNode(curPath);
if (curTop != null) { // should only be null at root
curTop.add(curDir);
}
Vector ol = new Vector();
String[] tmp = dir.list();
for (int i = 0; i < tmp.length; i++)
ol.addElement(tmp[i]);
Collections.sort(ol, String.CASE_INSENSITIVE_ORDER);
File f;
Vector files = new Vector();
// Make two passes, one for Dirs and one for Files. This is #1.
for (int i = 0; i < ol.size(); i++) {
String thisObject = (String) ol.elementAt(i);
String newPath;
if (curPath.equals("."))
newPath = thisObject;
else
newPath = curPath + File.separator + thisObject;
if ((f = new File(newPath)).isDirectory())
addNodes(curDir, f);
else
files.addElement(thisObject);
}
// Pass two: for files.
for (int fnum = 0; fnum < files.size(); fnum++)
curDir.add(new DefaultMutableTreeNode(files.elementAt(fnum)));
return curDir;
}
public Dimension getMinimumSize() {
return new Dimension(200, 400);
}
public Dimension getPreferredSize() {
return new Dimension(200, 400);
}
/** Main: make a Frame, add a FileTree */
public static void main(String[] av) {
JFrame frame = new JFrame("FileTree");
frame.setForeground(Color.black);
frame.setBackground(Color.lightGray);
Container cp = frame.getContentPane();
if (av.length == 0) {
cp.add(new FileTree(new File(".")));
} else {
cp.setLayout(new BoxLayout(cp, BoxLayout.X_AXIS));
for (int i = 0; i < av.length; i++)
cp.add(new FileTree(new File(av[i])));
}
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Displaying Hierarchical Data within a JTree
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
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 TreeIt {
class MyCellRenderer extends JLabel implements TreeCellRenderer {
MyCellRenderer() {
setOpaque(true);
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
StringBuffer text = new StringBuffer();
if (expanded)
text.append("E:");
if (leaf)
text.append("L:");
if (hasFocus)
text.append("H:");
text.append(row + "->");
text.append(value.toString());
setBackground(selected ? Color.BLUE : Color.YELLOW);
setForeground(selected ? Color.YELLOW : Color.BLUE);
setText(text.toString());
return this;
}
}
public TreeIt() {
JFrame f = new JFrame();
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Calendar");
DefaultMutableTreeNode months = new DefaultMutableTreeNode("Months");
root.add(months);
String monthLabels[] = { "January", "February", "March", "April",
"May", "June", "July", "August", "September", "October",
"November", "December" };
for (int i = 0, n = monthLabels.length; i < n; i++)
months.add(new DefaultMutableTreeNode(monthLabels[i]));
DefaultMutableTreeNode weeks = new DefaultMutableTreeNode("Weeks");
root.add(weeks);
String weekLabels[] = { "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday" };
for (int i = 0, n = weekLabels.length; i < n; i++)
weeks.add(new DefaultMutableTreeNode(weekLabels[i]));
JTree jt = new JTree(root);
jt.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
TreePath path = e.getPath();
System.out.println("Picked: " + path.getLastPathComponent());
Object elements[] = path.getPath();
for (int i = 0, n = elements.length; i < n; i++) {
System.out.print("->" + elements[i]);
}
System.out.println();
}
});
DefaultMutableTreeNode lastLeaf = root.getLastLeaf();
TreePath path = new TreePath(lastLeaf.getPath());
jt.setSelectionPath(path);
jt.setCellRenderer(new MyCellRenderer());
JScrollPane jsp = new JScrollPane(jt);
Container c = f.getContentPane();
c.add(jsp, BorderLayout.CENTER);
f.setSize(250, 250);
f.show();
}
public static void main(String args[]) {
new TreeIt();
}
}
Display user object in a tree
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 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:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution 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, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
/**
* 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.Dimension;
import java.awt.GridLayout;
import java.io.IOException;
import java.net.URL;
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.UIManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
public class TreeDemo extends JPanel
implements TreeSelectionListener {
private JEditorPane htmlPane;
private JTree tree;
private URL helpURL;
private static boolean DEBUG = false;
//Optionally play with line styles. Possible values are
//"Angled" (the default), "Horizontal", and "None".
private static boolean playWithLineStyle = false;
private static String lineStyle = "Horizontal";
//Optionally set the look and feel.
private static boolean useSystemLookAndFeel = false;
public TreeDemo() {
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);
//Listen for when the selection changes.
tree.addTreeSelectionListener(this);
if (playWithLineStyle) {
System.out.println("line style = " + lineStyle);
tree.putClientProperty("JTree.lineStyle", lineStyle);
}
//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 = TreeDemo.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 = TreeDemo.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);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
if (useSystemLookAndFeel) {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
System.err.println("Couldn"t use system look and feel.");
}
}
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TreeDemo newContentPane = new TreeDemo();
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();
}
});
}
}
DnD (drag and drop)JTree code
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly
*/
// TreeDragTest.java
//A simple starting point for testing the DnD JTree code.
//
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class TreeDragTest extends JFrame {
TreeDragSource ds;
TreeDropTarget dt;
JTree tree;
public TreeDragTest() {
super("Rearrangeable Tree");
setSize(300, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// If you want autoscrolling, use this line:
tree = new AutoScrollingJTree();
// Otherwise, use this line:
//tree = new JTree();
getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
// If we only support move operations...
//ds = new TreeDragSource(tree, DnDConstants.ACTION_MOVE);
ds = new TreeDragSource(tree, DnDConstants.ACTION_COPY_OR_MOVE);
dt = new TreeDropTarget(tree);
setVisible(true);
}
public class AutoScrollingJTree extends JTree implements Autoscroll {
private int margin = 12;
public AutoScrollingJTree() {
super();
}
public void autoscroll(Point p) {
int realrow = getRowForLocation(p.x, p.y);
Rectangle outer = getBounds();
realrow = (p.y + outer.y <= margin ? realrow < 1 ? 0 : realrow - 1
: realrow < getRowCount() - 1 ? realrow + 1 : realrow);
scrollRowToVisible(realrow);
}
public Insets getAutoscrollInsets() {
Rectangle outer = getBounds();
Rectangle inner = getParent().getBounds();
return new Insets(inner.y - outer.y + margin, inner.x - outer.x
+ margin, outer.height - inner.height - inner.y + outer.y
+ margin, outer.width - inner.width - inner.x + outer.x
+ margin);
}
// Use this method if you want to see the boundaries of the
// autoscroll active region
public void paintComponent(Graphics g) {
super.paintComponent(g);
Rectangle outer = getBounds();
Rectangle inner = getParent().getBounds();
g.setColor(Color.red);
g.drawRect(-outer.x + 12, -outer.y + 12, inner.width - 24,
inner.height - 24);
}
}
public static void main(String args[]) {
new TreeDragTest();
}
}
//TreeDragSource.java
//A drag source wrapper for a JTree. This class can be used to make
//a rearrangeable DnD tree with the TransferableTreeNode class as the
//transfer data type.
class TreeDragSource implements DragSourceListener, DragGestureListener {
DragSource source;
DragGestureRecognizer recognizer;
TransferableTreeNode transferable;
DefaultMutableTreeNode oldNode;
JTree sourceTree;
public TreeDragSource(JTree tree, int actions) {
sourceTree = tree;
source = new DragSource();
recognizer = source.createDefaultDragGestureRecognizer(sourceTree,
actions, this);
}
/*
* Drag Gesture Handler
*/
public void dragGestureRecognized(DragGestureEvent dge) {
TreePath path = sourceTree.getSelectionPath();
if ((path == null) || (path.getPathCount() <= 1)) {
// We can"t move the root node or an empty selection
return;
}
oldNode = (DefaultMutableTreeNode) path.getLastPathComponent();
transferable = new TransferableTreeNode(path);
source.startDrag(dge, DragSource.DefaultMoveNoDrop, transferable, this);
// If you support dropping the node anywhere, you should probably
// start with a valid move cursor:
//source.startDrag(dge, DragSource.DefaultMoveDrop, transferable,
// this);
}
/*
* Drag Event Handlers
*/
public void dragEnter(DragSourceDragEvent dsde) {
}
public void dragExit(DragSourceEvent dse) {
}
public void dragOver(DragSourceDragEvent dsde) {
}
public void dropActionChanged(DragSourceDragEvent dsde) {
System.out.println("Action: " + dsde.getDropAction());
System.out.println("Target Action: " + dsde.getTargetActions());
System.out.println("User Action: " + dsde.getUserAction());
}
public void dragDropEnd(DragSourceDropEvent dsde) {
/*
* to support move or copy, we have to check which occurred:
*/
System.out.println("Drop Action: " + dsde.getDropAction());
if (dsde.getDropSuccess()
&& (dsde.getDropAction() == DnDConstants.ACTION_MOVE)) {
((DefaultTreeModel) sourceTree.getModel())
.removeNodeFromParent(oldNode);
}
/*
* to support move only... if (dsde.getDropSuccess()) {
* ((DefaultTreeModel)sourceTree.getModel()).removeNodeFromParent(oldNode); }
*/
}
}
//TreeDropTarget.java
//A quick DropTarget that"s looking for drops from draggable JTrees.
//
class TreeDropTarget implements DropTargetListener {
DropTarget target;
JTree targetTree;
public TreeDropTarget(JTree tree) {
targetTree = tree;
target = new DropTarget(targetTree, this);
}
/*
* Drop Event Handlers
*/
private TreeNode getNodeForEvent(DropTargetDragEvent dtde) {
Point p = dtde.getLocation();
DropTargetContext dtc = dtde.getDropTargetContext();
JTree tree = (JTree) dtc.getComponent();
TreePath path = tree.getClosestPathForLocation(p.x, p.y);
return (TreeNode) path.getLastPathComponent();
}
public void dragEnter(DropTargetDragEvent dtde) {
TreeNode node = getNodeForEvent(dtde);
if (node.isLeaf()) {
dtde.rejectDrag();
} else {
// start by supporting move operations
//dtde.acceptDrag(DnDConstants.ACTION_MOVE);
dtde.acceptDrag(dtde.getDropAction());
}
}
public void dragOver(DropTargetDragEvent dtde) {
TreeNode node = getNodeForEvent(dtde);
if (node.isLeaf()) {
dtde.rejectDrag();
} else {
// start by supporting move operations
//dtde.acceptDrag(DnDConstants.ACTION_MOVE);
dtde.acceptDrag(dtde.getDropAction());
}
}
public void dragExit(DropTargetEvent dte) {
}
public void dropActionChanged(DropTargetDragEvent dtde) {
}
public void drop(DropTargetDropEvent dtde) {
Point pt = dtde.getLocation();
DropTargetContext dtc = dtde.getDropTargetContext();
JTree tree = (JTree) dtc.getComponent();
TreePath parentpath = tree.getClosestPathForLocation(pt.x, pt.y);
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) parentpath
.getLastPathComponent();
if (parent.isLeaf()) {
dtde.rejectDrop();
return;
}
try {
Transferable tr = dtde.getTransferable();
DataFlavor[] flavors = tr.getTransferDataFlavors();
for (int i = 0; i < flavors.length; i++) {
if (tr.isDataFlavorSupported(flavors[i])) {
dtde.acceptDrop(dtde.getDropAction());
TreePath p = (TreePath) tr.getTransferData(flavors[i]);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) p
.getLastPathComponent();
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
model.insertNodeInto(node, parent, 0);
dtde.dropComplete(true);
return;
}
}
dtde.rejectDrop();
} catch (Exception e) {
e.printStackTrace();
dtde.rejectDrop();
}
}
}
//TransferableTreeNode.java
//A Transferable TreePath to be used with Drag & Drop applications.
//
class TransferableTreeNode implements Transferable {
public static DataFlavor TREE_PATH_FLAVOR = new DataFlavor(TreePath.class,
"Tree Path");
DataFlavor flavors[] = { TREE_PATH_FLAVOR };
TreePath path;
public TransferableTreeNode(TreePath tp) {
path = tp;
}
public synchronized DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return (flavor.getRepresentationClass() == TreePath.class);
}
public synchronized Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (isDataFlavorSupported(flavor)) {
return (Object) path;
} else {
throw new UnsupportedFlavorException(flavor);
}
}
}
Drag and drop of a group of files into a tree
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class MyTree extends JTree {
public MyTree() {
super();
setDragEnabled(false);
setTransferHandler(new FSTransfer());
}
}
class FSTransfer extends TransferHandler {
public boolean importData(JComponent comp, Transferable t) {
if (!(comp instanceof MyTree)) {
return false;
}
if (!t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
return false;
}
MyTree tree = (MyTree) comp;
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
try {
List data = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
Iterator i = data.iterator();
while (i.hasNext()) {
File f = (File) i.next();
root.add(new DefaultMutableTreeNode(f.getName()));
}
model.reload();
return true;
} catch (Exception ioe) {
System.out.println(ioe);
}
return false;
}
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
if (comp instanceof MyTree) {
for (int i = 0; i < transferFlavors.length; i++) {
if (!transferFlavors[i].equals(DataFlavor.javaFileListFlavor)) {
return false;
}
}
return true;
}
return false;
}
}
Enabling and Disabling Multiple Selections in a JTree Component
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;
public class TreeSelectionOption {
public static void main(String[] argv) {
JTree tree = new JTree();
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
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);
}
}
Expand All for a tree path
/*
* soapUI, copyright (C) 2004-2009 eviware.ru
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class TreeUtils {
public static void expandAll(JTree tree, TreePath parent, boolean expand) {
// Traverse children
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, expand);
}
}
// Expansion or collapse must be done bottom-up
if (expand) {
tree.expandPath(parent);
} else {
tree.collapsePath(parent);
}
}
}
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);
}
}
Expansion and Collapse Events in a JTree are fired before a node is expanded or collapsed can be vetoed, thereby preventing the operation.
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
public class Main {
public static void main() {
JTree tree = new JTree();
tree.addTreeWillExpandListener(new MyTreeWillExpandListener());
tree.addTreeExpansionListener(new MyTreeExpansionListener());
JFrame f = new JFrame();
f.add(new JScrollPane(tree));
f.setSize(300, 300);
f.setVisible(true);
}
}
class MyTreeWillExpandListener implements TreeWillExpandListener {
public void treeWillExpand(TreeExpansionEvent evt) throws ExpandVetoException {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
boolean veto = false;
if (veto) {
throw new ExpandVetoException(evt);
}
}
public void treeWillCollapse(TreeExpansionEvent evt) throws ExpandVetoException {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
boolean veto = false;
if (veto) {
throw new ExpandVetoException(evt);
}
}
}
class MyTreeExpansionListener implements TreeExpansionListener {
public void treeExpanded(TreeExpansionEvent evt) {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
System.out.println("treeExpanded");
}
public void treeCollapsed(TreeExpansionEvent evt) {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
System.out.println("treeCollapsed");
}
}
File folder Tree with icons
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class FileTree1
extends JFrame
{
public static final ImageIcon ICON_COMPUTER =
new ImageIcon("computer.gif");
public static final ImageIcon ICON_DISK =
new ImageIcon("disk.gif");
public static final ImageIcon ICON_FOLDER =
new ImageIcon("folder.gif");
public static final ImageIcon ICON_EXPANDEDFOLDER =
new ImageIcon("expandedfolder.gif");
protected JTree m_tree;
protected DefaultTreeModel m_model;
protected JTextField m_display;
public FileTree1()
{
super("Directories Tree");
setSize(400, 300);
DefaultMutableTreeNode top = new DefaultMutableTreeNode(
new IconData(ICON_COMPUTER, null, "Computer"));
DefaultMutableTreeNode node;
File[] roots = File.listRoots();
for (int k=0; k<roots.length; k++)
{
node = new DefaultMutableTreeNode(new IconData(ICON_DISK,
null, new FileNode(roots[k])));
top.add(node);
node.add( new DefaultMutableTreeNode(new Boolean(true)));
}
m_model = new DefaultTreeModel(top);
m_tree = new JTree(m_model);
m_tree.putClientProperty("JTree.lineStyle", "Angled");
TreeCellRenderer renderer = new
IconCellRenderer();
m_tree.setCellRenderer(renderer);
m_tree.addTreeExpansionListener(new
DirExpansionListener());
m_tree.addTreeSelectionListener(new
DirSelectionListener());
m_tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
m_tree.setShowsRootHandles(true);
m_tree.setEditable(false);
JScrollPane s = new JScrollPane();
s.getViewport().add(m_tree);
getContentPane().add(s, BorderLayout.CENTER);
m_display = new JTextField();
m_display.setEditable(false);
getContentPane().add(m_display, BorderLayout.NORTH);
WindowListener wndCloser = new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
DefaultMutableTreeNode getTreeNode(TreePath path)
{
return (DefaultMutableTreeNode)(path.getLastPathComponent());
}
FileNode getFileNode(DefaultMutableTreeNode node)
{
if (node == null)
return null;
Object obj = node.getUserObject();
if (obj instanceof IconData)
obj = ((IconData)obj).getObject();
if (obj instanceof FileNode)
return (FileNode)obj;
else
return null;
}
// Make sure expansion is threaded and updating the tree model
// only occurs within the event dispatching thread.
class DirExpansionListener implements TreeExpansionListener
{
public void treeExpanded(TreeExpansionEvent event)
{
final DefaultMutableTreeNode node = getTreeNode(
event.getPath());
final FileNode fnode = getFileNode(node);
Thread runner = new Thread()
{
public void run()
{
if (fnode != null && fnode.expand(node))
{
Runnable runnable = new Runnable()
{
public void run()
{
m_model.reload(node);
}
};
SwingUtilities.invokeLater(runnable);
}
}
};
runner.start();
}
public void treeCollapsed(TreeExpansionEvent event) {}
}
class DirSelectionListener
implements TreeSelectionListener
{
public void valueChanged(TreeSelectionEvent event)
{
DefaultMutableTreeNode node = getTreeNode(
event.getPath());
FileNode fnode = getFileNode(node);
if (fnode != null)
m_display.setText(fnode.getFile().
getAbsolutePath());
else
m_display.setText("");
}
}
public static void main(String argv[])
{
new FileTree1();
}
}
class IconCellRenderer
extends JLabel
implements TreeCellRenderer
{
protected Color m_textSelectionColor;
protected Color m_textNonSelectionColor;
protected Color m_bkSelectionColor;
protected Color m_bkNonSelectionColor;
protected Color m_borderSelectionColor;
protected boolean m_selected;
public IconCellRenderer()
{
super();
m_textSelectionColor = UIManager.getColor(
"Tree.selectionForeground");
m_textNonSelectionColor = UIManager.getColor(
"Tree.textForeground");
m_bkSelectionColor = UIManager.getColor(
"Tree.selectionBackground");
m_bkNonSelectionColor = UIManager.getColor(
"Tree.textBackground");
m_borderSelectionColor = UIManager.getColor(
"Tree.selectionBorderColor");
setOpaque(false);
}
public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean sel, boolean expanded, boolean leaf,
int row, boolean hasFocus)
{
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)value;
Object obj = node.getUserObject();
setText(obj.toString());
if (obj instanceof Boolean)
setText("Retrieving data...");
if (obj instanceof IconData)
{
IconData idata = (IconData)obj;
if (expanded)
setIcon(idata.getExpandedIcon());
else
setIcon(idata.getIcon());
}
else
setIcon(null);
setFont(tree.getFont());
setForeground(sel ? m_textSelectionColor :
m_textNonSelectionColor);
setBackground(sel ? m_bkSelectionColor :
m_bkNonSelectionColor);
m_selected = sel;
return this;
}
public void paintComponent(Graphics g)
{
Color bColor = getBackground();
Icon icon = getIcon();
g.setColor(bColor);
int offset = 0;
if(icon != null && getText() != null)
offset = (icon.getIconWidth() + getIconTextGap());
g.fillRect(offset, 0, getWidth() - 1 - offset,
getHeight() - 1);
if (m_selected)
{
g.setColor(m_borderSelectionColor);
g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
}
super.paintComponent(g);
}
}
class IconData
{
protected Icon m_icon;
protected Icon m_expandedIcon;
protected Object m_data;
public IconData(Icon icon, Object data)
{
m_icon = icon;
m_expandedIcon = null;
m_data = data;
}
public IconData(Icon icon, Icon expandedIcon, Object data)
{
m_icon = icon;
m_expandedIcon = expandedIcon;
m_data = data;
}
public Icon getIcon()
{
return m_icon;
}
public Icon getExpandedIcon()
{
return m_expandedIcon!=null ? m_expandedIcon : m_icon;
}
public Object getObject()
{
return m_data;
}
public String toString()
{
return m_data.toString();
}
}
class FileNode
{
protected File m_file;
public FileNode(File file)
{
m_file = file;
}
public File getFile()
{
return m_file;
}
public String toString()
{
return m_file.getName().length() > 0 ? m_file.getName() :
m_file.getPath();
}
public boolean expand(DefaultMutableTreeNode parent)
{
DefaultMutableTreeNode flag =
(DefaultMutableTreeNode)parent.getFirstChild();
if (flag==null) // No flag
return false;
Object obj = flag.getUserObject();
if (!(obj instanceof Boolean))
return false; // Already expanded
parent.removeAllChildren(); // Remove Flag
File[] files = listFiles();
if (files == null)
return true;
Vector v = new Vector();
for (int k=0; k<files.length; k++)
{
File f = files[k];
if (!(f.isDirectory()))
continue;
FileNode newNode = new FileNode(f);
boolean isAdded = false;
for (int i=0; i<v.size(); i++)
{
FileNode nd = (FileNode)v.elementAt(i);
if (newNode.rupareTo(nd) < 0)
{
v.insertElementAt(newNode, i);
isAdded = true;
break;
}
}
if (!isAdded)
v.addElement(newNode);
}
for (int i=0; i<v.size(); i++)
{
FileNode nd = (FileNode)v.elementAt(i);
IconData idata = new IconData(FileTree1.ICON_FOLDER,
FileTree1.ICON_EXPANDEDFOLDER, nd);
DefaultMutableTreeNode node = new
DefaultMutableTreeNode(idata);
parent.add(node);
if (nd.hasSubDirs())
node.add(new DefaultMutableTreeNode(
new Boolean(true) ));
}
return true;
}
public boolean hasSubDirs()
{
File[] files = listFiles();
if (files == null)
return false;
for (int k=0; k<files.length; k++)
{
if (files[k].isDirectory())
return true;
}
return false;
}
public int compareTo(FileNode toCompare)
{
return m_file.getName().rupareToIgnoreCase(
toCompare.m_file.getName() );
}
protected File[] listFiles()
{
if (!m_file.isDirectory())
return null;
try
{
return m_file.listFiles();
}
catch (Exception ex)
{
JOptionPane.showMessageDialog(null,
"Error reading directory "+m_file.getAbsolutePath(),
"Warning", JOptionPane.WARNING_MESSAGE);
return null;
}
}
}
File System Tree
import java.io.File;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
public class FileTreeFrame extends JFrame {
private JTree fileTree;
private FileSystemModel fileSystemModel;
private JTextArea fileDetailsTextArea = new JTextArea();
public FileTreeFrame(String directory) {
super("JTree FileSystem Viewer");
fileDetailsTextArea.setEditable(false);
fileSystemModel = new FileSystemModel(new File(directory));
fileTree = new JTree(fileSystemModel);
fileTree.setEditable(true);
fileTree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent event) {
File file = (File) fileTree.getLastSelectedPathComponent();
fileDetailsTextArea.setText(getFileDetails(file));
}
});
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(
fileTree), new JScrollPane(fileDetailsTextArea));
getContentPane().add(splitPane);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(640, 480);
setVisible(true);
}
private String getFileDetails(File file) {
if (file == null)
return "";
StringBuffer buffer = new StringBuffer();
buffer.append("Name: " + file.getName() + "\n");
buffer.append("Path: " + file.getPath() + "\n");
buffer.append("Size: " + file.length() + "\n");
return buffer.toString();
}
public static void main(String args[]) {
new FileTreeFrame("c:\\");
}
}
class FileSystemModel implements TreeModel {
private File root;
private Vector listeners = new Vector();
public FileSystemModel(File rootDirectory) {
root = rootDirectory;
}
public Object getRoot() {
return root;
}
public Object getChild(Object parent, int index) {
File directory = (File) parent;
String[] children = directory.list();
return new TreeFile(directory, children[index]);
}
public int getChildCount(Object parent) {
File file = (File) parent;
if (file.isDirectory()) {
String[] fileList = file.list();
if (fileList != null)
return file.list().length;
}
return 0;
}
public boolean isLeaf(Object node) {
File file = (File) node;
return file.isFile();
}
public int getIndexOfChild(Object parent, Object child) {
File directory = (File) parent;
File file = (File) child;
String[] children = directory.list();
for (int i = 0; i < children.length; i++) {
if (file.getName().equals(children[i])) {
return i;
}
}
return -1;
}
public void valueForPathChanged(TreePath path, Object value) {
File oldFile = (File) path.getLastPathComponent();
String fileParentPath = oldFile.getParent();
String newFileName = (String) value;
File targetFile = new File(fileParentPath, newFileName);
oldFile.renameTo(targetFile);
File parent = new File(fileParentPath);
int[] changedChildrenIndices = { getIndexOfChild(parent, targetFile) };
Object[] changedChildren = { targetFile };
fireTreeNodesChanged(path.getParentPath(), changedChildrenIndices, changedChildren);
}
private void fireTreeNodesChanged(TreePath parentPath, int[] indices, Object[] children) {
TreeModelEvent event = new TreeModelEvent(this, parentPath, indices, children);
Iterator iterator = listeners.iterator();
TreeModelListener listener = null;
while (iterator.hasNext()) {
listener = (TreeModelListener) iterator.next();
listener.treeNodesChanged(event);
}
}
public void addTreeModelListener(TreeModelListener listener) {
listeners.add(listener);
}
public void removeTreeModelListener(TreeModelListener listener) {
listeners.remove(listener);
}
private class TreeFile extends File {
public TreeFile(File parent, String child) {
super(parent, child);
}
public String toString() {
return getName();
}
}
}
File Tree with Popup Menu
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class FileTree2
extends JFrame
{
public static final ImageIcon ICON_COMPUTER =
new ImageIcon("computer.gif");
public static final ImageIcon ICON_DISK =
new ImageIcon("disk.gif");
public static final ImageIcon ICON_FOLDER =
new ImageIcon("folder.gif");
public static final ImageIcon ICON_EXPANDEDFOLDER =
new ImageIcon("expandedfolder.gif");
protected JTree m_tree;
protected DefaultTreeModel m_model;
protected JTextField m_display;
// NEW
protected JPopupMenu m_popup;
protected Action m_action;
protected TreePath m_clickedPath;
public FileTree2()
{
super("Directories Tree [Popup Menus]");
setSize(400, 300);
DefaultMutableTreeNode top = new DefaultMutableTreeNode(
new IconData(ICON_COMPUTER, null, "Computer"));
DefaultMutableTreeNode node;
File[] roots = File.listRoots();
for (int k=0; k<roots.length; k++)
{
node = new DefaultMutableTreeNode(new IconData(ICON_DISK,
null, new FileNode(roots[k])));
top.add(node);
node.add(new DefaultMutableTreeNode( new Boolean(true) ));
}
m_model = new DefaultTreeModel(top);
m_tree = new JTree(m_model);
m_tree.putClientProperty("JTree.lineStyle", "Angled");
TreeCellRenderer renderer = new
IconCellRenderer();
m_tree.setCellRenderer(renderer);
m_tree.addTreeExpansionListener(new
DirExpansionListener());
m_tree.addTreeSelectionListener(new
DirSelectionListener());
m_tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
m_tree.setShowsRootHandles(true);
m_tree.setEditable(false);
JScrollPane s = new JScrollPane();
s.getViewport().add(m_tree);
getContentPane().add(s, BorderLayout.CENTER);
m_display = new JTextField();
m_display.setEditable(false);
getContentPane().add(m_display, BorderLayout.NORTH);
// NEW
m_popup = new JPopupMenu();
m_action = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
if (m_clickedPath==null)
return;
if (m_tree.isExpanded(m_clickedPath))
m_tree.collapsePath(m_clickedPath);
else
m_tree.expandPath(m_clickedPath);
}
};
m_popup.add(m_action);
m_popup.addSeparator();
Action a1 = new AbstractAction("Delete")
{
public void actionPerformed(ActionEvent e)
{
m_tree.repaint();
JOptionPane.showMessageDialog(FileTree2.this,
"Delete option is not implemented",
"Info", JOptionPane.INFORMATION_MESSAGE);
}
};
m_popup.add(a1);
Action a2 = new AbstractAction("Rename")
{
public void actionPerformed(ActionEvent e)
{
m_tree.repaint();
JOptionPane.showMessageDialog(FileTree2.this,
"Rename option is not implemented",
"Info", JOptionPane.INFORMATION_MESSAGE);
}
};
m_popup.add(a2);
m_tree.add(m_popup);
m_tree.addMouseListener(new PopupTrigger());
WindowListener wndCloser = new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
DefaultMutableTreeNode getTreeNode(TreePath path)
{
return (DefaultMutableTreeNode)(path.getLastPathComponent());
}
FileNode getFileNode(DefaultMutableTreeNode node)
{
if (node == null)
return null;
Object obj = node.getUserObject();
if (obj instanceof IconData)
obj = ((IconData)obj).getObject();
if (obj instanceof FileNode)
return (FileNode)obj;
else
return null;
}
// NEW
class PopupTrigger extends MouseAdapter
{
public void mouseReleased(MouseEvent e)
{
if (e.isPopupTrigger())
{
int x = e.getX();
int y = e.getY();
TreePath path = m_tree.getPathForLocation(x, y);
if (path != null)
{
if (m_tree.isExpanded(path))
m_action.putValue(Action.NAME, "Collapse");
else
m_action.putValue(Action.NAME, "Expand");
m_popup.show(m_tree, x, y);
m_clickedPath = path;
}
}
}
}
// Make sure expansion is threaded and updating the tree model
// only occurs within the event dispatching thread.
class DirExpansionListener implements TreeExpansionListener
{
public void treeExpanded(TreeExpansionEvent event)
{
final DefaultMutableTreeNode node = getTreeNode(
event.getPath());
final FileNode fnode = getFileNode(node);
Thread runner = new Thread()
{
public void run()
{
if (fnode != null && fnode.expand(node))
{
Runnable runnable = new Runnable()
{
public void run()
{
m_model.reload(node);
}
};
SwingUtilities.invokeLater(runnable);
}
}
};
runner.start();
}
public void treeCollapsed(TreeExpansionEvent event) {}
}
class DirSelectionListener
implements TreeSelectionListener
{
public void valueChanged(TreeSelectionEvent event)
{
DefaultMutableTreeNode node = getTreeNode(
event.getPath());
FileNode fnode = getFileNode(node);
if (fnode != null)
m_display.setText(fnode.getFile().
getAbsolutePath());
else
m_display.setText("");
}
}
public static void main(String argv[])
{
new FileTree2();
}
}
class IconCellRenderer
extends JLabel
implements TreeCellRenderer
{
protected Color m_textSelectionColor;
protected Color m_textNonSelectionColor;
protected Color m_bkSelectionColor;
protected Color m_bkNonSelectionColor;
protected Color m_borderSelectionColor;
protected boolean m_selected;
public IconCellRenderer()
{
super();
m_textSelectionColor = UIManager.getColor(
"Tree.selectionForeground");
m_textNonSelectionColor = UIManager.getColor(
"Tree.textForeground");
m_bkSelectionColor = UIManager.getColor(
"Tree.selectionBackground");
m_bkNonSelectionColor = UIManager.getColor(
"Tree.textBackground");
m_borderSelectionColor = UIManager.getColor(
"Tree.selectionBorderColor");
setOpaque(false);
}
public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean sel, boolean expanded, boolean leaf,
int row, boolean hasFocus)
{
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)value;
Object obj = node.getUserObject();
setText(obj.toString());
if (obj instanceof Boolean)
setText("Retrieving data...");
if (obj instanceof IconData)
{
IconData idata = (IconData)obj;
if (expanded)
setIcon(idata.getExpandedIcon());
else
setIcon(idata.getIcon());
}
else
setIcon(null);
setFont(tree.getFont());
setForeground(sel ? m_textSelectionColor :
m_textNonSelectionColor);
setBackground(sel ? m_bkSelectionColor :
m_bkNonSelectionColor);
m_selected = sel;
return this;
}
public void paintComponent(Graphics g)
{
Color bColor = getBackground();
Icon icon = getIcon();
g.setColor(bColor);
int offset = 0;
if(icon != null && getText() != null)
offset = (icon.getIconWidth() + getIconTextGap());
g.fillRect(offset, 0, getWidth() - 1 - offset,
getHeight() - 1);
if (m_selected)
{
g.setColor(m_borderSelectionColor);
g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
}
super.paintComponent(g);
}
}
class IconData
{
protected Icon m_icon;
protected Icon m_expandedIcon;
protected Object m_data;
public IconData(Icon icon, Object data)
{
m_icon = icon;
m_expandedIcon = null;
m_data = data;
}
public IconData(Icon icon, Icon expandedIcon, Object data)
{
m_icon = icon;
m_expandedIcon = expandedIcon;
m_data = data;
}
public Icon getIcon()
{
return m_icon;
}
public Icon getExpandedIcon()
{
return m_expandedIcon!=null ? m_expandedIcon : m_icon;
}
public Object getObject()
{
return m_data;
}
public String toString()
{
return m_data.toString();
}
}
class FileNode
{
protected File m_file;
public FileNode(File file)
{
m_file = file;
}
public File getFile()
{
return m_file;
}
public String toString()
{
return m_file.getName().length() > 0 ? m_file.getName() :
m_file.getPath();
}
public boolean expand(DefaultMutableTreeNode parent)
{
DefaultMutableTreeNode flag =
(DefaultMutableTreeNode)parent.getFirstChild();
if (flag==null) // No flag
return false;
Object obj = flag.getUserObject();
if (!(obj instanceof Boolean))
return false; // Already expanded
parent.removeAllChildren(); // Remove Flag
File[] files = listFiles();
if (files == null)
return true;
Vector v = new Vector();
for (int k=0; k<files.length; k++)
{
File f = files[k];
if (!(f.isDirectory()))
continue;
FileNode newNode = new FileNode(f);
boolean isAdded = false;
for (int i=0; i<v.size(); i++)
{
FileNode nd = (FileNode)v.elementAt(i);
if (newNode.rupareTo(nd) < 0)
{
v.insertElementAt(newNode, i);
isAdded = true;
break;
}
}
if (!isAdded)
v.addElement(newNode);
}
for (int i=0; i<v.size(); i++)
{
FileNode nd = (FileNode)v.elementAt(i);
IconData idata = new IconData(FileTree2.ICON_FOLDER,
FileTree2.ICON_EXPANDEDFOLDER, nd);
DefaultMutableTreeNode node = new
DefaultMutableTreeNode(idata);
parent.add(node);
if (nd.hasSubDirs())
node.add(new DefaultMutableTreeNode(
new Boolean(true) ));
}
return true;
}
public boolean hasSubDirs()
{
File[] files = listFiles();
if (files == null)
return false;
for (int k=0; k<files.length; k++)
{
if (files[k].isDirectory())
return true;
}
return false;
}
public int compareTo(FileNode toCompare)
{
return m_file.getName().rupareToIgnoreCase(
toCompare.m_file.getName() );
}
protected File[] listFiles()
{
if (!m_file.isDirectory())
return null;
try
{
return m_file.listFiles();
}
catch (Exception ex)
{
JOptionPane.showMessageDialog(null,
"Error reading directory "+m_file.getAbsolutePath(),
"Warning", JOptionPane.WARNING_MESSAGE);
return null;
}
}
}
File Tree with Tooltips
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class FileTree3
extends JFrame
{
public static final ImageIcon ICON_COMPUTER =
new ImageIcon("computer.gif");
public static final ImageIcon ICON_DISK =
new ImageIcon("disk.gif");
public static final ImageIcon ICON_FOLDER =
new ImageIcon("folder.gif");
public static final ImageIcon ICON_EXPANDEDFOLDER =
new ImageIcon("expandedfolder.gif");
protected JTree m_tree;
protected DefaultTreeModel m_model;
protected JTextField m_display;
protected JPopupMenu m_popup;
protected Action m_action;
protected TreePath m_clickedPath;
public FileTree3()
{
super("Directories Tree [Tool Tips]");
setSize(400, 300);
DefaultMutableTreeNode top = new DefaultMutableTreeNode(
new IconData(ICON_COMPUTER, null, "Computer"));
DefaultMutableTreeNode node;
File[] roots = File.listRoots();
for (int k=0; k<roots.length; k++)
{
node = new DefaultMutableTreeNode(new IconData(ICON_DISK,
null, new FileNode(roots[k])));
top.add(node);
node.add(new DefaultMutableTreeNode( new Boolean(true) ));
}
m_model = new DefaultTreeModel(top);
// NEW
m_tree = new JTree(m_model)
{
public String getToolTipText(MouseEvent ev)
{
if(ev == null)
return null;
TreePath path = m_tree.getPathForLocation(ev.getX(),
ev.getY());
if (path != null)
{
FileNode fnode = getFileNode(getTreeNode(path));
if (fnode==null)
return null;
File f = fnode.getFile();
return (f==null ? null : f.getPath());
}
return null;
}
};
ToolTipManager.sharedInstance().registerComponent(m_tree);
m_tree.putClientProperty("JTree.lineStyle", "Angled");
TreeCellRenderer renderer = new
IconCellRenderer();
m_tree.setCellRenderer(renderer);
m_tree.addTreeExpansionListener(new
DirExpansionListener());
m_tree.addTreeSelectionListener(new
DirSelectionListener());
m_tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
m_tree.setShowsRootHandles(true);
m_tree.setEditable(false);
JScrollPane s = new JScrollPane();
s.getViewport().add(m_tree);
getContentPane().add(s, BorderLayout.CENTER);
m_display = new JTextField();
m_display.setEditable(false);
getContentPane().add(m_display, BorderLayout.NORTH);
m_popup = new JPopupMenu();
m_action = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
if (m_clickedPath==null)
return;
if (m_tree.isExpanded(m_clickedPath))
m_tree.collapsePath(m_clickedPath);
else
m_tree.expandPath(m_clickedPath);
}
};
m_popup.add(m_action);
m_popup.addSeparator();
Action a1 = new AbstractAction("Delete")
{
public void actionPerformed(ActionEvent e)
{
m_tree.repaint();
JOptionPane.showMessageDialog(FileTree3.this,
"Delete option is not implemented",
"Info", JOptionPane.INFORMATION_MESSAGE);
}
};
m_popup.add(a1);
Action a2 = new AbstractAction("Rename")
{
public void actionPerformed(ActionEvent e)
{
m_tree.repaint();
JOptionPane.showMessageDialog(FileTree3.this,
"Rename option is not implemented",
"Info", JOptionPane.INFORMATION_MESSAGE);
}
};
m_popup.add(a2);
m_tree.add(m_popup);
m_tree.addMouseListener(new PopupTrigger());
WindowListener wndCloser = new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
DefaultMutableTreeNode getTreeNode(TreePath path)
{
return (DefaultMutableTreeNode)(path.getLastPathComponent());
}
FileNode getFileNode(DefaultMutableTreeNode node)
{
if (node == null)
return null;
Object obj = node.getUserObject();
if (obj instanceof IconData)
obj = ((IconData)obj).getObject();
if (obj instanceof FileNode)
return (FileNode)obj;
else
return null;
}
class PopupTrigger extends MouseAdapter
{
public void mouseReleased(MouseEvent e)
{
if (e.isPopupTrigger())
{
int x = e.getX();
int y = e.getY();
TreePath path = m_tree.getPathForLocation(x, y);
if (path != null)
{
if (m_tree.isExpanded(path))
m_action.putValue(Action.NAME, "Collapse");
else
m_action.putValue(Action.NAME, "Expand");
m_popup.show(m_tree, x, y);
m_clickedPath = path;
}
}
}
}
// Make sure expansion is threaded and updating the tree model
// only occurs within the event dispatching thread.
class DirExpansionListener implements TreeExpansionListener
{
public void treeExpanded(TreeExpansionEvent event)
{
final DefaultMutableTreeNode node = getTreeNode(
event.getPath());
final FileNode fnode = getFileNode(node);
Thread runner = new Thread()
{
public void run()
{
if (fnode != null && fnode.expand(node))
{
Runnable runnable = new Runnable()
{
public void run()
{
m_model.reload(node);
}
};
SwingUtilities.invokeLater(runnable);
}
}
};
runner.start();
}
public void treeCollapsed(TreeExpansionEvent event) {}
}
class DirSelectionListener
implements TreeSelectionListener
{
public void valueChanged(TreeSelectionEvent event)
{
DefaultMutableTreeNode node = getTreeNode(
event.getPath());
FileNode fnode = getFileNode(node);
if (fnode != null)
m_display.setText(fnode.getFile().
getAbsolutePath());
else
m_display.setText("");
}
}
public static void main(String argv[])
{
new FileTree3();
}
}
class IconCellRenderer
extends JLabel
implements TreeCellRenderer
{
protected Color m_textSelectionColor;
protected Color m_textNonSelectionColor;
protected Color m_bkSelectionColor;
protected Color m_bkNonSelectionColor;
protected Color m_borderSelectionColor;
protected boolean m_selected;
public IconCellRenderer()
{
super();
m_textSelectionColor = UIManager.getColor(
"Tree.selectionForeground");
m_textNonSelectionColor = UIManager.getColor(
"Tree.textForeground");
m_bkSelectionColor = UIManager.getColor(
"Tree.selectionBackground");
m_bkNonSelectionColor = UIManager.getColor(
"Tree.textBackground");
m_borderSelectionColor = UIManager.getColor(
"Tree.selectionBorderColor");
setOpaque(false);
}
public Component getTreeCellRendererComponent(JTree tree,
Object value, boolean sel, boolean expanded, boolean leaf,
int row, boolean hasFocus)
{
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)value;
Object obj = node.getUserObject();
setText(obj.toString());
if (obj instanceof Boolean)
setText("Retrieving data...");
if (obj instanceof IconData)
{
IconData idata = (IconData)obj;
if (expanded)
setIcon(idata.getExpandedIcon());
else
setIcon(idata.getIcon());
}
else
setIcon(null);
setFont(tree.getFont());
setForeground(sel ? m_textSelectionColor :
m_textNonSelectionColor);
setBackground(sel ? m_bkSelectionColor :
m_bkNonSelectionColor);
m_selected = sel;
return this;
}
public void paintComponent(Graphics g)
{
Color bColor = getBackground();
Icon icon = getIcon();
g.setColor(bColor);
int offset = 0;
if(icon != null && getText() != null)
offset = (icon.getIconWidth() + getIconTextGap());
g.fillRect(offset, 0, getWidth() - 1 - offset,
getHeight() - 1);
if (m_selected)
{
g.setColor(m_borderSelectionColor);
g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
}
super.paintComponent(g);
}
}
class IconData
{
protected Icon m_icon;
protected Icon m_expandedIcon;
protected Object m_data;
public IconData(Icon icon, Object data)
{
m_icon = icon;
m_expandedIcon = null;
m_data = data;
}
public IconData(Icon icon, Icon expandedIcon, Object data)
{
m_icon = icon;
m_expandedIcon = expandedIcon;
m_data = data;
}
public Icon getIcon()
{
return m_icon;
}
public Icon getExpandedIcon()
{
return m_expandedIcon!=null ? m_expandedIcon : m_icon;
}
public Object getObject()
{
return m_data;
}
public String toString()
{
return m_data.toString();
}
}
class FileNode
{
protected File m_file;
public FileNode(File file)
{
m_file = file;
}
public File getFile()
{
return m_file;
}
public String toString()
{
return m_file.getName().length() > 0 ? m_file.getName() :
m_file.getPath();
}
public boolean expand(DefaultMutableTreeNode parent)
{
DefaultMutableTreeNode flag =
(DefaultMutableTreeNode)parent.getFirstChild();
if (flag==null) // No flag
return false;
Object obj = flag.getUserObject();
if (!(obj instanceof Boolean))
return false; // Already expanded
parent.removeAllChildren(); // Remove Flag
File[] files = listFiles();
if (files == null)
return true;
Vector v = new Vector();
for (int k=0; k<files.length; k++)
{
File f = files[k];
if (!(f.isDirectory()))
continue;
FileNode newNode = new FileNode(f);
boolean isAdded = false;
for (int i=0; i<v.size(); i++)
{
FileNode nd = (FileNode)v.elementAt(i);
if (newNode.rupareTo(nd) < 0)
{
v.insertElementAt(newNode, i);
isAdded = true;
break;
}
}
if (!isAdded)
v.addElement(newNode);
}
for (int i=0; i<v.size(); i++)
{
FileNode nd = (FileNode)v.elementAt(i);
IconData idata = new IconData(FileTree3.ICON_FOLDER,
FileTree3.ICON_EXPANDEDFOLDER, nd);
DefaultMutableTreeNode node = new
DefaultMutableTreeNode(idata);
parent.add(node);
if (nd.hasSubDirs())
node.add(new DefaultMutableTreeNode(
new Boolean(true) ));
}
return true;
}
public boolean hasSubDirs()
{
File[] files = listFiles();
if (files == null)
return false;
for (int k=0; k<files.length; k++)
{
if (files[k].isDirectory())
return true;
}
return false;
}
public int compareTo(FileNode toCompare)
{
return m_file.getName().rupareToIgnoreCase(
toCompare.m_file.getName() );
}
protected File[] listFiles()
{
if (!m_file.isDirectory())
return null;
try
{
return m_file.listFiles();
}
catch (Exception ex)
{
JOptionPane.showMessageDialog(null,
"Error reading directory "+m_file.getAbsolutePath(),
"Warning", JOptionPane.WARNING_MESSAGE);
return null;
}
}
}
Finding a Node in a JTree Component
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) throws Exception {
JTree tree = new JTree();
// Search forward from first visible row looking for any visible node
// whose name starts with prefix.
int startRow = 0;
String prefix = "b";
TreePath path = tree.getNextMatch(prefix, startRow, Position.Bias.Forward);
System.out.println(path);
}
}
Find the path regardless of visibility that matches the specified sequence of names
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) throws Exception {
JTree tree = new JTree();
TreePath path = findByName(tree, new String[] { "JTree", "A", "a" });
}
public static TreePath findByName(JTree tree, String[] names) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
return find(tree, new TreePath(root), names, 0);
}
private static TreePath find(JTree tree, TreePath parent, Object[] nodes, int depth) {
TreeNode node = (TreeNode) parent.getLastPathComponent();
Object o = node;
if (o.equals(nodes[depth])) {
if (depth == nodes.length - 1) {
return parent;
}
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
TreePath result = find(tree, path, nodes, depth + 1);
if (result != null) {
return result;
}
}
}
}
return null;
}
}
Flush the internal cache of Row height
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeightCache {
public static void main(String[] argv) {
JTree tree = new JTree();
if (tree.getRowHeight() <= 0) {
tree.setRowHeight(1);
}
tree.setRowHeight(0);
JFrame frame = new JFrame("Image");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Genealogy Tree
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 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:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution 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, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
/*
* A 1.4 example that uses the following files: GenealogyModel.java Person.java
*
* Based on an example provided by tutorial reader Olivier Berlanger.
*/
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
public class GenealogyExample extends JPanel implements ActionListener {
GenealogyTree tree;
private static String SHOW_ANCESTOR_CMD = "showAncestor";
public GenealogyExample() {
super(new BorderLayout());
//Construct the panel with the toggle buttons.
JRadioButton showDescendant = new JRadioButton("Show descendants", true);
final JRadioButton showAncestor = new JRadioButton("Show ancestors");
ButtonGroup bGroup = new ButtonGroup();
bGroup.add(showDescendant);
bGroup.add(showAncestor);
showDescendant.addActionListener(this);
showAncestor.addActionListener(this);
showAncestor.setActionCommand(SHOW_ANCESTOR_CMD);
JPanel buttonPanel = new JPanel();
buttonPanel.add(showDescendant);
buttonPanel.add(showAncestor);
//Construct the tree.
tree = new GenealogyTree(getGenealogyGraph());
JScrollPane scrollPane = new JScrollPane(tree);
scrollPane.setPreferredSize(new Dimension(200, 200));
//Add everything to this panel.
add(buttonPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
}
/**
* Required by the ActionListener interface. Handle events on the
* showDescendant and showAncestore buttons.
*/
public void actionPerformed(ActionEvent ae) {
if (ae.getActionCommand() == SHOW_ANCESTOR_CMD) {
tree.showAncestor(true);
} else {
tree.showAncestor(false);
}
}
/**
* Constructs the genealogy graph used by the model.
*/
public Person getGenealogyGraph() {
//the greatgrandparent generation
Person a1 = new Person("Jack (great-granddaddy)");
Person a2 = new Person("Jean (great-granny)");
Person a3 = new Person("Albert (great-granddaddy)");
Person a4 = new Person("Rae (great-granny)");
Person a5 = new Person("Paul (great-granddaddy)");
Person a6 = new Person("Josie (great-granny)");
//the grandparent generation
Person b1 = new Person("Peter (grandpa)");
Person b2 = new Person("Zoe (grandma)");
Person b3 = new Person("Simon (grandpa)");
Person b4 = new Person("James (grandpa)");
Person b5 = new Person("Bertha (grandma)");
Person b6 = new Person("Veronica (grandma)");
Person b7 = new Person("Anne (grandma)");
Person b8 = new Person("Renee (grandma)");
Person b9 = new Person("Joseph (grandpa)");
//the parent generation
Person c1 = new Person("Isabelle (mom)");
Person c2 = new Person("Frank (dad)");
Person c3 = new Person("Louis (dad)");
Person c4 = new Person("Laurence (dad)");
Person c5 = new Person("Valerie (mom)");
Person c6 = new Person("Marie (mom)");
Person c7 = new Person("Helen (mom)");
Person c8 = new Person("Mark (dad)");
Person c9 = new Person("Oliver (dad)");
//the youngest generation
Person d1 = new Person("Clement (boy)");
Person d2 = new Person("Colin (boy)");
Person.linkFamily(a1, a2, new Person[] { b1, b2, b3, b4 });
Person.linkFamily(a3, a4, new Person[] { b5, b6, b7 });
Person.linkFamily(a5, a6, new Person[] { b8, b9 });
Person.linkFamily(b3, b6, new Person[] { c1, c2, c3 });
Person.linkFamily(b4, b5, new Person[] { c4, c5, c6 });
Person.linkFamily(b8, b7, new Person[] { c7, c8, c9 });
Person.linkFamily(c4, c7, new Person[] { d1, d2 });
return a1;
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("GenealogyExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
GenealogyExample newContentPane = new GenealogyExample();
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();
}
});
}
}
class GenealogyModel implements TreeModel {
private boolean showAncestors;
private Vector treeModelListeners = new Vector();
private Person rootPerson;
public GenealogyModel(Person root) {
showAncestors = false;
rootPerson = root;
}
/**
* Used to toggle between show ancestors/show descendant and to change the
* root of the tree.
*/
public void showAncestor(boolean b, Object newRoot) {
showAncestors = b;
Person oldRoot = rootPerson;
if (newRoot != null) {
rootPerson = (Person) newRoot;
}
fireTreeStructureChanged(oldRoot);
}
//////////////// Fire events //////////////////////////////////////////////
/**
* The only event raised by this model is TreeStructureChanged with the root
* as path, i.e. the whole tree has changed.
*/
protected void fireTreeStructureChanged(Person oldRoot) {
int len = treeModelListeners.size();
TreeModelEvent e = new TreeModelEvent(this, new Object[] { oldRoot });
for (int i = 0; i < len; i++) {
((TreeModelListener) treeModelListeners.elementAt(i))
.treeStructureChanged(e);
}
}
//////////////// TreeModel interface implementation ///////////////////////
/**
* Adds a listener for the TreeModelEvent posted after the tree changes.
*/
public void addTreeModelListener(TreeModelListener l) {
treeModelListeners.addElement(l);
}
/**
* Returns the child of parent at index index in the parent"s child array.
*/
public Object getChild(Object parent, int index) {
Person p = (Person) parent;
if (showAncestors) {
if ((index > 0) && (p.getFather() != null)) {
return p.getMother();
}
return p.getFather();
}
return p.getChildAt(index);
}
/**
* Returns the number of children of parent.
*/
public int getChildCount(Object parent) {
Person p = (Person) parent;
if (showAncestors) {
int count = 0;
if (p.getFather() != null) {
count++;
}
if (p.getMother() != null) {
count++;
}
return count;
}
return p.getChildCount();
}
/**
* Returns the index of child in parent.
*/
public int getIndexOfChild(Object parent, Object child) {
Person p = (Person) parent;
if (showAncestors) {
int count = 0;
Person father = p.getFather();
if (father != null) {
count++;
if (father == child) {
return 0;
}
}
if (p.getMother() != child) {
return count;
}
return -1;
}
return p.getIndexOfChild((Person) child);
}
/**
* Returns the root of the tree.
*/
public Object getRoot() {
return rootPerson;
}
/**
* Returns true if node is a leaf.
*/
public boolean isLeaf(Object node) {
Person p = (Person) node;
if (showAncestors) {
return ((p.getFather() == null) && (p.getMother() == null));
}
return p.getChildCount() == 0;
}
/**
* Removes a listener previously added with addTreeModelListener().
*/
public void removeTreeModelListener(TreeModelListener l) {
treeModelListeners.removeElement(l);
}
/**
* Messaged when the user has altered the value for the item identified by
* path to newValue. Not used by this model.
*/
public void valueForPathChanged(TreePath path, Object newValue) {
System.out.println("*** valueForPathChanged : " + path + " --> "
+ newValue);
}
}
class Person {
Person father;
Person mother;
Vector children;
private String name;
public Person(String name) {
this.name = name;
mother = father = null;
children = new Vector();
}
/**
* Link together all members of a family.
*
* @param pa
* the father
* @param ma
* the mother
* @param kids
* the children
*/
public static void linkFamily(Person pa, Person ma, Person[] kids) {
int len = kids.length;
Person kid = null;
for (int i = 0; i < len; i++) {
kid = kids[i];
pa.children.addElement(kid);
ma.children.addElement(kid);
kid.father = pa;
kid.mother = ma;
}
}
/// getter methods ///////////////////////////////////
public String toString() {
return name;
}
public String getName() {
return name;
}
public Person getFather() {
return father;
}
public Person getMother() {
return mother;
}
public int getChildCount() {
return children.size();
}
public Person getChildAt(int i) {
return (Person) children.elementAt(i);
}
public int getIndexOfChild(Person kid) {
return children.indexOf(kid);
}
}
class GenealogyTree extends JTree {
GenealogyModel model;
public GenealogyTree(Person graphNode) {
super(new GenealogyModel(graphNode));
getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
Icon personIcon = null;
renderer.setLeafIcon(personIcon);
renderer.setClosedIcon(personIcon);
renderer.setOpenIcon(personIcon);
setCellRenderer(renderer);
}
/**
* Get the selected item in the tree, and call showAncestor with this item
* on the model.
*/
public void showAncestor(boolean b) {
Object newRoot = null;
TreePath path = getSelectionModel().getSelectionPath();
if (path != null) {
newRoot = path.getLastPathComponent();
}
((GenealogyModel) getModel()).showAncestor(b, newRoot);
}
}
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);
}
}
}
}
Getting the Selected Nodes in a JTree Component
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) throws Exception {
JTree tree = new JTree();
JFrame f = new JFrame();
f.add(new JScrollPane(tree));
f.setSize(300, 300);
f.setVisible(true);
// Get paths of all selected nodes
TreePath[] paths = tree.getSelectionPaths();
}
}
Get tree path from TreeNode
import java.util.ArrayList;
import java.util.List;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Utils {
public static TreePath getPath(TreeNode treeNode) {
List<Object> nodes = new ArrayList<Object>();
if (treeNode != null) {
nodes.add(treeNode);
treeNode = treeNode.getParent();
while (treeNode != null) {
nodes.add(0, treeNode);
treeNode = treeNode.getParent();
}
}
return nodes.isEmpty() ? null : new TreePath(nodes.toArray());
}
}
Have a popup attached to a JTree
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main extends JPanel {
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root", true),
node1 = new DefaultMutableTreeNode("node 1", true), node2 = new DefaultMutableTreeNode(
"node 2", true), node3 = new DefaultMutableTreeNode("node 3", true);
MyJTree tree = new MyJTree(root);
public Main() {
root.add(node1);
node1.add(node2);
root.add(node3);
setLayout(new BorderLayout());
add(new JScrollPane((JTree) tree), "Center");
}
public static void main(String s[]) {
JFrame frame = new JFrame("Tree With Popup");
Main panel = new Main();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setBackground(Color.lightGray);
frame.getContentPane().add(panel, "Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class MyJTree extends JTree implements ActionListener {
JPopupMenu popup = new JPopupMenu();
JMenuItem mi = new JMenuItem("Insert a children");
MyJTree(DefaultMutableTreeNode dmtn) {
super(dmtn);
mi.addActionListener(this);
mi.setActionCommand("insert");
popup.add(mi);
mi = new JMenuItem("Remove this node");
mi.addActionListener(this);
mi.setActionCommand("remove");
popup.add(mi);
addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show((JComponent) e.getSource(), e.getX(), e.getY());
}
}
});
}
public void actionPerformed(ActionEvent ae) {
DefaultMutableTreeNode dmtn, node;
TreePath path = this.getSelectionPath();
dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
if (ae.getActionCommand().equals("insert")) {
node = new DefaultMutableTreeNode("children");
dmtn.add(node);
((DefaultTreeModel) this.getModel()).nodeStructureChanged((TreeNode) dmtn);
}
if (ae.getActionCommand().equals("remove")) {
node = (DefaultMutableTreeNode) dmtn.getParent();
int nodeIndex = node.getIndex(dmtn);
dmtn.removeAllChildren();
node.remove(nodeIndex);
((DefaultTreeModel) this.getModel()).nodeStructureChanged((TreeNode) dmtn);
}
}
}
Have the row height for each row computed individually
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeightCalculation {
public static void main(String[] argv) {
JTree tree = new JTree();
tree.setRowHeight(0);
JFrame frame = new JFrame("tree row height calculation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
implements TreeSelectionListener to create your own listener
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class Tree1
extends JFrame
{
protected JTree m_tree = null;
protected DefaultTreeModel m_model = null;
protected JTextField m_display;
public Tree1()
{
super("Sample Tree [OID]");
setSize(400, 300);
Object[] nodes = new Object[5];
DefaultMutableTreeNode top = new DefaultMutableTreeNode(
new OidNode(1, "ISO"));
DefaultMutableTreeNode parent = top;
nodes[0] = top;
DefaultMutableTreeNode node = new DefaultMutableTreeNode(
new OidNode(0, "standard"));
parent.add(node);
node = new DefaultMutableTreeNode(new OidNode(2,
"member-body"));
parent.add(node);
node = new DefaultMutableTreeNode(new OidNode(3, "org"));
parent.add(node);
parent = node;
nodes[1] = parent;
node = new DefaultMutableTreeNode(new OidNode(6, "dod"));
parent.add(node);
parent = node;
nodes[2] = parent;
node = new DefaultMutableTreeNode(new OidNode(1,
"internet"));
parent.add(node);
parent = node;
nodes[3] = parent;
node = new DefaultMutableTreeNode(new OidNode(1,
"directory"));
parent.add(node);
node = new DefaultMutableTreeNode(new OidNode(2,
"mgmt"));
parent.add(node);
nodes[4] = node;
node.add(new DefaultMutableTreeNode(new OidNode(1,
"mib-2")));
node = new DefaultMutableTreeNode(new OidNode(3,
"experimental"));
parent.add(node);
node = new DefaultMutableTreeNode(new OidNode(4,
"private"));
node.add(new DefaultMutableTreeNode(new OidNode(1,
"enterprises")));
parent.add(node);
node = new DefaultMutableTreeNode(new OidNode(5,
"security"));
parent.add(node);
node = new DefaultMutableTreeNode(new OidNode(6,
"snmpV2"));
parent.add(node);
node = new DefaultMutableTreeNode(new OidNode(7,
"mail"));
parent.add(node);
m_model = new DefaultTreeModel(top);
m_tree = new JTree(m_model);
DefaultTreeCellRenderer renderer = new
DefaultTreeCellRenderer();
renderer.setOpenIcon(new ImageIcon("opened.gif"));
renderer.setClosedIcon(new ImageIcon("closed.gif"));
renderer.setLeafIcon(new ImageIcon("leaf.gif"));
m_tree.setCellRenderer(renderer);
m_tree.setShowsRootHandles(true);
m_tree.setEditable(false);
TreePath path = new TreePath(nodes);
m_tree.setSelectionPath(path);
m_tree.addTreeSelectionListener(new
OidSelectionListener());
JScrollPane s = new JScrollPane();
s.getViewport().add(m_tree);
getContentPane().add(s, BorderLayout.CENTER);
m_display = new JTextField();
m_display.setEditable(false);
getContentPane().add(m_display, BorderLayout.SOUTH);
WindowListener wndCloser = new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
public static void main(String argv[])
{
new Tree1();
}
class OidSelectionListener
implements TreeSelectionListener
{
public void valueChanged(TreeSelectionEvent e)
{
TreePath path = e.getPath();
Object[] nodes = path.getPath();
String oid = "";
for (int k=0; k<nodes.length; k++)
{
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)nodes[k];
OidNode nd = (OidNode)node.getUserObject();
oid += "."+nd.getId();
}
m_display.setText(oid);
}
}
}
class OidNode
{
protected int m_id;
protected String m_name;
public OidNode(int id, String name)
{
m_id = id;
m_name = name;
}
public int getId()
{
return m_id;
}
public String getName()
{
return m_name;
}
public String toString()
{
return m_name;
}
}
Installs custom icons
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly
*/
// TestTree3.java
//A variation on TestTree that installs custom icons. The icons installed
//will appear on *every* tree.
//
import java.awt.BorderLayout;
import java.util.Hashtable;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultTreeModel;
public class TestTree3 extends JFrame {
JTree tree;
DefaultTreeModel treeModel;
public TestTree3() {
super("Tree Test Example");
setSize(200, 150);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// Add our own customized tree icons.
UIManager.put("Tree.leafIcon", new ImageIcon("world.gif"));
UIManager.put("Tree.openIcon", new ImageIcon("door.open.gif"));
UIManager.put("Tree.closedIcon", new ImageIcon("door.closed.gif"));
UIManager.put("Tree.expandedIcon", new ImageIcon("unlocked.gif"));
UIManager.put("Tree.collapsedIcon", new ImageIcon("locked.gif"));
}
public void init() {
// Build the hierarchy of containers & objects.
String[] schoolyard = { "School", "Playground", "Parking Lot", "Field" };
String[] mainstreet = { "Grocery", "Shoe Shop", "Five & Dime",
"Post Office" };
String[] highway = { "Gas Station", "Convenience Store" };
String[] housing = { "Victorian_blue", "Faux Colonial",
"Victorian_white" };
String[] housing2 = { "Mission", "Ranch", "Condo" };
Hashtable homeHash = new Hashtable();
homeHash.put("Residential 1", housing);
homeHash.put("Residential 2", housing2);
Hashtable cityHash = new Hashtable();
cityHash.put("School grounds", schoolyard);
cityHash.put("Downtown", mainstreet);
cityHash.put("Highway", highway);
cityHash.put("Housing", homeHash);
Hashtable worldHash = new Hashtable();
worldHash.put("My First VRML World", cityHash);
// Build our tree out of our big hash table.
tree = new JTree(worldHash);
// Pick an angled line style.
tree.putClientProperty("JTree.lineStyle", "Angled");
getContentPane().add(tree, BorderLayout.CENTER);
}
public static void main(String args[]) {
TestTree3 tt = new TestTree3();
tt.init();
tt.setVisible(true);
}
}
Install ToolTips for Tree (JTree)
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.util.Dictionary;
import java.util.Properties;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;
public class TreeTips {
public static void main(String args[]) {
JFrame frame = new JFrame("Tree Tips");
Properties props = System.getProperties();
JTree tree = new JTree(props);
ToolTipManager.sharedInstance().registerComponent(tree);
TreeCellRenderer renderer = new ToolTipTreeCellRenderer(props);
tree.setCellRenderer(renderer);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
class ToolTipTreeCellRenderer implements TreeCellRenderer {
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
Dictionary tipTable;
public ToolTipTreeCellRenderer(Dictionary tipTable) {
this.tipTable = tipTable;
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus) {
renderer.getTreeCellRendererComponent(tree, value, selected, expanded,
leaf, row, hasFocus);
if (value != null) {
Object tipKey;
if (value instanceof DefaultMutableTreeNode) {
tipKey = ((DefaultMutableTreeNode) value).getUserObject();
} else {
tipKey = tree.convertValueToText(value, selected, expanded,
leaf, row, hasFocus);
}
Object tip = tipTable.get(tipKey);
if (tip != null) {
renderer.setToolTipText(tip.toString());
} else {
renderer.setToolTipText(null);
}
}
return renderer;
}
}
JTree drag and drop utilites
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.tree.TreePath;
/* This comes from "Denis" at http://forum.java.sun.ru/thread.jspa?forumID=57&threadID=296255 */
/*
* My program use 4 classes. The application displays two trees.
* You can drag (move by default or copy with ctrl pressed) a node from the left tree to the right one, from the right to the left and inside the same tree.
* The rules for moving are :
* - you can"t move the root
* - you can"t move the selected node to its subtree (in the same tree).
* - you can"t move the selected node to itself (in the same tree).
* - you can"t move the selected node to its parent (in the same tree).
* - you can move a node to anywhere you want according to the 4 previous rules.
* The rules for copying are :
* - you can copy a node to anywhere you want.
*
* In the implementation I used DnD version of Java 1.3 because in 1.4 the DnD is too restrictive :
* you can"t do what you want (displaying the image of the node while dragging, changing the cursor
* according to where you are dragging, etc...). In 1.4, the DnD is based on the 1.3 version but
* it is too encapsulated.
*/
public class JTreeUtil {
private static final Insets DEFAULT_INSETS = new Insets(20, 20, 20, 20);
private static final DataFlavor NODE_FLAVOR = new DataFlavor(
DataFlavor.javaJVMLocalObjectMimeType, "Node");
private static Object draggedNode;
private static BufferedImage image = null; // buff image
private static class TransferableNode implements Transferable {
private Object node;
private DataFlavor[] flavors = { NODE_FLAVOR };
public TransferableNode(Object nd) {
node = nd;
}
public synchronized Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException {
if(flavor == NODE_FLAVOR) {
return node;
} else {
throw new UnsupportedFlavorException(flavor);
}
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return Arrays.asList(flavors).contains(flavor);
}
}
/*
* This class is the most important. It manages all the DnD behavior. It is
* abstract because it contains two abstract methods:
* public abstract boolean canPerformAction(JTree target,
* Object draggedNode, int action, Point location);
* public abstract boolean executeDrop(DNDTree tree,
* Object draggedNode, Object newParentNode, int action);
* we have to override to give the required behavior of DnD in your tree.
*/
private static class TreeTransferHandler implements
DragGestureListener, DragSourceListener, DropTargetListener {
private JTree tree;
private JTreeDragController controller;
private DragSource dragSource; // dragsource
private Rectangle rect2D = new Rectangle();
private boolean drawImage;
protected TreeTransferHandler(JTree tree, JTreeDragController controller,
int action, boolean drawIcon) {
this.tree = tree;
this.controller = controller;
drawImage = drawIcon;
dragSource = new DragSource();
dragSource.createDefaultDragGestureRecognizer(tree, action, this);
}
/* Methods for DragSourceListener */
public void dragDropEnd(DragSourceDropEvent dsde) {
/*
if(dsde.getDropSuccess()
&& dsde.getDropAction() == DnDConstants.ACTION_MOVE
&& draggedNodeParent != null) {
((DefaultTreeModel) tree.getModel())
.nodeStructureChanged(draggedNodeParent);
}
*/
}
public final void dragEnter(DragSourceDragEvent dsde) {
int action = dsde.getDropAction();
if(action == DnDConstants.ACTION_COPY) {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultCopyDrop);
} else {
if(action == DnDConstants.ACTION_MOVE) {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultMoveDrop);
} else {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultMoveNoDrop);
}
}
}
public final void dragOver(DragSourceDragEvent dsde) {
int action = dsde.getDropAction();
if(action == DnDConstants.ACTION_COPY) {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultCopyDrop);
} else {
if(action == DnDConstants.ACTION_MOVE) {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultMoveDrop);
} else {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultMoveNoDrop);
}
}
}
public final void dropActionChanged(DragSourceDragEvent dsde) {
int action = dsde.getDropAction();
if(action == DnDConstants.ACTION_COPY) {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultCopyDrop);
} else {
if(action == DnDConstants.ACTION_MOVE) {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultMoveDrop);
} else {
dsde.getDragSourceContext().setCursor(
DragSource.DefaultMoveNoDrop);
}
}
}
public final void dragExit(DragSourceEvent dse) {
dse.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
}
/* Methods for DragGestureListener */
public final void dragGestureRecognized(DragGestureEvent dge) {
TreePath path = tree.getSelectionPath();
if(path != null) {
draggedNode = path.getLastPathComponent();
if(drawImage) {
Rectangle pathBounds = tree.getPathBounds(path); // getpathbounds
// of
// selectionpath
JComponent lbl = (JComponent) tree
.getCellRenderer()
.getTreeCellRendererComponent(
tree,
draggedNode,
false,
tree.isExpanded(path),
tree.getModel() .isLeaf(path.getLastPathComponent()),
0, false);// returning the label
lbl.setBounds(pathBounds);// setting bounds to lbl
image = new BufferedImage(lbl.getWidth(), lbl.getHeight(),
java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE);// buffered
// image
// reference
// passing
// the
// label"s
// ht
// and
// width
Graphics2D graphics = image.createGraphics();// creating
// the
// graphics
// for
// buffered
// image
graphics.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, 0.5f)); // Sets the
// Composite for
// the
// Graphics2D
// context
lbl.setOpaque(false);
lbl.paint(graphics); // painting the graphics to label
graphics.dispose();
}
dragSource.startDrag(dge, DragSource.DefaultMoveNoDrop, image,
new Point(0, 0), new TransferableNode(draggedNode),
this);
}
}
/* Methods for DropTargetListener */
public final void dragEnter(DropTargetDragEvent dtde) {
Point pt = dtde.getLocation();
int action = dtde.getDropAction();
if(drawImage) {
paintImage(pt);
}
if(controller.canPerformAction(tree, draggedNode, action, pt)) {
dtde.acceptDrag(action);
} else {
dtde.rejectDrag();
}
}
public final void dragExit(DropTargetEvent dte) {
if(drawImage) {
clearImage();
}
}
public final void dragOver(DropTargetDragEvent dtde) {
Point pt = dtde.getLocation();
int action = dtde.getDropAction();
autoscroll(tree, pt);
if(drawImage) {
paintImage(pt);
}
if(controller.canPerformAction(tree, draggedNode, action, pt)) {
dtde.acceptDrag(action);
} else {
dtde.rejectDrag();
}
}
public final void dropActionChanged(DropTargetDragEvent dtde) {
Point pt = dtde.getLocation();
int action = dtde.getDropAction();
if(drawImage) {
paintImage(pt);
}
if(controller.canPerformAction(tree, draggedNode, action, pt)) {
dtde.acceptDrag(action);
} else {
dtde.rejectDrag();
}
}
public final void drop(DropTargetDropEvent dtde) {
try {
if(drawImage) {
clearImage();
}
int action = dtde.getDropAction();
Transferable transferable = dtde.getTransferable();
Point pt = dtde.getLocation();
if(transferable
.isDataFlavorSupported(NODE_FLAVOR)
&& controller.canPerformAction(tree, draggedNode, action, pt)) {
TreePath pathTarget = tree.getPathForLocation(pt.x, pt.y);
Object node = transferable.getTransferData(NODE_FLAVOR);
Object newParentNode = pathTarget.getLastPathComponent();
if(controller.executeDrop(tree, node, newParentNode, action)) {
dtde.acceptDrop(action);
dtde.dropComplete(true);
return;
}
}
dtde.rejectDrop();
dtde.dropComplete(false);
} catch(Exception e) {
dtde.rejectDrop();
dtde.dropComplete(false);
}
}
private final void paintImage(Point pt) {
tree.paintImmediately(rect2D.getBounds());
rect2D.setRect((int) pt.getX(), (int) pt.getY(), image.getWidth(),
image.getHeight());
tree.getGraphics().drawImage(image, (int) pt.getX(),
(int) pt.getY(), tree);
}
private final void clearImage() {
tree.paintImmediately(rect2D.getBounds());
}
}
public static void configureDragAndDrop(JTree tree, JTreeDragController controller) {
tree.setAutoscrolls(true);
new TreeTransferHandler(tree, controller, DnDConstants.ACTION_COPY_OR_MOVE, true);
}
private static void autoscroll(JTree tree, Point cursorLocation) {
Insets insets = DEFAULT_INSETS;
Rectangle outer = tree.getVisibleRect();
Rectangle inner = new Rectangle(outer.x + insets.left, outer.y
+ insets.top, outer.width - (insets.left + insets.right),
outer.height - (insets.top + insets.bottom));
if(!inner.contains(cursorLocation)) {
Rectangle scrollRect = new Rectangle(cursorLocation.x
- insets.left, cursorLocation.y - insets.top,
insets.left + insets.right, insets.top + insets.bottom);
tree.scrollRectToVisible(scrollRect);
}
}
}
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
/* This comes from "Denis" at http://forum.java.sun.ru/thread.jspa?forumID=57&threadID=296255 */
/*
* My program use 4 classes. The application displays two trees.
* You can drag (move by default or copy with ctrl pressed) a node from the left tree to the right one, from the right to the left and inside the same tree.
* The rules for moving are :
* - you can"t move the root
* - you can"t move the selected node to its subtree (in the same tree).
* - you can"t move the selected node to itself (in the same tree).
* - you can"t move the selected node to its parent (in the same tree).
* - you can move a node to anywhere you want according to the 4 previous rules.
* The rules for copying are :
* - you can copy a node to anywhere you want.
*
* In the implementation I used DnD version of Java 1.3 because in 1.4 the DnD is too restrictive :
* you can"t do what you want (displaying the image of the node while dragging, changing the cursor
* according to where you are dragging, etc...). In 1.4, the DnD is based on the 1.3 version but
* it is too encapsulated.
*/
interface JTreeDragController {
public boolean canPerformAction(JTree target, Object draggedNode,
int action, Point location);
public boolean executeDrop(JTree tree, Object draggedNode,
Object newParentNode, int action);
}
JTree.DynamicUtilTreeNode.createChildren
import java.awt.BorderLayout;
import java.util.Hashtable;
import java.util.Properties;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
public class TreeUtilSample {
public static void main(String args[]) {
JFrame frame = new JFrame("DynamicUtilTreeNode Hashtable");
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
Hashtable hashtable = new Hashtable();
hashtable.put("One", args);
hashtable.put("Two", new String[] { "Mercury", "Venus", "Mars" });
Hashtable innerHashtable = new Hashtable();
Properties props = System.getProperties();
innerHashtable.put(props, props);
innerHashtable.put("Two", new String[] { "Mercury", "Venus", "Mars" });
hashtable.put("Three", innerHashtable);
JTree.DynamicUtilTreeNode.createChildren(root, hashtable);
JTree tree = new JTree(root);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
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);
}
}
Listening for Expansion and Collapse Events in a JTree Component
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
public class Main {
public static void main() {
JTree tree = new JTree();
tree.addTreeWillExpandListener(new MyTreeWillExpandListener());
tree.addTreeExpansionListener(new MyTreeExpansionListener());
JFrame f = new JFrame();
f.add(new JScrollPane(tree));
f.setSize(300, 300);
f.setVisible(true);
}
}
class MyTreeWillExpandListener implements TreeWillExpandListener {
public void treeWillExpand(TreeExpansionEvent evt) throws ExpandVetoException {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
boolean veto = false;
if (veto) {
throw new ExpandVetoException(evt);
}
}
public void treeWillCollapse(TreeExpansionEvent evt) throws ExpandVetoException {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
boolean veto = false;
if (veto) {
throw new ExpandVetoException(evt);
}
}
}
class MyTreeExpansionListener implements TreeExpansionListener {
public void treeExpanded(TreeExpansionEvent evt) {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
System.out.println("treeExpanded");
}
public void treeCollapsed(TreeExpansionEvent evt) {
JTree tree = (JTree) evt.getSource();
TreePath path = evt.getPath();
System.out.println("treeCollapsed");
}
}
Listening for Selection Events in a JTree Component
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) throws Exception {
JTree tree = new JTree();
tree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent evt) {
TreePath[] paths = evt.getPaths();
for (int i = 0; i < paths.length; i++) {
if (evt.isAddedPath(i)) {
System.out.println("This node has been selected");
} else {
System.out.println("This node has been deselected");
}
}
}
});
}
}
Preventing Expansion or Collapse of a Node in a JTree: override JTree.setExpandedState()
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) {
JTree tree = new JTree() {
protected void setExpandedState(TreePath path, boolean state) {
if (state) {
super.setExpandedState(path, state);
}
}
};
JFrame frame = new JFrame("Ignore all collapse requests");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Preventing the Expansion or Collapse of a Node in a JTree Component
import javax.swing.JTree;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) {
JTree tree = new JTree() {
protected void setExpandedState(TreePath path, boolean state) {
if (state) {
super.setExpandedState(path, state);
}
}
};
}
}
Removing a Node to a JTree Component
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
public class TreeNodeRemove{
public static void main(String[] argv) {
Vector<String> v = new Vector<String>();
v.add("a");
v.add("b");
v.add("c");
JTree tree = new JTree(v);
DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
int startRow = 0;
String prefix = "b";
TreePath path = tree.getNextMatch(prefix, startRow, Position.Bias.Forward);
MutableTreeNode node = (MutableTreeNode) path.getLastPathComponent();
model.removeNodeFromParent(node);
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);
}
}
Returns a TreePath containing the specified node.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
public TreePath getPath(TreeNode node) {
List<TreeNode> list = new ArrayList<TreeNode>();
while (node != null) {
list.add(node);
node = node.getParent();
}
Collections.reverse(list);
return new TreePath(list.toArray());
}
}
Search backward from last visible row looking for any visible node whose name starts with prefix.
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) throws Exception {
JTree tree = new JTree();
int startRow = tree.getRowCount() - 1;
String prefix = "b";
TreePath path = tree.getNextMatch(prefix, startRow, Position.Bias.Backward);
System.out.println(path);
}
}
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();
}
}
Set the Tree Line
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
public class TreeLineSample {
public static void main(String args[]) {
String title = "JTree Sample";
JFrame frame = new JFrame(title);
UIManager.put("Tree.line", Color.green);
JTree tree = new JTree();
tree.putClientProperty("JTree.lineStyle", "Horizontal");
tree.setSelectionModel(null);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
Setting the Row Height of a JTree
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeight {
public static void main(String[] argv) {
JTree tree = new JTree();
tree.setRowHeight(15);
JFrame frame = new JFrame("tree row height");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tree));
frame.setSize(380, 320);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Traverse all expanded nodes in tree
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
public static void main(String[] argv) throws Exception {
JTree tree = new JTree();
visitAllExpandedNodes(tree);
}
public static void visitAllExpandedNodes(JTree tree) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
visitAllExpandedNodes(tree, new TreePath(root));
}
public static void visitAllExpandedNodes(JTree tree, TreePath parent) {
if (!tree.isVisible(parent)) {
return;
}
TreeNode node = (TreeNode) parent.getLastPathComponent();
System.out.println(node);
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
visitAllExpandedNodes(tree, path);
}
}
}
}
Traverse Tree
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski
ISBN: 1-893115-78-X
Publisher: APress
*/
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.*;
import java.util.*;
public class TraverseTree {
public static void main(String args[]) {
JFrame frame = new JFrame("Traverse Tree");
Object footballNodes[] = { "Giants", "Jets", "Bills" };
Vector footballVector = new NamedVector("Football", footballNodes);
Object newYorkNodes[] = { "Mets", "Yankees", "Rangers", footballVector };
Vector newYorkVector = new NamedVector("New York", newYorkNodes);
Object bostonNodes[] = { "Red Sox", "Celtics", "Bruins" };
Vector bostonVector = new NamedVector("Boston", bostonNodes);
Object denverNodes[] = { "Rockies", "Avalanche", "Broncos" };
Vector denverVector = new NamedVector("Denver", denverNodes);
Object rootNodes[] = { newYorkVector, bostonVector, denverVector };
Vector rootVector = new NamedVector("Root", rootNodes);
JTree tree = new JTree(rootVector);
tree.setRootVisible(true);
TreeModel model = tree.getModel();
Object rootObject = model.getRoot();
if ((rootObject != null)
&& (rootObject instanceof DefaultMutableTreeNode)) {
DefaultMutableTreeNode root = (DefaultMutableTreeNode) rootObject;
// printDescendents(root);
Enumeration breadth = root.breadthFirstEnumeration();
Enumeration depth = root.depthFirstEnumeration();
Enumeration preOrder = root.preorderEnumeration();
printEnumeration(breadth, "Breadth");
// printEnumeration(depth, "Depth");
// printEnumeration(preOrder, "Pre");
}
TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
JTree treeSource = (JTree) treeSelectionEvent.getSource();
TreePath path = treeSource.getSelectionPath();
System.out.println(path);
System.out.println(path.getPath());
System.out.println(path.getParentPath());
System.out.println(((DefaultMutableTreeNode) path
.getLastPathComponent()).getUserObject());
System.out.println(path.getPathCount());
}
};
tree.addTreeSelectionListener(treeSelectionListener);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 400);
frame.setVisible(true);
}
private static void printEnumeration(Enumeration e, String label) {
System.out.println("-----" + label + "-----");
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
}
public static void printDescendents(TreeNode root) {
System.out.println(root);
Enumeration children = root.children();
if (children != null) {
while (children.hasMoreElements()) {
printDescendents((TreeNode) children.nextElement());
}
}
}
}
class NamedVector extends Vector {
String name;
public NamedVector(String name) {
this.name = name;
}
public NamedVector(String name, Object elements[]) {
this.name = name;
for (int i = 0, n = elements.length; i < n; i++) {
add(elements[i]);
}
}
public String toString() {
return "[" + name + "]";
}
}
Tree based on Array structure
import java.awt.BorderLayout;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeArraySample {
public static void main(String args[]) {
JFrame frame = new JFrame("JTreeSample");
Vector oneVector = new NamedVector("One", args);
Vector twoVector = new NamedVector("Two", new String[] { "Mercury",
"Venus", "Mars" });
Vector threeVector = new NamedVector("Three");
threeVector.add(System.getProperties());
threeVector.add(twoVector);
Object rootNodes[] = { oneVector, twoVector, threeVector };
Vector rootVector = new NamedVector("Root", rootNodes);
JTree tree = new JTree(rootVector);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
// frame.getContentPane().add(tree, BorderLayout.CENTER);
frame.setSize(300, 300);
frame.setVisible(true);
}
}
class NamedVector extends Vector {
String name;
public NamedVector(String name) {
this.name = name;
}
public NamedVector(String name, Object elements[]) {
this.name = name;
for (int i = 0, n = elements.length; i < n; i++) {
add(elements[i]);
}
}
public String toString() {
return "[" + name + "]";
}
}
Tree: Drag and Drop
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Iterator;
import java.util.List;
import javax.swing.JFrame;
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.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class TreeTester {
public static void main(String args[]) {
JFrame f = new JFrame("Tree Dragging Tester");
DndTree tree1 = new DndTree();
JScrollPane leftPane = new JScrollPane(tree1);
DndTree tree2 = new DndTree();
JScrollPane rightPane = new JScrollPane(tree2);
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
leftPane, rightPane);
f.getContentPane().add(splitPane, BorderLayout.CENTER);
f.setSize(300, 200);
f.setVisible(true);
}
}
class DndTree extends JTree implements Autoscroll {
private Insets insets;
private int top = 0, bottom = 0, topRow = 0, bottomRow = 0;
public DndTree() {
DragSource dragSource = DragSource.getDefaultDragSource();
dragSource
.createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE,
new TreeDragGestureListener());
DropTarget dropTarget = new DropTarget(this,
new TreeDropTargetListener());
}
public DndTree(TreeModel model) {
super(model);
DragSource dragSource = DragSource.getDefaultDragSource();
dragSource
.createDefaultDragGestureRecognizer(this,
DnDConstants.ACTION_COPY_OR_MOVE,
new TreeDragGestureListener());
DropTarget dropTarget = new DropTarget(this,
new TreeDropTargetListener());
}
public Insets getAutoscrollInsets() {
return insets;
}
public void autoscroll(Point p) {
// Only support up/down scrolling
top = Math.abs(getLocation().y) + 10;
bottom = top + getParent().getHeight() - 20;
int next;
if (p.y < top) {
next = topRow--;
bottomRow++;
scrollRowToVisible(next);
} else if (p.y > bottom) {
next = bottomRow++;
topRow--;
scrollRowToVisible(next);
}
}
private static class TreeDragGestureListener implements DragGestureListener {
public void dragGestureRecognized(DragGestureEvent dragGestureEvent) {
// Can only drag leafs
JTree tree = (JTree) dragGestureEvent.getComponent();
TreePath path = tree.getSelectionPath();
if (path == null) {
// Nothing selected, nothing to drag
System.out.println("Nothing selected - beep");
tree.getToolkit().beep();
} else {
DefaultMutableTreeNode selection = (DefaultMutableTreeNode) path
.getLastPathComponent();
if (selection.isLeaf()) {
TransferableTreeNode node = new TransferableTreeNode(
selection);
dragGestureEvent.startDrag(DragSource.DefaultCopyDrop,
node, new MyDragSourceListener());
} else {
System.out.println("Not a leaf - beep");
tree.getToolkit().beep();
}
}
}
}
private class TreeDropTargetListener implements DropTargetListener {
public void dragEnter(DropTargetDragEvent dropTargetDragEvent) {
// Setup positioning info for auto-scrolling
top = Math.abs(getLocation().y);
bottom = top + getParent().getHeight();
topRow = getClosestRowForLocation(0, top);
bottomRow = getClosestRowForLocation(0, bottom);
insets = new Insets(top + 10, 0, bottom - 10, getWidth());
}
public void dragExit(DropTargetEvent dropTargetEvent) {
}
public void dragOver(DropTargetDragEvent dropTargetDragEvent) {
}
public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) {
}
public synchronized void drop(DropTargetDropEvent dropTargetDropEvent) {
// Only support dropping over nodes that aren"t leafs
Point location = dropTargetDropEvent.getLocation();
TreePath path = getPathForLocation(location.x, location.y);
Object node = path.getLastPathComponent();
if ((node != null) && (node instanceof TreeNode)
&& (!((TreeNode) node).isLeaf())) {
try {
Transferable tr = dropTargetDropEvent.getTransferable();
if (tr
.isDataFlavorSupported(TransferableTreeNode.DEFAULT_MUTABLE_TREENODE_FLAVOR)) {
dropTargetDropEvent
.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
Object userObject = tr
.getTransferData(TransferableTreeNode.DEFAULT_MUTABLE_TREENODE_FLAVOR);
addElement(path, userObject);
dropTargetDropEvent.dropComplete(true);
} else if (tr
.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dropTargetDropEvent
.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
String string = (String) tr
.getTransferData(DataFlavor.stringFlavor);
addElement(path, string);
dropTargetDropEvent.dropComplete(true);
} else if (tr
.isDataFlavorSupported(DataFlavor.plainTextFlavor)) {
dropTargetDropEvent
.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
Object stream = tr
.getTransferData(DataFlavor.plainTextFlavor);
if (stream instanceof InputStream) {
InputStreamReader isr = new InputStreamReader(
(InputStream) stream);
BufferedReader reader = new BufferedReader(isr);
String line;
while ((line = reader.readLine()) != null) {
addElement(path, line);
}
dropTargetDropEvent.dropComplete(true);
} else if (stream instanceof Reader) {
BufferedReader reader = new BufferedReader(
(Reader) stream);
String line;
while ((line = reader.readLine()) != null) {
addElement(path, line);
}
dropTargetDropEvent.dropComplete(true);
} else {
System.err.println("Unknown type: "
+ stream.getClass());
dropTargetDropEvent.rejectDrop();
}
} else if (tr
.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dropTargetDropEvent
.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
List fileList = (List) tr
.getTransferData(DataFlavor.javaFileListFlavor);
Iterator iterator = fileList.iterator();
while (iterator.hasNext()) {
File file = (File) iterator.next();
addElement(path, file.toURL());
}
dropTargetDropEvent.dropComplete(true);
} else {
System.err.println("Rejected");
dropTargetDropEvent.rejectDrop();
}
} catch (IOException io) {
io.printStackTrace();
dropTargetDropEvent.rejectDrop();
} catch (UnsupportedFlavorException ufe) {
ufe.printStackTrace();
dropTargetDropEvent.rejectDrop();
}
} else {
System.out.println("Can"t drop on a leaf");
dropTargetDropEvent.rejectDrop();
}
}
private void addElement(TreePath path, Object element) {
DefaultMutableTreeNode parent = (DefaultMutableTreeNode) path
.getLastPathComponent();
DefaultMutableTreeNode node = new DefaultMutableTreeNode(element);
System.out.println("Added: " + node + " to " + parent);
DefaultTreeModel model = (DefaultTreeModel) (DndTree.this
.getModel());
model.insertNodeInto(node, parent, parent.getChildCount());
}
}
private static class MyDragSourceListener implements DragSourceListener {
public void dragDropEnd(DragSourceDropEvent dragSourceDropEvent) {
if (dragSourceDropEvent.getDropSuccess()) {
int dropAction = dragSourceDropEvent.getDropAction();
if (dropAction == DnDConstants.ACTION_MOVE) {
System.out.println("MOVE: remove node");
}
}
}
public void dragEnter(DragSourceDragEvent dragSourceDragEvent) {
DragSourceContext context = dragSourceDragEvent
.getDragSourceContext();
int dropAction = dragSourceDragEvent.getDropAction();
if ((dropAction & DnDConstants.ACTION_COPY) != 0) {
context.setCursor(DragSource.DefaultCopyDrop);
} else if ((dropAction & DnDConstants.ACTION_MOVE) != 0) {
context.setCursor(DragSource.DefaultMoveDrop);
} else {
context.setCursor(DragSource.DefaultCopyNoDrop);
}
}
public void dragExit(DragSourceEvent dragSourceEvent) {
}
public void dragOver(DragSourceDragEvent dragSourceDragEvent) {
}
public void dropActionChanged(DragSourceDragEvent dragSourceDragEvent) {
}
}
}
class TransferableTreeNode extends DefaultMutableTreeNode implements
Transferable {
final static int TREE = 0;
final static int STRING = 1;
final static int PLAIN_TEXT = 1;
final public static DataFlavor DEFAULT_MUTABLE_TREENODE_FLAVOR = new DataFlavor(
DefaultMutableTreeNode.class, "Default Mutable Tree Node");
static DataFlavor flavors[] = { DEFAULT_MUTABLE_TREENODE_FLAVOR,
DataFlavor.stringFlavor, DataFlavor.plainTextFlavor };
private DefaultMutableTreeNode data;
public TransferableTreeNode(DefaultMutableTreeNode data) {
this.data = data;
}
public DataFlavor[] getTransferDataFlavors() {
return flavors;
}
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
Object returnObject;
if (flavor.equals(flavors[TREE])) {
Object userObject = data.getUserObject();
if (userObject == null) {
returnObject = data;
} else {
returnObject = userObject;
}
} else if (flavor.equals(flavors[STRING])) {
Object userObject = data.getUserObject();
if (userObject == null) {
returnObject = data.toString();
} else {
returnObject = userObject.toString();
}
} else if (flavor.equals(flavors[PLAIN_TEXT])) {
Object userObject = data.getUserObject();
String string;
if (userObject == null) {
string = data.toString();
} else {
string = userObject.toString();
}
returnObject = new ByteArrayInputStream(string.getBytes("Unicode"));
} else {
throw new UnsupportedFlavorException(flavor);
}
return returnObject;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
boolean returnValue = false;
for (int i = 0, n = flavors.length; i < n; i++) {
if (flavor.equals(flavors[i])) {
returnValue = true;
break;
}
}
return returnValue;
}
}
Tree Expand Event Demo
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 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:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution 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, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
/*
* TreeExpandEventDemo.java is a 1.4 example that requires no other files.
*/
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
public class TreeExpandEventDemo extends JPanel {
DemoArea demoArea;
JTextArea textArea;
final static String newline = "\n";
public TreeExpandEventDemo() {
super(new GridBagLayout());
GridBagLayout gridbag = (GridBagLayout) getLayout();
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1.0;
c.weighty = 1.0;
c.insets = new Insets(1, 1, 1, 1);
demoArea = new DemoArea();
gridbag.setConstraints(demoArea, c);
add(demoArea);
c.insets = new Insets(0, 0, 0, 0);
textArea = new JTextArea();
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane
.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(200, 75));
gridbag.setConstraints(scrollPane, c);
add(scrollPane);
setPreferredSize(new Dimension(450, 450));
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
void saySomething(String eventDescription, TreeExpansionEvent e) {
textArea.append(eventDescription + "; " + "path = " + e.getPath()
+ newline);
}
class DemoArea extends JScrollPane implements TreeExpansionListener {
Dimension minSize = new Dimension(100, 100);
JTree tree;
public DemoArea() {
TreeNode rootNode = createNodes();
tree = new JTree(rootNode);
tree.addTreeExpansionListener(this);
setViewportView(tree);
}
private TreeNode createNodes() {
DefaultMutableTreeNode root;
DefaultMutableTreeNode grandparent;
DefaultMutableTreeNode parent;
DefaultMutableTreeNode child;
root = new DefaultMutableTreeNode("San Francisco");
grandparent = new DefaultMutableTreeNode("Potrero Hill");
root.add(grandparent);
//
parent = new DefaultMutableTreeNode("Restaurants");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Thai Barbeque");
parent.add(child);
child = new DefaultMutableTreeNode("Goat Hill Pizza");
parent.add(child);
//
parent = new DefaultMutableTreeNode("Grocery Stores");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Good Life Grocery");
parent.add(child);
child = new DefaultMutableTreeNode("Safeway");
parent.add(child);
grandparent = new DefaultMutableTreeNode("Noe Valley");
root.add(grandparent);
//
parent = new DefaultMutableTreeNode("Restaurants");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Hamano Sushi");
parent.add(child);
child = new DefaultMutableTreeNode("Hahn"s Hibachi");
parent.add(child);
//
parent = new DefaultMutableTreeNode("Grocery Stores");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Real Foods");
parent.add(child);
child = new DefaultMutableTreeNode("Bell Market");
parent.add(child);
return root;
}
public Dimension getMinimumSize() {
return minSize;
}
public Dimension getPreferredSize() {
return minSize;
}
// Required by TreeExpansionListener interface.
public void treeExpanded(TreeExpansionEvent e) {
saySomething("Tree-expanded event detected", e);
}
// Required by TreeExpansionListener interface.
public void treeCollapsed(TreeExpansionEvent e) {
saySomething("Tree-collapsed event detected", e);
}
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("TreeExpandEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new TreeExpandEventDemo();
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();
}
});
}
}
Tree Expand Event Demo 2
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 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:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution 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, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
/*
* TreeExpandEventDemo2.java is a 1.4 example that requires no other files.
*/
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreeNode;
public class TreeExpandEventDemo2 extends JPanel {
DemoArea demoArea;
JTextArea textArea;
final static String newline = "\n";
public TreeExpandEventDemo2() {
super(new GridBagLayout());
GridBagLayout gridbag = (GridBagLayout) getLayout();
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1.0;
c.weighty = 1.0;
c.insets = new Insets(1, 1, 1, 1);
demoArea = new DemoArea();
gridbag.setConstraints(demoArea, c);
add(demoArea);
c.insets = new Insets(0, 0, 0, 0);
textArea = new JTextArea();
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane
.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(200, 75));
gridbag.setConstraints(scrollPane, c);
add(scrollPane);
setPreferredSize(new Dimension(450, 450));
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
void saySomething(String eventDescription, TreeExpansionEvent e) {
textArea.append(eventDescription + "; " + "path = " + e.getPath()
+ newline);
}
class DemoArea extends JScrollPane implements TreeExpansionListener,
TreeWillExpandListener {
Dimension minSize = new Dimension(100, 100);
JTree tree;
Object[] willExpandOptions = { "Cancel Expansion", "Expand" };
String willExpandText = "A branch node is about to be expanded.\n"
+ "Click \"Cancel Expansion\" to prevent it.";
String willExpandTitle = "Tree Will Expand";
public DemoArea() {
TreeNode rootNode = createNodes();
tree = new JTree(rootNode);
tree.addTreeExpansionListener(this);
tree.addTreeWillExpandListener(this);
setViewportView(tree);
}
private TreeNode createNodes() {
DefaultMutableTreeNode root;
DefaultMutableTreeNode grandparent;
DefaultMutableTreeNode parent;
DefaultMutableTreeNode child;
root = new DefaultMutableTreeNode("San Francisco");
grandparent = new DefaultMutableTreeNode("Potrero Hill");
root.add(grandparent);
//
parent = new DefaultMutableTreeNode("Restaurants");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Thai Barbeque");
parent.add(child);
child = new DefaultMutableTreeNode("Goat Hill Pizza");
parent.add(child);
//
parent = new DefaultMutableTreeNode("Grocery Stores");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Good Life Grocery");
parent.add(child);
child = new DefaultMutableTreeNode("Safeway");
parent.add(child);
grandparent = new DefaultMutableTreeNode("Noe Valley");
root.add(grandparent);
//
parent = new DefaultMutableTreeNode("Restaurants");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Hamano Sushi");
parent.add(child);
child = new DefaultMutableTreeNode("Hahn"s Hibachi");
parent.add(child);
//
parent = new DefaultMutableTreeNode("Grocery Stores");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Real Foods");
parent.add(child);
child = new DefaultMutableTreeNode("Bell Market");
parent.add(child);
return root;
}
public Dimension getMinimumSize() {
return minSize;
}
public Dimension getPreferredSize() {
return minSize;
}
//Required by TreeWillExpandListener interface.
public void treeWillExpand(TreeExpansionEvent e)
throws ExpandVetoException {
saySomething("Tree-will-expand event detected", e);
int n = JOptionPane.showOptionDialog(this, willExpandText,
willExpandTitle, JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, willExpandOptions,
willExpandOptions[1]);
if (n == 0) {
//User said cancel expansion.
saySomething("Tree expansion cancelled", e);
throw new ExpandVetoException(e);
}
}
//Required by TreeWillExpandListener interface.
public void treeWillCollapse(TreeExpansionEvent e) {
saySomething("Tree-will-collapse event detected", e);
}
// Required by TreeExpansionListener interface.
public void treeExpanded(TreeExpansionEvent e) {
saySomething("Tree-expanded event detected", e);
}
// Required by TreeExpansionListener interface.
public void treeCollapsed(TreeExpansionEvent e) {
saySomething("Tree-collapsed event detected", e);
}
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("TreeExpandEventDemo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new TreeExpandEventDemo2();
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();
}
});
}
}
TreeExpansionListener and TreeExpansionEvent
/*
* 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.
*/
/*
* TreeExpandEventDemo.java requires no other files.
*/
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
public class TreeExpandEventDemo extends JPanel {
DemoArea demoArea;
JTextArea textArea;
final static String newline = "\n";
public TreeExpandEventDemo() {
super(new GridBagLayout());
GridBagLayout gridbag = (GridBagLayout) getLayout();
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1.0;
c.weighty = 1.0;
c.insets = new Insets(1, 1, 1, 1);
demoArea = new DemoArea();
gridbag.setConstraints(demoArea, c);
add(demoArea);
c.insets = new Insets(0, 0, 0, 0);
textArea = new JTextArea();
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane
.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(200, 75));
gridbag.setConstraints(scrollPane, c);
add(scrollPane);
setPreferredSize(new Dimension(450, 450));
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
void saySomething(String eventDescription, TreeExpansionEvent e) {
textArea
.append(eventDescription + "; " + "path = " + e.getPath() + newline);
}
class DemoArea extends JScrollPane implements TreeExpansionListener {
Dimension minSize = new Dimension(100, 100);
JTree tree;
public DemoArea() {
TreeNode rootNode = createNodes();
tree = new JTree(rootNode);
tree.addTreeExpansionListener(this);
setViewportView(tree);
}
private TreeNode createNodes() {
DefaultMutableTreeNode root;
DefaultMutableTreeNode grandparent;
DefaultMutableTreeNode parent;
DefaultMutableTreeNode child;
root = new DefaultMutableTreeNode("San Francisco");
grandparent = new DefaultMutableTreeNode("Potrero Hill");
root.add(grandparent);
//
parent = new DefaultMutableTreeNode("Restaurants");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Thai Barbeque");
parent.add(child);
child = new DefaultMutableTreeNode("Goat Hill Pizza");
parent.add(child);
//
parent = new DefaultMutableTreeNode("Grocery Stores");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Good Life Grocery");
parent.add(child);
child = new DefaultMutableTreeNode("Safeway");
parent.add(child);
grandparent = new DefaultMutableTreeNode("Noe Valley");
root.add(grandparent);
//
parent = new DefaultMutableTreeNode("Restaurants");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Hamano Sushi");
parent.add(child);
child = new DefaultMutableTreeNode("Hahn"s Hibachi");
parent.add(child);
//
parent = new DefaultMutableTreeNode("Grocery Stores");
grandparent.add(parent);
child = new DefaultMutableTreeNode("Real Foods");
parent.add(child);
child = new DefaultMutableTreeNode("Bell Market");
parent.add(child);
return root;
}
public Dimension getMinimumSize() {
return minSize;
}
public Dimension getPreferredSize() {
return minSize;
}
// Required by TreeExpansionListener interface.
public void treeExpanded(TreeExpansionEvent e) {
saySomething("Tree-expanded event detected", e);
}
// Required by TreeExpansionListener interface.
public void treeCollapsed(TreeExpansionEvent e) {
saySomething("Tree-collapsed event detected", e);
}
}
/**
* 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("TreeExpandEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create and set up the content pane.
JComponent newContentPane = new TreeExpandEventDemo();
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();
}
});
}
}
Tree Icon Demo
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
* Copyright (c) 2006 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:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution 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, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
/**
* 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 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.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.ImageIcon;
import java.net.URL;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;
public class TreeIconDemo extends JPanel
implements TreeSelectionListener {
private JEditorPane htmlPane;
private JTree tree;
private URL helpURL;
private static boolean DEBUG = false;
public TreeIconDemo() {
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);
//Set the icon for leaf nodes.
ImageIcon leafIcon = createImageIcon("images/middle.gif");
if (leafIcon != null) {
DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
renderer.setLeafIcon(leafIcon);
tree.setCellRenderer(renderer);
} else {
System.err.println("Leaf 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 = TreeIconDemo.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 = TreeIconDemo.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 = TreeIconDemo.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() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("TreeIconDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TreeIconDemo newContentPane = new TreeIconDemo();
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();
}
});
}
}
Tree Lines
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeLines {
public static void main(String args[]) {
JFrame frame = new JFrame("Tree Lines");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = frame.getContentPane();
Box box = Box.createHorizontalBox();
JTree tree1 = new JTree();
tree1.putClientProperty("JTree.lineStyle", "Angled");
JScrollPane scrollPane1 = new JScrollPane(tree1);
tree1.setAutoscrolls(true);
JTree tree2 = new JTree();
JScrollPane scrollPane2 = new JScrollPane(tree2);
box.add(scrollPane1, BorderLayout.WEST);
box.add(scrollPane2, BorderLayout.EAST);
frame.getContentPane().add(box, BorderLayout.CENTER);
frame.setSize(300, 240);
frame.setVisible(true);
}
}
Tree open Icon
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
public class LazySample {
public static void main(String args[]) {
JFrame frame = new JFrame("Lazy Example");
Object iconObject = LookAndFeel.makeIcon(LazySample.class, "World.gif");
UIManager.put("Tree.leafIcon", iconObject);
Integer fifteen = new Integer(15);
Object lazyArgs[] = new Object[] { Color.green, Boolean.TRUE, fifteen,
fifteen };
Object lazyDiamond = new UIDefaults.ProxyLazyValue("DiamondIcon",
lazyArgs);
UIManager.put("Tree.openIcon", lazyDiamond);
JTree tree = new JTree();
JScrollPane scrollPane = new JScrollPane(tree);
Container contentPane = frame.getContentPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
Tree Selection Row
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
public class TreeSelectionRow {
public static void main(String args[]) {
String title = "JTree Sample";
JFrame frame = new JFrame(title);
JTree tree = new JTree();
TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
JTree treeSource = (JTree) treeSelectionEvent.getSource();
System.out.println("Min: " + treeSource.getMinSelectionRow());
System.out.println("Max: " + treeSource.getMaxSelectionRow());
System.out.println("Lead: " + treeSource.getLeadSelectionRow());
System.out.println("Row: " + treeSource.getSelectionRows()[0]);
}
};
tree.addTreeSelectionListener(treeSelectionListener);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
Tree will Expand event and listener
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
public class TreeExpandSample {
public static void main(String args[]) {
String title = ("JTree Expand Sample");
JFrame frame = new JFrame(title);
JTree tree = new JTree();
TreeWillExpandListener treeWillExpandListener = new TreeWillExpandListener() {
public void treeWillCollapse(TreeExpansionEvent treeExpansionEvent)
throws ExpandVetoException {
TreePath path = treeExpansionEvent.getPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
.getLastPathComponent();
String data = node.getUserObject().toString();
if (data.equals("colors")) {
throw new ExpandVetoException(treeExpansionEvent);
}
}
public void treeWillExpand(TreeExpansionEvent treeExpansionEvent)
throws ExpandVetoException {
TreePath path = treeExpansionEvent.getPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
.getLastPathComponent();
String data = node.getUserObject().toString();
if (data.equals("sports")) {
throw new ExpandVetoException(treeExpansionEvent);
}
}
};
tree.addTreeWillExpandListener(treeWillExpandListener);
JScrollPane scrollPane = new JScrollPane(tree);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
Use UIManager to change the default icon for JTree
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
public class Main {
public static void main(String[] argv) throws Exception {
Icon leafIcon = new ImageIcon("leaf.gif");
Icon openIcon = new ImageIcon("open.gif");
Icon closedIcon = new ImageIcon("closed.gif");
UIManager.put("Tree.leafIcon", leafIcon);
UIManager.put("Tree.openIcon", openIcon);
UIManager.put("Tree.closedIcon", closedIcon);
JTree tree = new JTree();
JFrame f = new JFrame();
f.add(new JScrollPane(tree));
f.setSize(300, 300);
f.setVisible(true);
}
}
Visiting All the Nodes in a JTree Component
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
public class Main {
public static void main(String[] argv) throws Exception {
JTree tree = new JTree();
visitAllNodes(tree);
}
public static void visitAllNodes(JTree tree) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
visitAllNodes(root);
}
public static void visitAllNodes(TreeNode node) {
System.out.println(node);
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
visitAllNodes(n);
}
}
}
}