Java/Swing JFC/Tree
Содержание
- 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
<source lang="java">
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(); }
}
</source>
Adding a Node to a JTree Component
<source lang="java">
import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; public class Main {
public static void main(String[] argv) throws Exception { JTree tree = new JTree(); DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); TreePath path = tree.getSelectionPath(); MutableTreeNode node = (MutableTreeNode) path.getLastPathComponent(); MutableTreeNode newNode = new DefaultMutableTreeNode("green"); model.insertNodeInto(newNode, node, node.getChildCount()); }
}
</source>
Adding editable nodes to JTree
<source lang="java">
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.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(); }
}
</source>
Add Tree to JScrollPane
<source lang="java">
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); }
}
</source>
Allow multiple selections of visible nodes
<source lang="java">
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); }
}
</source>
Allow only a single node to be selected (default)
<source lang="java">
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); }
}
</source>
Allow selection to span one vertical contiguous set of visible nodes
<source lang="java">
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); }
}
</source>
All rows will be given 15 pixels of height
<source lang="java">
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); }
}
</source>
Ancestor Tree with Icons
<source lang="java">
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(); }
}
</source>
A sample component for dragging and dropping a collection of files into a tree.
<source lang="java">
/* 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; } }
}
</source>
A simple test to see how we can build a tree and populate it
<source lang="java">
/* 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); }
}
</source>
A tree with component
<source lang="java">
/* 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 + "]"; }
}
</source>
Build a tree and customize its icons
<source lang="java">
/* 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); }
}
</source>
Build a tree and populate it from hashtables
<source lang="java">
/* 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); }
}
</source>
Build a tree based on DefaultMutableTreeNode
<source lang="java">
// : 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); }
} ///:~
</source>
Changing and Removing the Default Icons in a JTree Component
<source lang="java">
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); }
}
</source>
Converting All Nodes in a JTree Component to a TreePath Array
<source lang="java">
import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class Main {
public TreePath[] getPaths(JTree tree, boolean expanded) { TreeNode root = (TreeNode) tree.getModel().getRoot(); List<TreePath> list = new ArrayList<TreePath>(); getPaths(tree, new TreePath(root), expanded, list); return (TreePath[]) list.toArray(new TreePath[list.size()]); } public void getPaths(JTree tree, TreePath parent, boolean expanded, List<TreePath> list) { if (expanded && !tree.isVisible(parent)) { return; } list.add(parent); TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration e = node.children(); e.hasMoreElements();) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); getPaths(tree, path, expanded, list); } } }
}
</source>
Creating a JTree Component
<source lang="java">
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); }
}
</source>
DefaultMutableTreeNode and user object
<source lang="java">
/* 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; } }
}
</source>
DefaultMutableTreeNode Node Tree Sample
<source lang="java">
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); }
}
</source>
Deleting nodes from JTree
<source lang="java">
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.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(); }
}
</source>
Display a file system in a JTree view
<source lang="java">
/*
* 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); }
}
</source>
Displaying Hierarchical Data within a JTree
<source lang="java">
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(); }
}
</source>
Display user object in a tree
<source lang="java">
/* 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(); } }); }
}
</source>
DnD (drag and drop)JTree code
<source lang="java">
/* 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); } }
}
</source>
Drag and drop of a group of files into a tree
<source lang="java">
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; }
}
</source>
Enabling and Disabling Multiple Selections in a JTree Component
<source lang="java">
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); }
}
</source>
Expand All for a tree path
<source lang="java">
/*
* 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); } }
}
</source>
Expanding or Collapsing All Nodes in a JTree Component
<source lang="java">
import java.util.Enumeration; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class Main {
public void expandAll(JTree tree) { TreeNode root = (TreeNode) tree.getModel().getRoot(); expandAll(tree, new TreePath(root)); } private void expandAll(JTree tree, TreePath parent) { TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration e = node.children(); e.hasMoreElements();) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); expandAll(tree, path); } } tree.expandPath(parent); // tree.collapsePath(parent); }
}
</source>
Expansion and Collapse Events in a JTree are fired before a node is expanded or collapsed can be vetoed, thereby preventing the operation.
<source lang="java">
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"); }
}
</source>
File folder Tree with icons
<source lang="java">
/* 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; } }
}
</source>
File System Tree
<source lang="java">
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(); } }
}
</source>
File Tree with Popup Menu
<source lang="java">
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; } }
}
</source>
File Tree with Tooltips
<source lang="java">
/* 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; } }
}
</source>
Finding a Node in a JTree Component
<source lang="java">
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); }
}
</source>
Find the path regardless of visibility that matches the specified sequence of names
<source lang="java">
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; }
}
</source>
Flush the internal cache of Row height
<source lang="java">
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); }
}
</source>
Genealogy Tree
<source lang="java">
/* 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); }
}
</source>
Get path for all expanded or not expanded tree pathes
<source lang="java">
import java.util.Enumeration; import java.util.List; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class Main {
public void getPaths(JTree tree, TreePath parent, boolean expanded, List<TreePath> list) { if (expanded && !tree.isVisible(parent)) { return; } list.add(parent); TreeNode node = (TreeNode) parent.getLastPathComponent(); if (node.getChildCount() >= 0) { for (Enumeration e = node.children(); e.hasMoreElements();) { TreeNode n = (TreeNode) e.nextElement(); TreePath path = parent.pathByAddingChild(n); getPaths(tree, path, expanded, list); } } }
}
</source>
Getting the Selected Nodes in a JTree Component
<source lang="java">
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(); }
}
</source>
Get tree path from TreeNode
<source lang="java">
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()); }
}
</source>
Have a popup attached to a JTree
<source lang="java">
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); } }
}
</source>
Have the row height for each row computed individually
<source lang="java">
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); }
}
</source>
implements TreeSelectionListener to create your own listener
<source lang="java">
/* 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; }
}
</source>
Installs custom icons
<source lang="java">
/* 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); }
}
</source>
Install ToolTips for Tree (JTree)
<source lang="java">
/* 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; }
}
</source>
JTree drag and drop utilites
<source lang="java">
/* 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);
}
</source>
JTree.DynamicUtilTreeNode.createChildren
<source lang="java">
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); }
}
</source>
JTree root cannot be removed with removeNodeFromParent(), use DefaultTreeModel.setRoot() to remove the root
<source lang="java">
import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultTreeModel; public class TreeRootRemove {
public static void main(String[] argv) { JTree tree = new JTree(); DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); model.setRoot(null); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(tree)); frame.setSize(380, 320); frame.setLocationRelativeTo(null); frame.setVisible(true); }
}
</source>
Listening for Expansion and Collapse Events in a JTree Component
<source lang="java">
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"); }
}
</source>
Listening for Selection Events in a JTree Component
<source lang="java">
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"); } } } }); }
}
</source>
Preventing Expansion or Collapse of a Node in a JTree: override JTree.setExpandedState()
<source lang="java">
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); }
}
</source>
Preventing the Expansion or Collapse of a Node in a JTree Component
<source lang="java">
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); } } }; }
}
</source>
Removing a Node to a JTree Component
<source lang="java">
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); }
}
</source>
Returns a TreePath containing the specified node.
<source lang="java">
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()); }
}
</source>
Search backward from last visible row looking for any visible node whose name starts with prefix.
<source lang="java">
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); }
}
</source>
Searching node in a JTree
<source lang="java">
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Enumeration; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class EditableTree extends JFrame {
private DefaultMutableTreeNode m_rootNode = new DefaultMutableTreeNode("AA"); private DefaultTreeModel m_model = new DefaultTreeModel(m_rootNode); private JTree m_tree = new JTree(m_model); private JButton m_addButton = new JButton("Add Node"); private JButton m_delButton = new JButton("Delete Node"); private JButton m_searchButton = new JButton("Search Node"); private JButton m_searchAndDeleteButton = new JButton("Search and Delete Node"); private JTextField m_searchText; public EditableTree() { DefaultMutableTreeNode forums = new DefaultMutableTreeNode("A"); forums.add(new DefaultMutableTreeNode("B")); DefaultMutableTreeNode articles = new DefaultMutableTreeNode("E"); articles.add(new DefaultMutableTreeNode("F")); DefaultMutableTreeNode examples = new DefaultMutableTreeNode("G"); examples.add(new DefaultMutableTreeNode("H")); m_rootNode.add(forums); m_rootNode.add(articles); m_rootNode.add(examples); m_tree.setEditable(true); m_tree.setSelectionRow(0); JScrollPane scrollPane = new JScrollPane(m_tree); getContentPane().add(scrollPane, BorderLayout.CENTER); JPanel panel = new JPanel(); m_addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree .getLastSelectedPathComponent(); if (selNode == null) { return; } DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New Node"); m_model.insertNodeInto(newNode, selNode, selNode.getChildCount()); TreeNode[] nodes = m_model.getPathToRoot(newNode); TreePath path = new TreePath(nodes); m_tree.scrollPathToVisible(path); m_tree.setSelectionPath(path); m_tree.startEditingAtPath(path); } }); panel.add(m_addButton); m_delButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree .getLastSelectedPathComponent(); removeNode(selNode); } }); panel.add(m_delButton); JPanel searchPanel = new JPanel(); searchPanel.setBorder(BorderFactory.createEtchedBorder()); m_searchText = new JTextField(10); searchPanel.add(m_searchText); m_searchButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode node = searchNode(m_searchText.getText()); if (node != null) { TreeNode[] nodes = m_model.getPathToRoot(node); TreePath path = new TreePath(nodes); m_tree.scrollPathToVisible(path); m_tree.setSelectionPath(path); } else { System.out.println("Node with string " + m_searchText.getText() + " not found"); } } }); searchPanel.add(m_searchButton); m_searchAndDeleteButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode node = searchNode(m_searchText.getText()); if (node != null) { removeNode(node); } else { System.out.println("Node with string " + m_searchText.getText() + " not found"); } } }); searchPanel.add(m_searchAndDeleteButton); panel.add(searchPanel); getContentPane().add(panel, BorderLayout.SOUTH); setSize(700, 400); setVisible(true); } public DefaultMutableTreeNode searchNode(String nodeStr) { DefaultMutableTreeNode node = null; Enumeration e = m_rootNode.breadthFirstEnumeration(); while (e.hasMoreElements()) { node = (DefaultMutableTreeNode) e.nextElement(); if (nodeStr.equals(node.getUserObject().toString())) { return node; } } return null; } public void removeNode(DefaultMutableTreeNode selNode) { if (selNode == null) { return; } MutableTreeNode parent = (MutableTreeNode) (selNode.getParent()); if (parent == null) { return; } MutableTreeNode toBeSelNode = getSibling(selNode); if (toBeSelNode == null) { toBeSelNode = parent; } TreeNode[] nodes = m_model.getPathToRoot(toBeSelNode); TreePath path = new TreePath(nodes); m_tree.scrollPathToVisible(path); m_tree.setSelectionPath(path); m_model.removeNodeFromParent(selNode); } private MutableTreeNode getSibling(DefaultMutableTreeNode selNode) { MutableTreeNode sibling = (MutableTreeNode) selNode.getPreviousSibling(); if (sibling == null) { sibling = (MutableTreeNode) selNode.getNextSibling(); } return sibling; } public static void main(String[] arg) { EditableTree editableTree = new EditableTree(); }
}
</source>
Set the Tree Line
<source lang="java">
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); }
}
</source>
Setting the Row Height of a JTree
<source lang="java">
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); }
}
</source>
Traverse all expanded nodes in tree
<source lang="java">
import java.util.Enumeration; import javax.swing.JTree; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; public class Main {
public 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); } } }
}
</source>
Traverse Tree
<source lang="java">
/* 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 + "]"; }
}
</source>
Tree based on Array structure
<source lang="java">
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 + "]"; }
}
</source>
Tree: Drag and Drop
<source lang="java">
/* 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; }
}
</source>
Tree Expand Event Demo
<source lang="java">
/* 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(); } }); }
}
</source>
Tree Expand Event Demo 2
<source lang="java">
/* 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(); } }); }
}
</source>
TreeExpansionListener and TreeExpansionEvent
<source lang="java">
/*
* Copyright (c) 1995 - 2008 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/*
* 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(); } }); }
}
</source>
Tree Icon Demo
<source lang="java">
/* 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(); } }); }
}
</source>
Tree Lines
<source lang="java">
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); }
}
</source>
Tree open Icon
<source lang="java">
/* 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); }
}
</source>
Tree Selection Row
<source lang="java">
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); }
}
</source>
Tree will Expand event and listener
<source lang="java">
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); }
}
</source>
Use UIManager to change the default icon for JTree
<source lang="java">
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); }
}
</source>
Visiting All the Nodes in a JTree Component
<source lang="java">
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); } } }
}
</source>