Java/Swing JFC/Tree

Материал из Java эксперт
Версия от 06:41, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

Add and remove tree Node and expand the tree node

  
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class ModelJTree extends JFrame {
  private JTree tree;
  private DefaultTreeModel model;
  private DefaultMutableTreeNode rootNode;
  public ModelJTree() {
    DefaultMutableTreeNode philosophersNode = getPhilosopherTree();
    model = new DefaultTreeModel(philosophersNode);
    tree = new JTree(model);
    JButton addButton = new JButton("Add Philosopher");
    addButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        addPhilosopher();
      }
    });
    JButton removeButton = new JButton("Remove Selected Philosopher");
    removeButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        removeSelectedPhilosopher();
      }
    });
    JPanel inputPanel = new JPanel();
    inputPanel.add(addButton);
    inputPanel.add(removeButton);
    Container container = getContentPane();
    container.add(new JScrollPane(tree), BorderLayout.CENTER);
    container.add(inputPanel, BorderLayout.NORTH);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(400, 300);
    setVisible(true);
  }
  private void addPhilosopher() {
    DefaultMutableTreeNode parent = getSelectedNode();
    if (parent == null) {
      JOptionPane.showMessageDialog(ModelJTree.this, "Select an era.", "Error",
          JOptionPane.ERROR_MESSAGE);
      return;
    }
    String name = JOptionPane.showInputDialog(ModelJTree.this, "Enter Name:");
    model.insertNodeInto(new DefaultMutableTreeNode(name), parent, parent.getChildCount());
  }
  private void removeSelectedPhilosopher() {
    DefaultMutableTreeNode selectedNode = getSelectedNode();
    if (selectedNode != null)
      model.removeNodeFromParent(selectedNode);
  }
  private DefaultMutableTreeNode getSelectedNode() {
    return (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
  }
  private DefaultMutableTreeNode getPhilosopherTree() {
    DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Philosophers");
    DefaultMutableTreeNode ancient = new DefaultMutableTreeNode("Ancient");
    rootNode.add(ancient);
    ancient.add(new DefaultMutableTreeNode("Socrates"));
    DefaultMutableTreeNode medieval = new DefaultMutableTreeNode("Medieval");
    rootNode.add(medieval);
    return rootNode;
  }
  public static void main(String args[]) {
    new ModelJTree();
  }
}





Adding a Node to a JTree Component

  
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
    TreePath path = tree.getSelectionPath();
    MutableTreeNode node = (MutableTreeNode) path.getLastPathComponent();
    MutableTreeNode newNode = new DefaultMutableTreeNode("green");
    model.insertNodeInto(newNode, node, node.getChildCount());
  }
}





Adding editable nodes to JTree

  
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main extends JFrame {
  DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("J");
  DefaultTreeModel model = new DefaultTreeModel(rootNode);
  JTree m_tree = new JTree(model);
  JButton addButton;
  public Main() {
    DefaultMutableTreeNode forums = new DefaultMutableTreeNode("F");
    forums.add(new DefaultMutableTreeNode("T"));
    DefaultMutableTreeNode articles = new DefaultMutableTreeNode("A");
    articles.add(new DefaultMutableTreeNode("1"));
    DefaultMutableTreeNode examples = new DefaultMutableTreeNode("E");
    examples.add(new DefaultMutableTreeNode("2"));
    rootNode.add(forums);
    rootNode.add(articles);
    rootNode.add(examples);
    m_tree.setEditable(true);
    m_tree.setSelectionRow(0);
    JScrollPane scrollPane = new JScrollPane(m_tree);
    getContentPane().add(scrollPane, BorderLayout.CENTER);
    JPanel panel = new JPanel();
    addButton = new JButton("Add Node");
    addButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
            .getLastSelectedPathComponent();
        if (selNode != null) {
          DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New Node");
          model.insertNodeInto(newNode, selNode, selNode.getChildCount());
          TreeNode[] nodes = model.getPathToRoot(newNode);
          TreePath path = new TreePath(nodes);
          m_tree.scrollPathToVisible(path);
          m_tree.setSelectionPath(path);
          m_tree.startEditingAtPath(path);
        }
      }
    });
    panel.add(addButton);
    getContentPane().add(panel, BorderLayout.SOUTH);
    setSize(300, 400);
    setVisible(true);
  }
  public static void main(String[] arg) {
    new Main();
  }
}





Add Tree to JScrollPane

  
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeSample {
  public static void main(String args[]) {
    JFrame f = new JFrame("JTree Sample");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container content = f.getContentPane();
    JTree tree = new JTree();
    JScrollPane scrollPane = new JScrollPane(tree);
    content.add(scrollPane, BorderLayout.CENTER);
    f.setSize(300, 200);
    f.setVisible(true);
  }
}





Allow multiple selections of visible nodes

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;
public class TreeDISCONTIGUOUSSelection {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
    JFrame frame = new JFrame("tree DISCONTIGUOUS selection");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Allow only a single node to be selected (default)

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;

public class TreeSingleSelection {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    JFrame frame = new JFrame("Tree single selection");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Allow selection to span one vertical contiguous set of visible nodes

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;
public class TreeCONTIGUOUSSelection {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
    JFrame frame = new JFrame("Tree CONTIGUOUS selection");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





All rows will be given 15 pixels of height

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeight15 {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    tree.setRowHeight(15);
    JFrame frame = new JFrame("Image");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Ancestor Tree with Icons

  
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.tree.*;
public class AncestorTree extends JFrame
{
  public static ImageIcon ICON_SELF = 
    new ImageIcon("myself.gif");
  public static ImageIcon ICON_MALE = 
    new ImageIcon("male.gif");
  public static ImageIcon ICON_FEMALE = 
    new ImageIcon("female.gif");
  protected JTree  m_tree;
  protected DefaultTreeModel m_model;
  protected IconCellRenderer m_renderer;
  protected IconCellEditor m_editor;
  public AncestorTree()
  {
    super("Ancestor Tree");
    setSize(400, 300);
        DefaultMutableTreeNode top = new DefaultMutableTreeNode( 
      new IconData(ICON_SELF, "Myself"));
    addAncestors(top);
    m_model = new DefaultTreeModel(top);
    m_tree = new JTree(m_model);
    m_tree.getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION);
    m_tree.setShowsRootHandles(true); 
    m_tree.setEditable(true);
    m_renderer = new IconCellRenderer();
    m_tree.setCellRenderer(m_renderer); 
    m_editor = new IconCellEditor(m_tree);
    m_tree.setCellEditor(m_editor);
    m_tree.setInvokesStopCellEditing(true);
    m_tree.addMouseListener(new TreeExpander()); 
    JScrollPane s = new JScrollPane();
    s.getViewport().add(m_tree);
    getContentPane().add(s, BorderLayout.CENTER);
    WindowListener wndCloser = new WindowAdapter()
    {
      public void windowClosing(WindowEvent e) 
      {
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);
    setVisible(true);
  }
  public boolean addAncestors(DefaultMutableTreeNode node)
  {
    if (node.getChildCount() > 0)
      return false;
    Object obj = node.getUserObject();
    if (obj == null)
      return false;
    node.add(new DefaultMutableTreeNode( new IconData(
      ICON_MALE, "Father of: "+obj.toString()) ));
    node.add(new DefaultMutableTreeNode( new IconData(
      ICON_FEMALE, "Mother of: "+obj.toString()) ));
    return true;
  }
  public static void main(String argv[]) 
  {
    new AncestorTree();
  }
  class TreeExpander 
    extends MouseAdapter 
  {
    public void mouseClicked(MouseEvent e)
    {
      if (e.getClickCount() == 2)
      {
        TreePath selPath = m_tree.getPathForLocation(
          e.getX(), e.getY());
        if (selPath == null)
          return;
        DefaultMutableTreeNode node = 
          (DefaultMutableTreeNode)(selPath.
            getLastPathComponent());
        if (node!=null && addAncestors(node))
        {
          m_tree.expandPath(selPath);
          m_tree.repaint();
        }
      }
    }
  }
}
class IconCellRenderer 
  extends    JLabel 
  implements TreeCellRenderer
{
  protected Color m_textSelectionColor;
  protected Color m_textNonSelectionColor;
  protected Color m_bkSelectionColor;
  protected Color m_bkNonSelectionColor;
  protected Color m_borderSelectionColor;
  protected boolean m_selected;
  public IconCellRenderer()
  {
    super();
    m_textSelectionColor = UIManager.getColor(
      "Tree.selectionForeground");
    m_textNonSelectionColor = UIManager.getColor(
      "Tree.textForeground");
    m_bkSelectionColor = UIManager.getColor(
      "Tree.selectionBackground");
    m_bkNonSelectionColor = UIManager.getColor(
      "Tree.textBackground");
    m_borderSelectionColor = UIManager.getColor(
      "Tree.selectionBorderColor");
    setOpaque(false);
  }
  public Component getTreeCellRendererComponent(JTree tree, 
    Object value, boolean sel, boolean expanded, boolean leaf, 
    int row, boolean hasFocus) 
    
  {
    DefaultMutableTreeNode node = 
      (DefaultMutableTreeNode)value;
    Object obj = node.getUserObject();
    setText(obj.toString());
    if (obj instanceof IconData)
    {
      IconData idata = (IconData)obj;
      if (expanded)
        setIcon(idata.getOpenIcon());
      else
        setIcon(idata.getIcon());
    }
    else
      setIcon(null);
    setFont(tree.getFont());
    setForeground(sel ? m_textSelectionColor : 
      m_textNonSelectionColor);
    setBackground(sel ? m_bkSelectionColor : 
      m_bkNonSelectionColor);
    m_selected = sel;
    return this;
  }
    
  public void paint(Graphics g) 
  {
    Color bColor = getBackground();
    Icon icon = getIcon();
    g.setColor(bColor);
    int offset = 0;
    if(icon != null && getText() != null) 
      offset = (icon.getIconWidth() + getIconTextGap());
    g.fillRect(offset, 0, getWidth() - 1 - offset,
      getHeight() - 1);
    
    if (m_selected) 
    {
      g.setColor(m_borderSelectionColor);
      g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
    }
    super.paint(g);
    }
}
class IconData
{
  protected Icon   m_icon;
  protected Icon   m_openIcon;
  protected Object m_data;
  public IconData(Icon icon, Object data)
  {
    m_icon = icon;
    m_openIcon = null;
    m_data = data;
  }
  public IconData(Icon icon, Icon openIcon, Object data)
  {
    m_icon = icon;
    m_openIcon = openIcon;
    m_data = data;
  }
  public Icon getIcon() 
  { 
    return m_icon;
  }
  public Icon getOpenIcon() 
  { 
    return m_openIcon!=null ? m_openIcon : m_icon;
  }
  public Object getObject() 
  { 
    return m_data;
  }
  public String toString() 
  { 
    return m_data.toString();
  }
}
class IconCellEditor 
  extends    JLabel 
  implements TreeCellEditor, ActionListener
{
  protected JTree      m_tree = null;
  protected JTextField m_editor = null;
  protected IconData   m_item = null;
  protected int        m_lastRow = -1;
  protected long       m_lastClick = 0;
  protected Vector     m_listeners = null;
  public IconCellEditor(JTree tree)
  {
    super();
    m_tree = tree;
    m_listeners = new Vector();
  }
  public Component getTreeCellEditorComponent(JTree tree, 
    Object value, boolean isSelected, boolean expanded, 
    boolean leaf, int row)
  {
    if (value instanceof DefaultMutableTreeNode)
    {
      DefaultMutableTreeNode node = 
        (DefaultMutableTreeNode)value;
      Object obj = node.getUserObject();
      if (obj instanceof IconData)
      {
        IconData idata = (IconData)obj;
        m_item = idata;
        // Reserve some more space...
        setText(idata.toString()+"     "); 
        setIcon(idata.m_icon);
        setFont(tree.getFont());
        return this;
      }
    }
    // We don"t support other objects...
    return null;
  }
  public Object getCellEditorValue() 
  { 
    if (m_item != null && m_editor != null)
      m_item.m_data = m_editor.getText();
    return m_item; 
  }
  public boolean isCellEditable(EventObject evt) 
  { 
    if (evt instanceof MouseEvent)
    {
      MouseEvent mEvt = (MouseEvent)evt;
      if (mEvt.getClickCount() == 1)
      {
        int row = m_tree.getRowForLocation(mEvt.getX(), 
          mEvt.getY());
        if (row != m_lastRow)
        {
          m_lastRow = row;
          m_lastClick = System.currentTimeMillis();
          return false;
        }
        else if (System.currentTimeMillis()-m_lastClick 
          > 1000)
        {
          m_lastRow = -1;
          m_lastClick = 0;
          prepareEditor();
          mEvt.consume();
          return true;
        }
        else
          return false; 
      }
    }
    return false; 
  }
    protected void prepareEditor() 
  {
    if (m_item == null)
      return;
    String str = m_item.toString();
    m_editor = new JTextField(str);
    m_editor.addActionListener(this);
    m_editor.selectAll();
    m_editor.setFont(m_tree.getFont());
    
    add(m_editor);
    revalidate();
    TreePath path = m_tree.getPathForRow(m_lastRow);
    m_tree.startEditingAtPath(path);
  }
    protected void removeEditor() 
  {
    if (m_editor != null)
    {
      remove(m_editor);
      m_editor.setVisible(false);
      m_editor = null;
      m_item = null;
    }
  }
  public void doLayout()
  {
    super.doLayout();
    if (m_editor != null)
    {
      int offset = getIconTextGap();
      if (getIcon() != null)
        offset += getIcon().getIconWidth();
      Dimension cSize = getSize();
      m_editor.setBounds(offset, 0, cSize.width - offset, 
        cSize.height);
    }
  }
  public boolean shouldSelectCell(EventObject evt) 
  { 
    return true; 
  }
  public boolean stopCellEditing() 
  {
    if (m_item != null)
      m_item.m_data = m_editor.getText();
    ChangeEvent e = new ChangeEvent(this);
    for (int k=0; k<m_listeners.size(); k++)
    {
      CellEditorListener l = (CellEditorListener)m_listeners.
        elementAt(k);
      l.editingStopped(e);
    }
    removeEditor();
    return true; 
  }
  public void cancelCellEditing() 
  {
    ChangeEvent e = new ChangeEvent(this);
    for (int k=0; k<m_listeners.size(); k++)
    {
      CellEditorListener l = (CellEditorListener)m_listeners.
        elementAt(k);
      l.editingCanceled(e);
    }
    removeEditor();
  }
  public void addCellEditorListener(CellEditorListener l) 
  {
    m_listeners.addElement(l);
  }
  public void removeCellEditorListener(CellEditorListener l)
  {
    m_listeners.removeElement(l);
  }
  public void actionPerformed(ActionEvent e)
  {
    stopCellEditing();
    m_tree.stopEditing();
  }
}





A sample component for dragging and dropping a collection of files into a tree.

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// FSTest.java
//A quick test environment for the FSTree component.
//
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
public class FSTest extends JFrame {
  public FSTest() {
    super("FSTree Component Test");
    setSize(300, 300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    FSTree fst = new FSTree(new DefaultMutableTreeNode("Starter"));
    getContentPane().add(new JScrollPane(fst));
    setVisible(true);
  }
  public static void main(String args[]) {
    new FSTest();
  }
}
//FSTree.java
//A sample component for dragging & dropping a collection of files
//into a tree.
//
class FSTree extends JTree {
  public FSTree() {
    super();
    init();
  }
  public FSTree(TreeModel newModel) {
    super(newModel);
    init();
  }
  public FSTree(TreeNode root) {
    super(root);
    init();
  }
  public FSTree(TreeNode root, boolean asks) {
    super(root, asks);
    init();
  }
  private void init() {
    // We don"t want to export anything from this tree, only import
    setDragEnabled(false);
    setTransferHandler(new FSTransfer());
  }
  public class FSTransfer extends TransferHandler {
    public boolean importData(JComponent comp, Transferable t) {
      // Make sure we have the right starting points
      if (!(comp instanceof FSTree)) {
        return false;
      }
      if (!t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
        return false;
      }
      // Grab the tree, its model and the root node
      FSTree tree = (FSTree) comp;
      DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
      DefaultMutableTreeNode root = (DefaultMutableTreeNode) model
          .getRoot();
      try {
        List data = (List) t
            .getTransferData(DataFlavor.javaFileListFlavor);
        Iterator i = data.iterator();
        while (i.hasNext()) {
          File f = (File) i.next();
          root.add(new DefaultMutableTreeNode(f.getName()));
        }
        model.reload();
        return true;
      } catch (UnsupportedFlavorException ufe) {
        System.err.println("Ack! we should not be here.\nBad Flavor.");
      } catch (IOException ioe) {
        System.out.println("Something failed during import:\n" + ioe);
      }
      return false;
    }
    // We only support file lists on FSTrees...
    public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
      if (comp instanceof FSTree) {
        for (int i = 0; i < transferFlavors.length; i++) {
          if (!transferFlavors[i]
              .equals(DataFlavor.javaFileListFlavor)) {
            return false;
          }
        }
        return true;
      }
      return false;
    }
  }
}





A simple test to see how we can build a tree and populate it

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// TestTree.java
//A simple test to see how we can build a tree and populate it. We build
//the tree structure up by hand in this case.
//
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class TestTree extends JFrame {
  JTree tree;
  DefaultTreeModel treeModel;
  public TestTree() {
    super("Tree Test Example");
    setSize(400, 300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }
  public void init() {
    // Build up a bunch of TreeNodes. We use DefaultMutableTreeNode because
    // the
    // DefaultTreeModel can use it to build a complete tree.
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    DefaultMutableTreeNode subroot = new DefaultMutableTreeNode("SubRoot");
    DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("Leaf 1");
    DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("Leaf 2");
    // Build our tree model starting at the root node, and then make a JTree
    // out
    // of that.
    treeModel = new DefaultTreeModel(root);
    tree = new JTree(treeModel);
    // Build the tree up from the nodes we created.
    treeModel.insertNodeInto(subroot, root, 0);
    // Or, more succinctly:
    subroot.add(leaf1);
    root.add(leaf2);
    // Display it.
    getContentPane().add(tree, BorderLayout.CENTER);
  }
  public static void main(String args[]) {
    TestTree tt = new TestTree();
    tt.init();
    tt.setVisible(true);
  }
}





A tree with component

  
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Font;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
public class ComponentHier {
  public static void main(String args[]) {
    JFrame frame = new JFrame("JComponent Hierarchy");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Font font = (Font) UIManager.get("Tree.font");
    font = new Font(font.getFontName(), Font.BOLD, font.getSize() - 3);
    UIManager.put("Tree.font", font);
    Vector jEditorPaneVector = new NamedVector("JEditorPane",
        new Object[] { "JTextPane" });
    Vector jTextFieldVector = new NamedVector("JTextField",
        new Object[] { "JPasswordField" });
    Vector jTextComponentVector = new NamedVector(
        "JTextComponent",
        new Object[] { jEditorPaneVector, "JTextArea", jTextFieldVector });
    Vector jLayeredPaneVector = new NamedVector("JLayeredPane",
        new Object[] { "JDesktopPane" });
    Vector jToggleButtonVector = new NamedVector("JToggleButton",
        new Object[] { "JCheckBox", "JRadioButton" });
    Vector jMenuItemVector = new NamedVector("JMenuItem", new Object[] {
        "JCheckBoxMenuItem", "JMenu", "JRadioButtonMenuItem" });
    Vector abstractButtonVector = new NamedVector(
        "Abstract Button",
        new Object[] { "JButton", jMenuItemVector, jToggleButtonVector });
    Object jComponentNodes[] = { abstractButtonVector, "JColorChooser",
        "JComboBox", "JFileChooser", "JInternalFrame", "JLabel",
        jLayeredPaneVector, "JList", "JMenuBar", "JOptionPane",
        "JPanel", "JPopupMenu", "JProgressBar", "JRootPane",
        "JScrollBar", "JScrollPane", "JSeparator", "JSlider",
        "JSplitPane", "JTabbedPane", "JTable", jTextComponentVector,
        "JToolBar", "JTree", "JViewPort" };
    Vector jComponentVector = new NamedVector("JComponent", jComponentNodes);
    Object rootNodes[] = { jComponentVector };
    Vector rootVector = new NamedVector("Root", rootNodes);
    JTree tree = new JTree(rootVector);
    tree.putClientProperty("JTree.lineStyle", "Angled");
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(250, 480);
    frame.setVisible(true);
  }
}
class NamedVector extends Vector {
  String name;
  public NamedVector(String name) {
    this.name = name;
  }
  public NamedVector(String name, Object elements[]) {
    this.name = name;
    for (int i = 0, n = elements.length; i < n; i++) {
      add(elements[i]);
    }
  }
  public String toString() {
    return "[" + name + "]";
  }
}





Build a tree and customize its icons

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// TestTree4.java
//Another test to see how we can build a tree and customize its icons.
//This example does not affect the icons of other trees.
//
import java.awt.BorderLayout;
import java.util.Hashtable;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
public class TestTree4 extends JFrame {
  JTree tree1, tree2;
  DefaultTreeModel treeModel;
  public TestTree4() {
    super("Custom Icon Example");
    setSize(350, 450);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    // Build the hierarchy of containers & objects
    String[] schoolyard = { "School", "Playground", "Parking Lot", "Field" };
    String[] mainstreet = { "Grocery", "Shoe Shop", "Five & Dime",
        "Post Office" };
    String[] highway = { "Gas Station", "Convenience Store" };
    String[] housing = { "Victorian_blue", "Faux Colonial",
        "Victorian_white" };
    String[] housing2 = { "Mission", "Ranch", "Condo" };
    Hashtable homeHash = new Hashtable();
    homeHash.put("Residential 1", housing);
    homeHash.put("Residential 2", housing2);
    Hashtable cityHash = new Hashtable();
    cityHash.put("School grounds", schoolyard);
    cityHash.put("Downtown", mainstreet);
    cityHash.put("Highway", highway);
    cityHash.put("Housing", homeHash);
    Hashtable worldHash = new Hashtable();
    worldHash.put("My First VRML World", cityHash);
    // Build our tree out of our big hashtable
    tree1 = new JTree(worldHash);
    tree2 = new JTree(worldHash);
    DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree2
        .getCellRenderer();
    renderer.setClosedIcon(new ImageIcon("door.closed.gif"));
    renderer.setOpenIcon(new ImageIcon("door.open.gif"));
    renderer.setLeafIcon(new ImageIcon("world.gif"));
    JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tree1,
        tree2);
    getContentPane().add(pane, BorderLayout.CENTER);
  }
  public static void main(String args[]) {
    TestTree4 tt = new TestTree4();
    tt.setVisible(true);
  }
}





Build a tree and populate it from hashtables

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// ObjectTree.java
//A simple test to see how we can build a tree and populate it. This version
//builds the tree from hashtables.
//
import java.awt.BorderLayout;
import java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JTree;
public class ObjectTree extends JFrame {
  JTree tree;
  String[][] sampleData = { { "Amy" }, { "Brandon", "Bailey" }, { "Jodi" },
      { "Trent", "Garrett", "Paige", "Dylan" }, { "Donn" },
      { "Nancy", "Donald", "Phyllis", "John", "Pat" }, { "Ron" },
      { "Linda", "Mark", "Lois", "Marvin" } };
  public ObjectTree() {
    super("Hashtable Test");
    setSize(400, 300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }
  public void init() {
    Hashtable h = new Hashtable();
    // Build up the hashtable using every other entry in the String[][] as a
    // key
    // followed by a String[]"value."
    for (int i = 0; i < sampleData.length; i += 2) {
      h.put(sampleData[i][0], sampleData[i + 1]);
    }
    tree = new JTree(h);
    getContentPane().add(tree, BorderLayout.CENTER);
  }
  public static void main(String args[]) {
    ObjectTree tt = new ObjectTree();
    tt.init();
    tt.setVisible(true);
  }
}





Build a tree based on DefaultMutableTreeNode

  
// : c14:Trees.java
// Simple Swing tree. Trees can be vastly more complex.
// <applet code=Trees width=250 height=250></applet>
// From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002
// www.BruceEckel.ru. See copyright notice in CopyRight.txt.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
// Takes an array of Strings and makes the first
// element a node and the rest leaves:
class Branch {
  private DefaultMutableTreeNode r;
  public Branch(String[] data) {
    r = new DefaultMutableTreeNode(data[0]);
    for (int i = 1; i < data.length; i++)
      r.add(new DefaultMutableTreeNode(data[i]));
  }
  public DefaultMutableTreeNode node() {
    return r;
  }
}
public class Trees extends JApplet {
  private String[][] data = { { "Colors", "Red", "Blue", "Green" },
      { "Flavors", "Tart", "Sweet", "Bland" },
      { "Length", "Short", "Medium", "Long" },
      { "Volume", "High", "Medium", "Low" },
      { "Temperature", "High", "Medium", "Low" },
      { "Intensity", "High", "Medium", "Low" }, };
  private static int i = 0;
  private DefaultMutableTreeNode root, child, chosen;
  private JTree tree;
  private DefaultTreeModel model;
  public void init() {
    Container cp = getContentPane();
    root = new DefaultMutableTreeNode("root");
    tree = new JTree(root);
    // Add it and make it take care of scrolling:
    cp.add(new JScrollPane(tree), BorderLayout.CENTER);
    // Capture the tree"s model:
    model = (DefaultTreeModel) tree.getModel();
    JButton test = new JButton("Press me");
    test.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        if (i < data.length) {
          child = new Branch(data[i++]).node();
          // What"s the last one you clicked?
          chosen = (DefaultMutableTreeNode) tree
              .getLastSelectedPathComponent();
          if (chosen == null)
            chosen = root;
          // The model will create the appropriate event.
          // In response, the tree will update itself:
          model.insertNodeInto(child, chosen, 0);
          // Puts the new node on the chosen node.
        }
      }
    });
    // Change the button"s colors:
    test.setBackground(Color.BLUE);
    test.setForeground(Color.WHITE);
    JPanel p = new JPanel();
    p.add(test);
    cp.add(p, BorderLayout.SOUTH);
  }
  public static void main(String[] args) {
    run(new Trees(), 250, 250);
  }
  public static void run(JApplet applet, int width, int height) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(applet);
    frame.setSize(width, height);
    applet.init();
    applet.start();
    frame.setVisible(true);
  }
} ///:~





Changing and Removing the Default Icons in a JTree Component

  
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultTreeCellRenderer;
public class Main {
  public static void main(String[] argv) throws Exception {
    Icon leafIcon = new ImageIcon("leaf.gif");
    Icon openIcon = new ImageIcon("open.gif");
    Icon closedIcon = new ImageIcon("closed.gif");
    JTree tree = new JTree();
    DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) tree.getCellRenderer();
    renderer.setLeafIcon(leafIcon);
    renderer.setClosedIcon(closedIcon);
    renderer.setOpenIcon(openIcon);

    JFrame f = new JFrame();
    f.add(new JScrollPane(tree));
    f.setSize(300, 300);
    f.setVisible(true);
  }
}





Converting All Nodes in a JTree Component to a TreePath Array

  
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
  public TreePath[] getPaths(JTree tree, boolean expanded) {
    TreeNode root = (TreeNode) tree.getModel().getRoot();
    List<TreePath> list = new ArrayList<TreePath>();
    getPaths(tree, new TreePath(root), expanded, list);
    return (TreePath[]) list.toArray(new TreePath[list.size()]);
  }
  public void getPaths(JTree tree, TreePath parent, boolean expanded, List<TreePath> list) {
    if (expanded && !tree.isVisible(parent)) {
      return;
    }
    list.add(parent);
    TreeNode node = (TreeNode) parent.getLastPathComponent();
    if (node.getChildCount() >= 0) {
      for (Enumeration e = node.children(); e.hasMoreElements();) {
        TreeNode n = (TreeNode) e.nextElement();
        TreePath path = parent.pathByAddingChild(n);
        getPaths(tree, path, expanded, list);
      }
    }
  }
}





Creating a JTree Component

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
public class Main {
  public static void main(String[] argv) throws Exception {
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root Label");
    root.add(new DefaultMutableTreeNode("Node Label"));
    JTree tree = new JTree(root);
    
    JFrame f = new JFrame();
    f.add(new JScrollPane(tree));
    f.setSize(300,300);
    f.setVisible(true);
  }
}





DefaultMutableTreeNode and user object

  
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/**
 * A 1.4 application that requires the following additional files:
 *   TreeDemoHelp.html
 *    arnold.html
 *    bloch.html
 *    chan.html
 *    jls.html
 *    swingtutorial.html
 *    tutorial.html
 *    tutorialcont.html
 *    vm.html
 */
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.ToolTipManager;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import java.net.URL;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.ruponent;

public class TreeIconDemo2 extends JPanel 
                           implements TreeSelectionListener {
    private JEditorPane htmlPane;
    private JTree tree;
    private URL helpURL;
    private static boolean DEBUG = false;
    public TreeIconDemo2() {
        super(new GridLayout(1,0));
        //Create the nodes.
        DefaultMutableTreeNode top =
            new DefaultMutableTreeNode("The Java Series");
        createNodes(top);
        //Create a tree that allows one selection at a time.
        tree = new JTree(top);
        tree.getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);
        //Enable tool tips.
        ToolTipManager.sharedInstance().registerComponent(tree);
        //Set the icon for leaf nodes.
        ImageIcon tutorialIcon = createImageIcon("images/middle.gif");
        if (tutorialIcon != null) {
            tree.setCellRenderer(new MyRenderer(tutorialIcon));
        } else {
            System.err.println("Tutorial icon missing; using default.");
        }
        //Listen for when the selection changes.
        tree.addTreeSelectionListener(this);
        //Create the scroll pane and add the tree to it. 
        JScrollPane treeView = new JScrollPane(tree);
        //Create the HTML viewing pane.
        htmlPane = new JEditorPane();
        htmlPane.setEditable(false);
        initHelp();
        JScrollPane htmlView = new JScrollPane(htmlPane);
        //Add the scroll panes to a split pane.
        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        splitPane.setTopComponent(treeView);
        splitPane.setBottomComponent(htmlView);
        Dimension minimumSize = new Dimension(100, 50);
        htmlView.setMinimumSize(minimumSize);
        treeView.setMinimumSize(minimumSize);
        splitPane.setDividerLocation(100); //XXX: ignored in some releases
                                           //of Swing. bug 4101306
        //workaround for bug 4101306:
        //treeView.setPreferredSize(new Dimension(100, 100)); 
        splitPane.setPreferredSize(new Dimension(500, 300));
        //Add the split pane to this panel.
        add(splitPane);
    }
    /** Required by TreeSelectionListener interface. */
    public void valueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                           tree.getLastSelectedPathComponent();
        if (node == null) return;
        Object nodeInfo = node.getUserObject();
        if (node.isLeaf()) {
            BookInfo book = (BookInfo)nodeInfo;
            displayURL(book.bookURL);
            if (DEBUG) {
                System.out.print(book.bookURL + ":  \n    ");
            }
        } else {
            displayURL(helpURL); 
        }
        if (DEBUG) {
            System.out.println(nodeInfo.toString());
        }
    }
    private class BookInfo {
        public String bookName;
        public URL bookURL;
        public BookInfo(String book, String filename) {
            bookName = book;
            bookURL = TreeIconDemo2.class.getResource(filename);
            if (bookURL == null) {
                System.err.println("Couldn"t find file: "
                                   + filename);
            }
        }
        public String toString() {
            return bookName;
        }
    }
    private void initHelp() {
        String s = "TreeDemoHelp.html";
        helpURL = TreeIconDemo2.class.getResource(s);
        if (helpURL == null) {
            System.err.println("Couldn"t open help file: " + s);
        } else if (DEBUG) {
            System.out.println("Help URL is " + helpURL);
        }
        displayURL(helpURL);
    }
    private void displayURL(URL url) {
        try {
            if (url != null) {
                htmlPane.setPage(url);
            } else { //null url
    htmlPane.setText("File Not Found");
                if (DEBUG) {
                    System.out.println("Attempted to display a null URL.");
                }
            }
        } catch (IOException e) {
            System.err.println("Attempted to read a bad URL: " + url);
        }
    }
    private void createNodes(DefaultMutableTreeNode top) {
        DefaultMutableTreeNode category = null;
        DefaultMutableTreeNode book = null;
        category = new DefaultMutableTreeNode("Books for Java Programmers");
        top.add(category);
        //original Tutorial
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Tutorial: A Short Course on the Basics",
            "tutorial.html"));
        category.add(book);
        //Tutorial Continued
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Tutorial Continued: The Rest of the JDK",
            "tutorialcont.html"));
        category.add(book);
        //JFC Swing Tutorial
        book = new DefaultMutableTreeNode(new BookInfo
            ("The JFC Swing Tutorial: A Guide to Constructing GUIs",
            "swingtutorial.html"));
        category.add(book);
        //Bloch
        book = new DefaultMutableTreeNode(new BookInfo
            ("Effective Java Programming Language Guide",
       "bloch.html"));
        category.add(book);
        //Arnold/Gosling
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Programming Language", "arnold.html"));
        category.add(book);
        //Chan
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Developers Almanac",
             "chan.html"));
        category.add(book);
        category = new DefaultMutableTreeNode("Books for Java Implementers");
        top.add(category);
        //VM
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Virtual Machine Specification",
             "vm.html"));
        category.add(book);
        //Language Spec
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Language Specification",
             "jls.html"));
        category.add(book);
    }
    /** Returns an ImageIcon, or null if the path was invalid. */
    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = TreeIconDemo2.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn"t find file: " + path);
            return null;
        }
    }
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);
        //Create and set up the window.
        JFrame frame = new JFrame("TreeIconDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Create and set up the content pane.
        TreeIconDemo2 newContentPane = new TreeIconDemo2();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application"s GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
    private class MyRenderer extends DefaultTreeCellRenderer {
        Icon tutorialIcon;
        public MyRenderer(Icon icon) {
            tutorialIcon = icon;
        }
        public Component getTreeCellRendererComponent(
                            JTree tree,
                            Object value,
                            boolean sel,
                            boolean expanded,
                            boolean leaf,
                            int row,
                            boolean hasFocus) {
            super.getTreeCellRendererComponent(
                            tree, value, sel,
                            expanded, leaf, row,
                            hasFocus);
            if (leaf && isTutorialBook(value)) {
                setIcon(tutorialIcon);
                setToolTipText("This book is in the Tutorial series.");
            } else {
                setToolTipText(null); //no tool tip
            }
            return this;
        }
        protected boolean isTutorialBook(Object value) {
            DefaultMutableTreeNode node =
                    (DefaultMutableTreeNode)value;
            BookInfo nodeInfo = 
                    (BookInfo)(node.getUserObject());
            String title = nodeInfo.bookName;
            if (title.indexOf("Tutorial") >= 0) {
                return true;
            } 
            return false;
        }
    }
}





DefaultMutableTreeNode Node Tree Sample

  
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
public class NodeTreeSample {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Manual Nodes");
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    DefaultMutableTreeNode mercury = new DefaultMutableTreeNode("Mercury");
    root.add(mercury);
    DefaultMutableTreeNode venus = new DefaultMutableTreeNode("Venus");
    root.add(venus);
    DefaultMutableTreeNode mars = new DefaultMutableTreeNode("Mars");
    root.add(mars);
    JTree tree = new JTree(root);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}





Deleting nodes from JTree

  
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main extends JFrame {
  DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("A");
  private DefaultTreeModel m_model = new DefaultTreeModel(rootNode);
  private JTree m_tree = new JTree(m_model);
  private JButton m_addButton;
  private JButton m_delButton;
  public Main() {
    DefaultMutableTreeNode forums = new DefaultMutableTreeNode("B");
    forums.add(new DefaultMutableTreeNode("T"));
    DefaultMutableTreeNode articles = new DefaultMutableTreeNode("A");
    articles.add(new DefaultMutableTreeNode("A"));
    DefaultMutableTreeNode examples = new DefaultMutableTreeNode("E");
    examples.add(new DefaultMutableTreeNode("E"));
    rootNode.add(forums);
    rootNode.add(articles);
    rootNode.add(examples);
    m_tree.setEditable(true);
    m_tree.setSelectionRow(0);
    JScrollPane scrollPane = new JScrollPane(m_tree);
    getContentPane().add(scrollPane, BorderLayout.CENTER);
    JPanel panel = new JPanel();
    m_addButton = new JButton("Add Node");
    m_addButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
            .getLastSelectedPathComponent();
        if (selNode == null) {
          return;
        }
        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New");
        m_model.insertNodeInto(newNode, selNode, selNode.getChildCount());
        TreeNode[] nodes = m_model.getPathToRoot(newNode);
        TreePath path = new TreePath(nodes);
        m_tree.scrollPathToVisible(path);
        m_tree.setSelectionPath(path);
        m_tree.startEditingAtPath(path);
      }
    });
    panel.add(m_addButton);
    getContentPane().add(panel, BorderLayout.SOUTH);
    m_delButton = new JButton("Delete Node");
    m_delButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
            .getLastSelectedPathComponent();
        if (selNode == null) {
          return;
        }
        MutableTreeNode parent = (MutableTreeNode) (selNode.getParent());
        if (parent == null) {
          return;
        }
        MutableTreeNode toBeSelNode = (MutableTreeNode) selNode.getPreviousSibling();
        if (toBeSelNode == null) {
          toBeSelNode = (MutableTreeNode) selNode.getNextSibling();
        }
        if (toBeSelNode == null) {
          toBeSelNode = parent;
        }
        TreeNode[] nodes = m_model.getPathToRoot(toBeSelNode);
        TreePath path = new TreePath(nodes);
        m_tree.scrollPathToVisible(path);
        m_tree.setSelectionPath(path);
        m_model.removeNodeFromParent(selNode);
      }
    });
    panel.add(m_delButton);
    getContentPane().add(panel, BorderLayout.SOUTH);
    setSize(300, 400);
    setVisible(true);
  }
  public static void main(String[] arg) {
    new Main();
  }
}





Display a file system in a JTree view

  
/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.io.File;
import java.util.Collections;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
/**
 * Display a file system in a JTree view
 * 
 * @version $Id: FileTree.java,v 1.9 2004/02/23 03:39:22 ian Exp $
 * @author Ian Darwin
 */
public class FileTree extends JPanel {
  /** Construct a FileTree */
  public FileTree(File dir) {
    setLayout(new BorderLayout());
    // Make a tree list with all the nodes, and make it a JTree
    JTree tree = new JTree(addNodes(null, dir));
    // Add a listener
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
            .getPath().getLastPathComponent();
        System.out.println("You selected " + node);
      }
    });
    // Lastly, put the JTree into a JScrollPane.
    JScrollPane scrollpane = new JScrollPane();
    scrollpane.getViewport().add(tree);
    add(BorderLayout.CENTER, scrollpane);
  }
  /** Add nodes from under "dir" into curTop. Highly recursive. */
  DefaultMutableTreeNode addNodes(DefaultMutableTreeNode curTop, File dir) {
    String curPath = dir.getPath();
    DefaultMutableTreeNode curDir = new DefaultMutableTreeNode(curPath);
    if (curTop != null) { // should only be null at root
      curTop.add(curDir);
    }
    Vector ol = new Vector();
    String[] tmp = dir.list();
    for (int i = 0; i < tmp.length; i++)
      ol.addElement(tmp[i]);
    Collections.sort(ol, String.CASE_INSENSITIVE_ORDER);
    File f;
    Vector files = new Vector();
    // Make two passes, one for Dirs and one for Files. This is #1.
    for (int i = 0; i < ol.size(); i++) {
      String thisObject = (String) ol.elementAt(i);
      String newPath;
      if (curPath.equals("."))
        newPath = thisObject;
      else
        newPath = curPath + File.separator + thisObject;
      if ((f = new File(newPath)).isDirectory())
        addNodes(curDir, f);
      else
        files.addElement(thisObject);
    }
    // Pass two: for files.
    for (int fnum = 0; fnum < files.size(); fnum++)
      curDir.add(new DefaultMutableTreeNode(files.elementAt(fnum)));
    return curDir;
  }
  public Dimension getMinimumSize() {
    return new Dimension(200, 400);
  }
  public Dimension getPreferredSize() {
    return new Dimension(200, 400);
  }
  /** Main: make a Frame, add a FileTree */
  public static void main(String[] av) {
    JFrame frame = new JFrame("FileTree");
    frame.setForeground(Color.black);
    frame.setBackground(Color.lightGray);
    Container cp = frame.getContentPane();
    if (av.length == 0) {
      cp.add(new FileTree(new File(".")));
    } else {
      cp.setLayout(new BoxLayout(cp, BoxLayout.X_AXIS));
      for (int i = 0; i < av.length; i++)
        cp.add(new FileTree(new File(av[i])));
    }
    frame.pack();
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}





Displaying Hierarchical Data within a JTree

  
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
public class TreeIt {
  class MyCellRenderer extends JLabel implements TreeCellRenderer {
    MyCellRenderer() {
      setOpaque(true);
    }
    public Component getTreeCellRendererComponent(JTree tree, Object value,
        boolean selected, boolean expanded, boolean leaf, int row,
        boolean hasFocus) {
      StringBuffer text = new StringBuffer();
      if (expanded)
        text.append("E:");
      if (leaf)
        text.append("L:");
      if (hasFocus)
        text.append("H:");
      text.append(row + "->");
      text.append(value.toString());
      setBackground(selected ? Color.BLUE : Color.YELLOW);
      setForeground(selected ? Color.YELLOW : Color.BLUE);
      setText(text.toString());
      return this;
    }
  }
  public TreeIt() {
    JFrame f = new JFrame();
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Calendar");
    DefaultMutableTreeNode months = new DefaultMutableTreeNode("Months");
    root.add(months);
    String monthLabels[] = { "January", "February", "March", "April",
        "May", "June", "July", "August", "September", "October",
        "November", "December" };
    for (int i = 0, n = monthLabels.length; i < n; i++)
      months.add(new DefaultMutableTreeNode(monthLabels[i]));
    DefaultMutableTreeNode weeks = new DefaultMutableTreeNode("Weeks");
    root.add(weeks);
    String weekLabels[] = { "Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday" };
    for (int i = 0, n = weekLabels.length; i < n; i++)
      weeks.add(new DefaultMutableTreeNode(weekLabels[i]));
    JTree jt = new JTree(root);
    jt.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent e) {
        TreePath path = e.getPath();
        System.out.println("Picked: " + path.getLastPathComponent());
        Object elements[] = path.getPath();
        for (int i = 0, n = elements.length; i < n; i++) {
          System.out.print("->" + elements[i]);
        }
        System.out.println();
      }
    });
    DefaultMutableTreeNode lastLeaf = root.getLastLeaf();
    TreePath path = new TreePath(lastLeaf.getPath());
    jt.setSelectionPath(path);
    jt.setCellRenderer(new MyCellRenderer());
    JScrollPane jsp = new JScrollPane(jt);
    Container c = f.getContentPane();
    c.add(jsp, BorderLayout.CENTER);
    f.setSize(250, 250);
    f.show();
  }
  public static void main(String args[]) {
    new TreeIt();
  }
}





Display user object in a tree

  
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/**
 * A 1.4 application that requires the following additional files:
 *   TreeDemoHelp.html
 *    arnold.html
 *    bloch.html
 *    chan.html
 *    jls.html
 *    swingtutorial.html
 *    tutorial.html
 *    tutorialcont.html
 *    vm.html
 */
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.IOException;
import java.net.URL;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
public class TreeDemo extends JPanel
                      implements TreeSelectionListener {
    private JEditorPane htmlPane;
    private JTree tree;
    private URL helpURL;
    private static boolean DEBUG = false;
    //Optionally play with line styles.  Possible values are
    //"Angled" (the default), "Horizontal", and "None".
    private static boolean playWithLineStyle = false;
    private static String lineStyle = "Horizontal";
    
    //Optionally set the look and feel.
    private static boolean useSystemLookAndFeel = false;
    public TreeDemo() {
        super(new GridLayout(1,0));
        //Create the nodes.
        DefaultMutableTreeNode top =
            new DefaultMutableTreeNode("The Java Series");
        createNodes(top);
        //Create a tree that allows one selection at a time.
        tree = new JTree(top);
        tree.getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);
        //Listen for when the selection changes.
        tree.addTreeSelectionListener(this);
        if (playWithLineStyle) {
            System.out.println("line style = " + lineStyle);
            tree.putClientProperty("JTree.lineStyle", lineStyle);
        }
        //Create the scroll pane and add the tree to it. 
        JScrollPane treeView = new JScrollPane(tree);
        //Create the HTML viewing pane.
        htmlPane = new JEditorPane();
        htmlPane.setEditable(false);
        initHelp();
        JScrollPane htmlView = new JScrollPane(htmlPane);
        //Add the scroll panes to a split pane.
        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        splitPane.setTopComponent(treeView);
        splitPane.setBottomComponent(htmlView);
        Dimension minimumSize = new Dimension(100, 50);
        htmlView.setMinimumSize(minimumSize);
        treeView.setMinimumSize(minimumSize);
        splitPane.setDividerLocation(100); //XXX: ignored in some releases
                                           //of Swing. bug 4101306
        //workaround for bug 4101306:
        //treeView.setPreferredSize(new Dimension(100, 100)); 
        splitPane.setPreferredSize(new Dimension(500, 300));
        //Add the split pane to this panel.
        add(splitPane);
    }
    /** Required by TreeSelectionListener interface. */
    public void valueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                           tree.getLastSelectedPathComponent();
        if (node == null) return;
        Object nodeInfo = node.getUserObject();
        if (node.isLeaf()) {
            BookInfo book = (BookInfo)nodeInfo;
            displayURL(book.bookURL);
            if (DEBUG) {
                System.out.print(book.bookURL + ":  \n    ");
            }
        } else {
            displayURL(helpURL); 
        }
        if (DEBUG) {
            System.out.println(nodeInfo.toString());
        }
    }
    private class BookInfo {
        public String bookName;
        public URL bookURL;
        public BookInfo(String book, String filename) {
            bookName = book;
            bookURL = TreeDemo.class.getResource(filename);
            if (bookURL == null) {
                System.err.println("Couldn"t find file: "
                                   + filename);
            }
        }
        public String toString() {
            return bookName;
        }
    }
    private void initHelp() {
        String s = "TreeDemoHelp.html";
        helpURL = TreeDemo.class.getResource(s);
        if (helpURL == null) {
            System.err.println("Couldn"t open help file: " + s);
        } else if (DEBUG) {
            System.out.println("Help URL is " + helpURL);
        }
        displayURL(helpURL);
    }
    private void displayURL(URL url) {
        try {
            if (url != null) {
                htmlPane.setPage(url);
            } else { //null url
                htmlPane.setText("File Not Found");
                if (DEBUG) {
                    System.out.println("Attempted to display a null URL.");
                }
            }
        } catch (IOException e) {
            System.err.println("Attempted to read a bad URL: " + url);
        }
    }
    private void createNodes(DefaultMutableTreeNode top) {
        DefaultMutableTreeNode category = null;
        DefaultMutableTreeNode book = null;
        category = new DefaultMutableTreeNode("Books for Java Programmers");
        top.add(category);
        //original Tutorial
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Tutorial: A Short Course on the Basics",
            "tutorial.html"));
        category.add(book);
        //Tutorial Continued
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Tutorial Continued: The Rest of the JDK",
            "tutorialcont.html"));
        category.add(book);
        //JFC Swing Tutorial
        book = new DefaultMutableTreeNode(new BookInfo
            ("The JFC Swing Tutorial: A Guide to Constructing GUIs",
            "swingtutorial.html"));
        category.add(book);
        //Bloch
        book = new DefaultMutableTreeNode(new BookInfo
            ("Effective Java Programming Language Guide",
       "bloch.html"));
        category.add(book);
        //Arnold/Gosling
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Programming Language", "arnold.html"));
        category.add(book);
        //Chan
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Developers Almanac",
             "chan.html"));
        category.add(book);
        category = new DefaultMutableTreeNode("Books for Java Implementers");
        top.add(category);
        //VM
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Virtual Machine Specification",
             "vm.html"));
        category.add(book);
        //Language Spec
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Language Specification",
             "jls.html"));
        category.add(book);
    }
        
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        if (useSystemLookAndFeel) {
            try {
                UIManager.setLookAndFeel(
                    UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                System.err.println("Couldn"t use system look and feel.");
            }
        }
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);
        //Create and set up the window.
        JFrame frame = new JFrame("TreeDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Create and set up the content pane.
        TreeDemo newContentPane = new TreeDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application"s GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





DnD (drag and drop)JTree code

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// TreeDragTest.java
//A simple starting point for testing the DnD JTree code.
//
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class TreeDragTest extends JFrame {
  TreeDragSource ds;
  TreeDropTarget dt;
  JTree tree;
  public TreeDragTest() {
    super("Rearrangeable Tree");
    setSize(300, 200);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    // If you want autoscrolling, use this line:
    tree = new AutoScrollingJTree();
    // Otherwise, use this line:
    //tree = new JTree();
    getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
    // If we only support move operations...
    //ds = new TreeDragSource(tree, DnDConstants.ACTION_MOVE);
    ds = new TreeDragSource(tree, DnDConstants.ACTION_COPY_OR_MOVE);
    dt = new TreeDropTarget(tree);
    setVisible(true);
  }
  public class AutoScrollingJTree extends JTree implements Autoscroll {
    private int margin = 12;
    public AutoScrollingJTree() {
      super();
    }
    public void autoscroll(Point p) {
      int realrow = getRowForLocation(p.x, p.y);
      Rectangle outer = getBounds();
      realrow = (p.y + outer.y <= margin ? realrow < 1 ? 0 : realrow - 1
          : realrow < getRowCount() - 1 ? realrow + 1 : realrow);
      scrollRowToVisible(realrow);
    }
    public Insets getAutoscrollInsets() {
      Rectangle outer = getBounds();
      Rectangle inner = getParent().getBounds();
      return new Insets(inner.y - outer.y + margin, inner.x - outer.x
          + margin, outer.height - inner.height - inner.y + outer.y
          + margin, outer.width - inner.width - inner.x + outer.x
          + margin);
    }
    // Use this method if you want to see the boundaries of the
    // autoscroll active region
    public void paintComponent(Graphics g) {
      super.paintComponent(g);
      Rectangle outer = getBounds();
      Rectangle inner = getParent().getBounds();
      g.setColor(Color.red);
      g.drawRect(-outer.x + 12, -outer.y + 12, inner.width - 24,
          inner.height - 24);
    }
  }
  public static void main(String args[]) {
    new TreeDragTest();
  }
}
//TreeDragSource.java
//A drag source wrapper for a JTree. This class can be used to make
//a rearrangeable DnD tree with the TransferableTreeNode class as the
//transfer data type.
class TreeDragSource implements DragSourceListener, DragGestureListener {
  DragSource source;
  DragGestureRecognizer recognizer;
  TransferableTreeNode transferable;
  DefaultMutableTreeNode oldNode;
  JTree sourceTree;
  public TreeDragSource(JTree tree, int actions) {
    sourceTree = tree;
    source = new DragSource();
    recognizer = source.createDefaultDragGestureRecognizer(sourceTree,
        actions, this);
  }
  /*
   * Drag Gesture Handler
   */
  public void dragGestureRecognized(DragGestureEvent dge) {
    TreePath path = sourceTree.getSelectionPath();
    if ((path == null) || (path.getPathCount() <= 1)) {
      // We can"t move the root node or an empty selection
      return;
    }
    oldNode = (DefaultMutableTreeNode) path.getLastPathComponent();
    transferable = new TransferableTreeNode(path);
    source.startDrag(dge, DragSource.DefaultMoveNoDrop, transferable, this);
    // If you support dropping the node anywhere, you should probably
    // start with a valid move cursor:
    //source.startDrag(dge, DragSource.DefaultMoveDrop, transferable,
    // this);
  }
  /*
   * Drag Event Handlers
   */
  public void dragEnter(DragSourceDragEvent dsde) {
  }
  public void dragExit(DragSourceEvent dse) {
  }
  public void dragOver(DragSourceDragEvent dsde) {
  }
  public void dropActionChanged(DragSourceDragEvent dsde) {
    System.out.println("Action: " + dsde.getDropAction());
    System.out.println("Target Action: " + dsde.getTargetActions());
    System.out.println("User Action: " + dsde.getUserAction());
  }
  public void dragDropEnd(DragSourceDropEvent dsde) {
    /*
     * to support move or copy, we have to check which occurred:
     */
    System.out.println("Drop Action: " + dsde.getDropAction());
    if (dsde.getDropSuccess()
        && (dsde.getDropAction() == DnDConstants.ACTION_MOVE)) {
      ((DefaultTreeModel) sourceTree.getModel())
          .removeNodeFromParent(oldNode);
    }
    /*
     * to support move only... if (dsde.getDropSuccess()) {
     * ((DefaultTreeModel)sourceTree.getModel()).removeNodeFromParent(oldNode); }
     */
  }
}
//TreeDropTarget.java
//A quick DropTarget that"s looking for drops from draggable JTrees.
//
class TreeDropTarget implements DropTargetListener {
  DropTarget target;
  JTree targetTree;
  public TreeDropTarget(JTree tree) {
    targetTree = tree;
    target = new DropTarget(targetTree, this);
  }
  /*
   * Drop Event Handlers
   */
  private TreeNode getNodeForEvent(DropTargetDragEvent dtde) {
    Point p = dtde.getLocation();
    DropTargetContext dtc = dtde.getDropTargetContext();
    JTree tree = (JTree) dtc.getComponent();
    TreePath path = tree.getClosestPathForLocation(p.x, p.y);
    return (TreeNode) path.getLastPathComponent();
  }
  public void dragEnter(DropTargetDragEvent dtde) {
    TreeNode node = getNodeForEvent(dtde);
    if (node.isLeaf()) {
      dtde.rejectDrag();
    } else {
      // start by supporting move operations
      //dtde.acceptDrag(DnDConstants.ACTION_MOVE);
      dtde.acceptDrag(dtde.getDropAction());
    }
  }
  public void dragOver(DropTargetDragEvent dtde) {
    TreeNode node = getNodeForEvent(dtde);
    if (node.isLeaf()) {
      dtde.rejectDrag();
    } else {
      // start by supporting move operations
      //dtde.acceptDrag(DnDConstants.ACTION_MOVE);
      dtde.acceptDrag(dtde.getDropAction());
    }
  }
  public void dragExit(DropTargetEvent dte) {
  }
  public void dropActionChanged(DropTargetDragEvent dtde) {
  }
  public void drop(DropTargetDropEvent dtde) {
    Point pt = dtde.getLocation();
    DropTargetContext dtc = dtde.getDropTargetContext();
    JTree tree = (JTree) dtc.getComponent();
    TreePath parentpath = tree.getClosestPathForLocation(pt.x, pt.y);
    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) parentpath
        .getLastPathComponent();
    if (parent.isLeaf()) {
      dtde.rejectDrop();
      return;
    }
    try {
      Transferable tr = dtde.getTransferable();
      DataFlavor[] flavors = tr.getTransferDataFlavors();
      for (int i = 0; i < flavors.length; i++) {
        if (tr.isDataFlavorSupported(flavors[i])) {
          dtde.acceptDrop(dtde.getDropAction());
          TreePath p = (TreePath) tr.getTransferData(flavors[i]);
          DefaultMutableTreeNode node = (DefaultMutableTreeNode) p
              .getLastPathComponent();
          DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
          model.insertNodeInto(node, parent, 0);
          dtde.dropComplete(true);
          return;
        }
      }
      dtde.rejectDrop();
    } catch (Exception e) {
      e.printStackTrace();
      dtde.rejectDrop();
    }
  }
}
//TransferableTreeNode.java
//A Transferable TreePath to be used with Drag & Drop applications.
//
class TransferableTreeNode implements Transferable {
  public static DataFlavor TREE_PATH_FLAVOR = new DataFlavor(TreePath.class,
      "Tree Path");
  DataFlavor flavors[] = { TREE_PATH_FLAVOR };
  TreePath path;
  public TransferableTreeNode(TreePath tp) {
    path = tp;
  }
  public synchronized DataFlavor[] getTransferDataFlavors() {
    return flavors;
  }
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    return (flavor.getRepresentationClass() == TreePath.class);
  }
  public synchronized Object getTransferData(DataFlavor flavor)
      throws UnsupportedFlavorException, IOException {
    if (isDataFlavorSupported(flavor)) {
      return (Object) path;
    } else {
      throw new UnsupportedFlavorException(flavor);
    }
  }
}





Drag and drop of a group of files into a tree

  
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class MyTree extends JTree {
  public MyTree() {
    super();
    setDragEnabled(false);
    setTransferHandler(new FSTransfer());
  }
}
class FSTransfer extends TransferHandler {
  public boolean importData(JComponent comp, Transferable t) {
    if (!(comp instanceof MyTree)) {
      return false;
    }
    if (!t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
      return false;
    }
    MyTree tree = (MyTree) comp;
    DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
    DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
    try {
      List data = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
      Iterator i = data.iterator();
      while (i.hasNext()) {
        File f = (File) i.next();
        root.add(new DefaultMutableTreeNode(f.getName()));
      }
      model.reload();
      return true;
    } catch (Exception ioe) {
      System.out.println(ioe);
    }
    return false;
  }
  public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
    if (comp instanceof MyTree) {
      for (int i = 0; i < transferFlavors.length; i++) {
        if (!transferFlavors[i].equals(DataFlavor.javaFileListFlavor)) {
          return false;
        }
      }
      return true;
    }
    return false;
  }
}





Enabling and Disabling Multiple Selections in a JTree Component

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreeSelectionModel;
public class TreeSelectionOption {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Expand All for a tree path

 
/*
 *  soapUI, copyright (C) 2004-2009 eviware.ru 
 *
 *  soapUI is free software; you can redistribute it and/or modify it under the 
 *  terms of version 2.1 of the GNU Lesser General Public License as published by 
 *  the Free Software Foundation.
 *
 *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 *  See the GNU Lesser General Public License for more details at gnu.org.
 */
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class TreeUtils {
  public static void expandAll(JTree tree, TreePath parent, boolean expand) {
    // Traverse children
    TreeNode node = (TreeNode) parent.getLastPathComponent();
    if (node.getChildCount() >= 0) {
      for (Enumeration e = node.children(); e.hasMoreElements();) {
        TreeNode n = (TreeNode) e.nextElement();
        TreePath path = parent.pathByAddingChild(n);
        expandAll(tree, path, expand);
      }
    }
    // Expansion or collapse must be done bottom-up
    if (expand) {
      tree.expandPath(parent);
    } else {
      tree.collapsePath(parent);
    }
  }
}





Expanding or Collapsing All Nodes in a JTree Component

  

import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
  public void expandAll(JTree tree) {
    TreeNode root = (TreeNode) tree.getModel().getRoot();
    expandAll(tree, new TreePath(root));
  }
  private void expandAll(JTree tree, TreePath parent) {
    TreeNode node = (TreeNode) parent.getLastPathComponent();
    if (node.getChildCount() >= 0) {
      for (Enumeration e = node.children(); e.hasMoreElements();) {
        TreeNode n = (TreeNode) e.nextElement();
        TreePath path = parent.pathByAddingChild(n);
        expandAll(tree, path);
      }
    }
    tree.expandPath(parent);
    // tree.collapsePath(parent);
  }
}





Expansion and Collapse Events in a JTree are fired before a node is expanded or collapsed can be vetoed, thereby preventing the operation.

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
public class Main {
  public static void main() {
    JTree tree = new JTree();
    tree.addTreeWillExpandListener(new MyTreeWillExpandListener());
    tree.addTreeExpansionListener(new MyTreeExpansionListener());
    JFrame f = new JFrame();
    f.add(new JScrollPane(tree));
    f.setSize(300, 300);
    f.setVisible(true);
  }
}
class MyTreeWillExpandListener implements TreeWillExpandListener {
  public void treeWillExpand(TreeExpansionEvent evt) throws ExpandVetoException {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    boolean veto = false;
    if (veto) {
      throw new ExpandVetoException(evt);
    }
  }
  public void treeWillCollapse(TreeExpansionEvent evt) throws ExpandVetoException {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    boolean veto = false;
    if (veto) {
      throw new ExpandVetoException(evt);
    }
  }
}
class MyTreeExpansionListener implements TreeExpansionListener {
  public void treeExpanded(TreeExpansionEvent evt) {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    System.out.println("treeExpanded");
  }
  public void treeCollapsed(TreeExpansionEvent evt) {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    System.out.println("treeCollapsed");
  }
}





File folder Tree with icons

  
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class FileTree1 
  extends JFrame 
{
  public static final ImageIcon ICON_COMPUTER = 
    new ImageIcon("computer.gif");
  public static final ImageIcon ICON_DISK = 
    new ImageIcon("disk.gif");
  public static final ImageIcon ICON_FOLDER = 
    new ImageIcon("folder.gif");
  public static final ImageIcon ICON_EXPANDEDFOLDER = 
    new ImageIcon("expandedfolder.gif");
  protected JTree  m_tree;
  protected DefaultTreeModel m_model;
  protected JTextField m_display;
  public FileTree1()
  {
    super("Directories Tree");
    setSize(400, 300);
    DefaultMutableTreeNode top = new DefaultMutableTreeNode(
      new IconData(ICON_COMPUTER, null, "Computer"));
    DefaultMutableTreeNode node;
    File[] roots = File.listRoots();
    for (int k=0; k<roots.length; k++)
    {
      node = new DefaultMutableTreeNode(new IconData(ICON_DISK, 
        null, new FileNode(roots[k])));
      top.add(node);
                        node.add( new DefaultMutableTreeNode(new Boolean(true)));
    }
    m_model = new DefaultTreeModel(top);
    m_tree = new JTree(m_model);
                m_tree.putClientProperty("JTree.lineStyle", "Angled");
    TreeCellRenderer renderer = new 
      IconCellRenderer();
    m_tree.setCellRenderer(renderer);
    m_tree.addTreeExpansionListener(new 
      DirExpansionListener());
    m_tree.addTreeSelectionListener(new 
      DirSelectionListener());
    m_tree.getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION); 
    m_tree.setShowsRootHandles(true); 
    m_tree.setEditable(false);
    JScrollPane s = new JScrollPane();
    s.getViewport().add(m_tree);
    getContentPane().add(s, BorderLayout.CENTER);
    m_display = new JTextField();
    m_display.setEditable(false);
    getContentPane().add(m_display, BorderLayout.NORTH);
    WindowListener wndCloser = new WindowAdapter()
    {
      public void windowClosing(WindowEvent e) 
      {
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);
    
    setVisible(true);
  }
  DefaultMutableTreeNode getTreeNode(TreePath path)
  {
    return (DefaultMutableTreeNode)(path.getLastPathComponent());
  }
  FileNode getFileNode(DefaultMutableTreeNode node)
  {
    if (node == null)
      return null;
    Object obj = node.getUserObject();
    if (obj instanceof IconData)
      obj = ((IconData)obj).getObject();
    if (obj instanceof FileNode)
      return (FileNode)obj;
    else
      return null;
  }
    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener
    {
        public void treeExpanded(TreeExpansionEvent event)
        {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);
            Thread runner = new Thread() 
            {
              public void run() 
              {
                if (fnode != null && fnode.expand(node)) 
                {
                  Runnable runnable = new Runnable() 
                  {
                    public void run() 
                    {
                       m_model.reload(node);
                    }
                  };
                  SwingUtilities.invokeLater(runnable);
                }
              }
            };
            runner.start();
        }
        public void treeCollapsed(TreeExpansionEvent event) {}
    }

  class DirSelectionListener 
    implements TreeSelectionListener 
  {
    public void valueChanged(TreeSelectionEvent event)
    {
      DefaultMutableTreeNode node = getTreeNode(
        event.getPath());
      FileNode fnode = getFileNode(node);
      if (fnode != null)
        m_display.setText(fnode.getFile().
          getAbsolutePath());
      else
        m_display.setText("");
    }
  }
  public static void main(String argv[]) 
  {
    new FileTree1();
  }
}
class IconCellRenderer 
  extends    JLabel 
  implements TreeCellRenderer
{
  protected Color m_textSelectionColor;
  protected Color m_textNonSelectionColor;
  protected Color m_bkSelectionColor;
  protected Color m_bkNonSelectionColor;
  protected Color m_borderSelectionColor;
  protected boolean m_selected;
  public IconCellRenderer()
  {
    super();
    m_textSelectionColor = UIManager.getColor(
      "Tree.selectionForeground");
    m_textNonSelectionColor = UIManager.getColor(
      "Tree.textForeground");
    m_bkSelectionColor = UIManager.getColor(
      "Tree.selectionBackground");
    m_bkNonSelectionColor = UIManager.getColor(
      "Tree.textBackground");
    m_borderSelectionColor = UIManager.getColor(
      "Tree.selectionBorderColor");
    setOpaque(false);
  }
  public Component getTreeCellRendererComponent(JTree tree, 
    Object value, boolean sel, boolean expanded, boolean leaf, 
    int row, boolean hasFocus) 
    
  {
    DefaultMutableTreeNode node = 
      (DefaultMutableTreeNode)value;
    Object obj = node.getUserObject();
    setText(obj.toString());
                if (obj instanceof Boolean)
                  setText("Retrieving data...");
    if (obj instanceof IconData)
    {
      IconData idata = (IconData)obj;
      if (expanded)
        setIcon(idata.getExpandedIcon());
      else
        setIcon(idata.getIcon());
    }
    else
      setIcon(null);
    setFont(tree.getFont());
    setForeground(sel ? m_textSelectionColor : 
      m_textNonSelectionColor);
    setBackground(sel ? m_bkSelectionColor : 
      m_bkNonSelectionColor);
    m_selected = sel;
    return this;
  }
    
  public void paintComponent(Graphics g) 
  {
    Color bColor = getBackground();
    Icon icon = getIcon();
    g.setColor(bColor);
    int offset = 0;
    if(icon != null && getText() != null) 
      offset = (icon.getIconWidth() + getIconTextGap());
    g.fillRect(offset, 0, getWidth() - 1 - offset,
      getHeight() - 1);
    
    if (m_selected) 
    {
      g.setColor(m_borderSelectionColor);
      g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
    }
    super.paintComponent(g);
    }
}
class IconData
{
  protected Icon   m_icon;
  protected Icon   m_expandedIcon;
  protected Object m_data;
  public IconData(Icon icon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = null;
    m_data = data;
  }
  public IconData(Icon icon, Icon expandedIcon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = expandedIcon;
    m_data = data;
  }
  public Icon getIcon() 
  { 
    return m_icon;
  }
  public Icon getExpandedIcon() 
  { 
    return m_expandedIcon!=null ? m_expandedIcon : m_icon;
  }
  public Object getObject() 
  { 
    return m_data;
  }
  public String toString() 
  { 
    return m_data.toString();
  }
}
class FileNode
{
  protected File m_file;
  public FileNode(File file)
  {
    m_file = file;
  }
  public File getFile() 
  { 
    return m_file;
  }
  public String toString() 
  { 
    return m_file.getName().length() > 0 ? m_file.getName() : 
      m_file.getPath();
  }
  public boolean expand(DefaultMutableTreeNode parent)
  {
    DefaultMutableTreeNode flag = 
      (DefaultMutableTreeNode)parent.getFirstChild();
    if (flag==null)    // No flag
      return false;
    Object obj = flag.getUserObject();
    if (!(obj instanceof Boolean))
      return false;      // Already expanded
    parent.removeAllChildren();  // Remove Flag
    File[] files = listFiles();
    if (files == null)
      return true;
    Vector v = new Vector();
    for (int k=0; k<files.length; k++)
    {
      File f = files[k];
      if (!(f.isDirectory()))
        continue;
      FileNode newNode = new FileNode(f);
      
      boolean isAdded = false;
      for (int i=0; i<v.size(); i++)
      {
        FileNode nd = (FileNode)v.elementAt(i);
        if (newNode.rupareTo(nd) < 0)
        {
          v.insertElementAt(newNode, i);
          isAdded = true;
          break;
        }
      }
      if (!isAdded)
        v.addElement(newNode);
    }
    for (int i=0; i<v.size(); i++)
    {
      FileNode nd = (FileNode)v.elementAt(i);
      IconData idata = new IconData(FileTree1.ICON_FOLDER, 
        FileTree1.ICON_EXPANDEDFOLDER, nd);
      DefaultMutableTreeNode node = new 
        DefaultMutableTreeNode(idata);
      parent.add(node);
        
      if (nd.hasSubDirs())
        node.add(new DefaultMutableTreeNode( 
          new Boolean(true) ));
    }
    return true;
  }
  public boolean hasSubDirs()
  {
    File[] files = listFiles();
    if (files == null)
      return false;
    for (int k=0; k<files.length; k++)
    {
      if (files[k].isDirectory())
        return true;
    }
    return false;
  }
  
  public int compareTo(FileNode toCompare)
  { 
    return  m_file.getName().rupareToIgnoreCase(
      toCompare.m_file.getName() ); 
  }
  protected File[] listFiles()
  {
    if (!m_file.isDirectory())
      return null;
    try
    {
      return m_file.listFiles();
    }
    catch (Exception ex)
    {
      JOptionPane.showMessageDialog(null, 
        "Error reading directory "+m_file.getAbsolutePath(),
        "Warning", JOptionPane.WARNING_MESSAGE);
      return null;
    }
  }
}





File System Tree

  
import java.io.File;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
public class FileTreeFrame extends JFrame {
  private JTree fileTree;
  private FileSystemModel fileSystemModel;
  private JTextArea fileDetailsTextArea = new JTextArea();
  public FileTreeFrame(String directory) {
    super("JTree FileSystem Viewer");
    fileDetailsTextArea.setEditable(false);
    fileSystemModel = new FileSystemModel(new File(directory));
    fileTree = new JTree(fileSystemModel);
    fileTree.setEditable(true);
    fileTree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent event) {
        File file = (File) fileTree.getLastSelectedPathComponent();
        fileDetailsTextArea.setText(getFileDetails(file));
      }
    });
    JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(
        fileTree), new JScrollPane(fileDetailsTextArea));
    getContentPane().add(splitPane);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(640, 480);
    setVisible(true);
  }
  private String getFileDetails(File file) {
    if (file == null)
      return "";
    StringBuffer buffer = new StringBuffer();
    buffer.append("Name: " + file.getName() + "\n");
    buffer.append("Path: " + file.getPath() + "\n");
    buffer.append("Size: " + file.length() + "\n");
    return buffer.toString();
  }
  public static void main(String args[]) {
    new FileTreeFrame("c:\\");
  }
}
class FileSystemModel implements TreeModel {
  private File root;
  private Vector listeners = new Vector();
  public FileSystemModel(File rootDirectory) {
    root = rootDirectory;
  }
  public Object getRoot() {
    return root;
  }
  public Object getChild(Object parent, int index) {
    File directory = (File) parent;
    String[] children = directory.list();
    return new TreeFile(directory, children[index]);
  }
  public int getChildCount(Object parent) {
    File file = (File) parent;
    if (file.isDirectory()) {
      String[] fileList = file.list();
      if (fileList != null)
        return file.list().length;
    }
    return 0;
  }
  public boolean isLeaf(Object node) {
    File file = (File) node;
    return file.isFile();
  }
  public int getIndexOfChild(Object parent, Object child) {
    File directory = (File) parent;
    File file = (File) child;
    String[] children = directory.list();
    for (int i = 0; i < children.length; i++) {
      if (file.getName().equals(children[i])) {
        return i;
      }
    }
    return -1;
  }
  public void valueForPathChanged(TreePath path, Object value) {
    File oldFile = (File) path.getLastPathComponent();
    String fileParentPath = oldFile.getParent();
    String newFileName = (String) value;
    File targetFile = new File(fileParentPath, newFileName);
    oldFile.renameTo(targetFile);
    File parent = new File(fileParentPath);
    int[] changedChildrenIndices = { getIndexOfChild(parent, targetFile) };
    Object[] changedChildren = { targetFile };
    fireTreeNodesChanged(path.getParentPath(), changedChildrenIndices, changedChildren);
  }
  private void fireTreeNodesChanged(TreePath parentPath, int[] indices, Object[] children) {
    TreeModelEvent event = new TreeModelEvent(this, parentPath, indices, children);
    Iterator iterator = listeners.iterator();
    TreeModelListener listener = null;
    while (iterator.hasNext()) {
      listener = (TreeModelListener) iterator.next();
      listener.treeNodesChanged(event);
    }
  }
  public void addTreeModelListener(TreeModelListener listener) {
    listeners.add(listener);
  }
  public void removeTreeModelListener(TreeModelListener listener) {
    listeners.remove(listener);
  }
  private class TreeFile extends File {
    public TreeFile(File parent, String child) {
      super(parent, child);
    }
    public String toString() {
      return getName();
    }
  }
}





File Tree with Popup Menu

  
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class FileTree2 
  extends JFrame 
{
  public static final ImageIcon ICON_COMPUTER = 
    new ImageIcon("computer.gif");
  public static final ImageIcon ICON_DISK = 
    new ImageIcon("disk.gif");
  public static final ImageIcon ICON_FOLDER = 
    new ImageIcon("folder.gif");
  public static final ImageIcon ICON_EXPANDEDFOLDER = 
    new ImageIcon("expandedfolder.gif");
  protected JTree  m_tree;
  protected DefaultTreeModel m_model;
  protected JTextField m_display;
// NEW
  protected JPopupMenu m_popup;
  protected Action m_action;
  protected TreePath m_clickedPath;
  public FileTree2()
  {
    super("Directories Tree [Popup Menus]");
    setSize(400, 300);
    DefaultMutableTreeNode top = new DefaultMutableTreeNode(
      new IconData(ICON_COMPUTER, null, "Computer"));
    DefaultMutableTreeNode node;
    File[] roots = File.listRoots();
    for (int k=0; k<roots.length; k++)
    {
      node = new DefaultMutableTreeNode(new IconData(ICON_DISK, 
        null, new FileNode(roots[k])));
      top.add(node);
      node.add(new DefaultMutableTreeNode( new Boolean(true) ));
    }
    m_model = new DefaultTreeModel(top);
    m_tree = new JTree(m_model);
                m_tree.putClientProperty("JTree.lineStyle", "Angled");
    TreeCellRenderer renderer = new 
      IconCellRenderer();
    m_tree.setCellRenderer(renderer);
    m_tree.addTreeExpansionListener(new 
      DirExpansionListener());
    m_tree.addTreeSelectionListener(new 
      DirSelectionListener());
    m_tree.getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION); 
    m_tree.setShowsRootHandles(true); 
    m_tree.setEditable(false);
    JScrollPane s = new JScrollPane();
    s.getViewport().add(m_tree);
    getContentPane().add(s, BorderLayout.CENTER);
    m_display = new JTextField();
    m_display.setEditable(false);
    getContentPane().add(m_display, BorderLayout.NORTH);
// NEW
    m_popup = new JPopupMenu();
    m_action = new AbstractAction() 
    { 
      public void actionPerformed(ActionEvent e)
      {
        if (m_clickedPath==null)
          return;
        if (m_tree.isExpanded(m_clickedPath))
          m_tree.collapsePath(m_clickedPath);
        else
          m_tree.expandPath(m_clickedPath);
      }
    };
    m_popup.add(m_action);
    m_popup.addSeparator();
    Action a1 = new AbstractAction("Delete") 
    { 
      public void actionPerformed(ActionEvent e)
      {
                                m_tree.repaint();
        JOptionPane.showMessageDialog(FileTree2.this, 
          "Delete option is not implemented",
          "Info", JOptionPane.INFORMATION_MESSAGE);
      }
    };
    m_popup.add(a1);
    Action a2 = new AbstractAction("Rename") 
    { 
      public void actionPerformed(ActionEvent e)
      {
                                m_tree.repaint();
        JOptionPane.showMessageDialog(FileTree2.this, 
          "Rename option is not implemented",
          "Info", JOptionPane.INFORMATION_MESSAGE);
      }
    };
    m_popup.add(a2);
    m_tree.add(m_popup);
    m_tree.addMouseListener(new PopupTrigger());
    WindowListener wndCloser = new WindowAdapter()
    {
      public void windowClosing(WindowEvent e) 
      {
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);
    
    setVisible(true);
  }
  DefaultMutableTreeNode getTreeNode(TreePath path)
  {
    return (DefaultMutableTreeNode)(path.getLastPathComponent());
  }
  FileNode getFileNode(DefaultMutableTreeNode node)
  {
    if (node == null)
      return null;
    Object obj = node.getUserObject();
    if (obj instanceof IconData)
      obj = ((IconData)obj).getObject();
    if (obj instanceof FileNode)
      return (FileNode)obj;
    else
      return null;
  }
// NEW
  class PopupTrigger extends MouseAdapter
  {
    public void mouseReleased(MouseEvent e)
    {
      if (e.isPopupTrigger())
      {
        int x = e.getX();
        int y = e.getY();
        TreePath path = m_tree.getPathForLocation(x, y);
        if (path != null)
        {
          if (m_tree.isExpanded(path))
            m_action.putValue(Action.NAME, "Collapse");
          else
            m_action.putValue(Action.NAME, "Expand");
          m_popup.show(m_tree, x, y);
          m_clickedPath = path;
        }
      }
    }
  }
    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener
    {
        public void treeExpanded(TreeExpansionEvent event)
        {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);
            Thread runner = new Thread() 
            {
              public void run() 
              {
                if (fnode != null && fnode.expand(node)) 
                {
                  Runnable runnable = new Runnable() 
                  {
                    public void run() 
                    {
                       m_model.reload(node);
                    }
                  };
                  SwingUtilities.invokeLater(runnable);
                }
              }
            };
            runner.start();
        }
        public void treeCollapsed(TreeExpansionEvent event) {}
    }
  class DirSelectionListener 
    implements TreeSelectionListener 
  {
    public void valueChanged(TreeSelectionEvent event)
    {
      DefaultMutableTreeNode node = getTreeNode(
        event.getPath());
      FileNode fnode = getFileNode(node);
      if (fnode != null)
        m_display.setText(fnode.getFile().
          getAbsolutePath());
      else
        m_display.setText("");
    }
  }
  public static void main(String argv[]) 
  {
    new FileTree2();
  }
}
class IconCellRenderer 
  extends    JLabel 
  implements TreeCellRenderer
{
  protected Color m_textSelectionColor;
  protected Color m_textNonSelectionColor;
  protected Color m_bkSelectionColor;
  protected Color m_bkNonSelectionColor;
  protected Color m_borderSelectionColor;
  protected boolean m_selected;
  public IconCellRenderer()
  {
    super();
    m_textSelectionColor = UIManager.getColor(
      "Tree.selectionForeground");
    m_textNonSelectionColor = UIManager.getColor(
      "Tree.textForeground");
    m_bkSelectionColor = UIManager.getColor(
      "Tree.selectionBackground");
    m_bkNonSelectionColor = UIManager.getColor(
      "Tree.textBackground");
    m_borderSelectionColor = UIManager.getColor(
      "Tree.selectionBorderColor");
    setOpaque(false);
  }
  public Component getTreeCellRendererComponent(JTree tree, 
    Object value, boolean sel, boolean expanded, boolean leaf, 
    int row, boolean hasFocus) 
    
  {
    DefaultMutableTreeNode node = 
      (DefaultMutableTreeNode)value;
    Object obj = node.getUserObject();
    setText(obj.toString());
                if (obj instanceof Boolean)
                  setText("Retrieving data...");
    if (obj instanceof IconData)
    {
      IconData idata = (IconData)obj;
      if (expanded)
        setIcon(idata.getExpandedIcon());
      else
        setIcon(idata.getIcon());
    }
    else
      setIcon(null);
    setFont(tree.getFont());
    setForeground(sel ? m_textSelectionColor : 
      m_textNonSelectionColor);
    setBackground(sel ? m_bkSelectionColor : 
      m_bkNonSelectionColor);
    m_selected = sel;
    return this;
  }
    
  public void paintComponent(Graphics g) 
  {
    Color bColor = getBackground();
    Icon icon = getIcon();
    g.setColor(bColor);
    int offset = 0;
    if(icon != null && getText() != null) 
      offset = (icon.getIconWidth() + getIconTextGap());
    g.fillRect(offset, 0, getWidth() - 1 - offset,
      getHeight() - 1);
    
    if (m_selected) 
    {
      g.setColor(m_borderSelectionColor);
      g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
    }
    super.paintComponent(g);
    }
}
class IconData
{
  protected Icon   m_icon;
  protected Icon   m_expandedIcon;
  protected Object m_data;
  public IconData(Icon icon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = null;
    m_data = data;
  }
  public IconData(Icon icon, Icon expandedIcon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = expandedIcon;
    m_data = data;
  }
  public Icon getIcon() 
  { 
    return m_icon;
  }
  public Icon getExpandedIcon() 
  { 
    return m_expandedIcon!=null ? m_expandedIcon : m_icon;
  }
  public Object getObject() 
  { 
    return m_data;
  }
  public String toString() 
  { 
    return m_data.toString();
  }
}
class FileNode
{
  protected File m_file;
  public FileNode(File file)
  {
    m_file = file;
  }
  public File getFile() 
  { 
    return m_file;
  }
  public String toString() 
  { 
    return m_file.getName().length() > 0 ? m_file.getName() : 
      m_file.getPath();
  }
  public boolean expand(DefaultMutableTreeNode parent)
  {
    DefaultMutableTreeNode flag = 
      (DefaultMutableTreeNode)parent.getFirstChild();
    if (flag==null)    // No flag
      return false;
    Object obj = flag.getUserObject();
    if (!(obj instanceof Boolean))
      return false;      // Already expanded
    parent.removeAllChildren();  // Remove Flag
    File[] files = listFiles();
    if (files == null)
      return true;
    Vector v = new Vector();
    for (int k=0; k<files.length; k++)
    {
      File f = files[k];
      if (!(f.isDirectory()))
        continue;
      FileNode newNode = new FileNode(f);
      
      boolean isAdded = false;
      for (int i=0; i<v.size(); i++)
      {
        FileNode nd = (FileNode)v.elementAt(i);
        if (newNode.rupareTo(nd) < 0)
        {
          v.insertElementAt(newNode, i);
          isAdded = true;
          break;
        }
      }
      if (!isAdded)
        v.addElement(newNode);
    }
    for (int i=0; i<v.size(); i++)
    {
      FileNode nd = (FileNode)v.elementAt(i);
      IconData idata = new IconData(FileTree2.ICON_FOLDER, 
        FileTree2.ICON_EXPANDEDFOLDER, nd);
      DefaultMutableTreeNode node = new 
        DefaultMutableTreeNode(idata);
      parent.add(node);
        
      if (nd.hasSubDirs())
        node.add(new DefaultMutableTreeNode( 
          new Boolean(true) ));
    }
    return true;
  }
  public boolean hasSubDirs()
  {
    File[] files = listFiles();
    if (files == null)
      return false;
    for (int k=0; k<files.length; k++)
    {
      if (files[k].isDirectory())
        return true;
    }
    return false;
  }
  
  public int compareTo(FileNode toCompare)
  { 
    return  m_file.getName().rupareToIgnoreCase(
      toCompare.m_file.getName() ); 
  }
  protected File[] listFiles()
  {
    if (!m_file.isDirectory())
      return null;
    try
    {
      return m_file.listFiles();
    }
    catch (Exception ex)
    {
      JOptionPane.showMessageDialog(null, 
        "Error reading directory "+m_file.getAbsolutePath(),
        "Warning", JOptionPane.WARNING_MESSAGE);
      return null;
    }
  }
}





File Tree with Tooltips

  
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class FileTree3 
  extends JFrame 
{
  public static final ImageIcon ICON_COMPUTER = 
    new ImageIcon("computer.gif");
  public static final ImageIcon ICON_DISK = 
    new ImageIcon("disk.gif");
  public static final ImageIcon ICON_FOLDER = 
    new ImageIcon("folder.gif");
  public static final ImageIcon ICON_EXPANDEDFOLDER = 
    new ImageIcon("expandedfolder.gif");
  protected JTree  m_tree;
  protected DefaultTreeModel m_model;
  protected JTextField m_display;
  protected JPopupMenu m_popup;
  protected Action m_action;
  protected TreePath m_clickedPath;
  public FileTree3()
  {
    super("Directories Tree [Tool Tips]");
    setSize(400, 300);
    DefaultMutableTreeNode top = new DefaultMutableTreeNode(
      new IconData(ICON_COMPUTER, null, "Computer"));
    DefaultMutableTreeNode node;
    File[] roots = File.listRoots();
    for (int k=0; k<roots.length; k++)
    {
      node = new DefaultMutableTreeNode(new IconData(ICON_DISK, 
        null, new FileNode(roots[k])));
      top.add(node);
      node.add(new DefaultMutableTreeNode( new Boolean(true) ));
    }
    m_model = new DefaultTreeModel(top);
// NEW
    m_tree = new JTree(m_model)
    {
      public String getToolTipText(MouseEvent ev) 
      {
        if(ev == null)
          return null;
        TreePath path = m_tree.getPathForLocation(ev.getX(), 
          ev.getY());
        if (path != null)
        {
          FileNode fnode = getFileNode(getTreeNode(path));
          if (fnode==null)
            return null;
          File f = fnode.getFile();
          return (f==null ? null : f.getPath());
        }
        return null;
      }
    };
    ToolTipManager.sharedInstance().registerComponent(m_tree);
                m_tree.putClientProperty("JTree.lineStyle", "Angled");
    TreeCellRenderer renderer = new 
      IconCellRenderer();
    m_tree.setCellRenderer(renderer);
    m_tree.addTreeExpansionListener(new 
      DirExpansionListener());
    m_tree.addTreeSelectionListener(new 
      DirSelectionListener());
    m_tree.getSelectionModel().setSelectionMode(
      TreeSelectionModel.SINGLE_TREE_SELECTION); 
    m_tree.setShowsRootHandles(true); 
    m_tree.setEditable(false);
    JScrollPane s = new JScrollPane();
    s.getViewport().add(m_tree);
    getContentPane().add(s, BorderLayout.CENTER);
    m_display = new JTextField();
    m_display.setEditable(false);
    getContentPane().add(m_display, BorderLayout.NORTH);
    m_popup = new JPopupMenu();
    m_action = new AbstractAction() 
    { 
      public void actionPerformed(ActionEvent e)
      {
        if (m_clickedPath==null)
          return;
        if (m_tree.isExpanded(m_clickedPath))
          m_tree.collapsePath(m_clickedPath);
        else
          m_tree.expandPath(m_clickedPath);
      }
    };
    m_popup.add(m_action);
    m_popup.addSeparator();
    Action a1 = new AbstractAction("Delete") 
    { 
      public void actionPerformed(ActionEvent e)
      {
                                m_tree.repaint();
        JOptionPane.showMessageDialog(FileTree3.this, 
          "Delete option is not implemented",
          "Info", JOptionPane.INFORMATION_MESSAGE);
      }
    };
    m_popup.add(a1);
    Action a2 = new AbstractAction("Rename") 
    { 
      public void actionPerformed(ActionEvent e)
      {
                                m_tree.repaint();
        JOptionPane.showMessageDialog(FileTree3.this, 
          "Rename option is not implemented",
          "Info", JOptionPane.INFORMATION_MESSAGE);
      }
    };
    m_popup.add(a2);
    m_tree.add(m_popup);
    m_tree.addMouseListener(new PopupTrigger());
    WindowListener wndCloser = new WindowAdapter()
    {
      public void windowClosing(WindowEvent e) 
      {
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);
    
    setVisible(true);
  }
  DefaultMutableTreeNode getTreeNode(TreePath path)
  {
    return (DefaultMutableTreeNode)(path.getLastPathComponent());
  }
  FileNode getFileNode(DefaultMutableTreeNode node)
  {
    if (node == null)
      return null;
    Object obj = node.getUserObject();
    if (obj instanceof IconData)
      obj = ((IconData)obj).getObject();
    if (obj instanceof FileNode)
      return (FileNode)obj;
    else
      return null;
  }
  class PopupTrigger extends MouseAdapter
  {
    public void mouseReleased(MouseEvent e)
    {
      if (e.isPopupTrigger())
      {
        int x = e.getX();
        int y = e.getY();
        TreePath path = m_tree.getPathForLocation(x, y);
        if (path != null)
        {
          if (m_tree.isExpanded(path))
            m_action.putValue(Action.NAME, "Collapse");
          else
            m_action.putValue(Action.NAME, "Expand");
          m_popup.show(m_tree, x, y);
          m_clickedPath = path;
        }
      }
    }
  }
    // Make sure expansion is threaded and updating the tree model
    // only occurs within the event dispatching thread.
    class DirExpansionListener implements TreeExpansionListener
    {
        public void treeExpanded(TreeExpansionEvent event)
        {
            final DefaultMutableTreeNode node = getTreeNode(
                event.getPath());
            final FileNode fnode = getFileNode(node);
            Thread runner = new Thread() 
            {
              public void run() 
              {
                if (fnode != null && fnode.expand(node)) 
                {
                  Runnable runnable = new Runnable() 
                  {
                    public void run() 
                    {
                       m_model.reload(node);
                    }
                  };
                  SwingUtilities.invokeLater(runnable);
                }
              }
            };
            runner.start();
        }
        public void treeCollapsed(TreeExpansionEvent event) {}
    }
  class DirSelectionListener 
    implements TreeSelectionListener 
  {
    public void valueChanged(TreeSelectionEvent event)
    {
      DefaultMutableTreeNode node = getTreeNode(
        event.getPath());
      FileNode fnode = getFileNode(node);
      if (fnode != null)
        m_display.setText(fnode.getFile().
          getAbsolutePath());
      else
        m_display.setText("");
    }
  }
  public static void main(String argv[]) 
  {
    new FileTree3();
  }
}
class IconCellRenderer 
  extends    JLabel 
  implements TreeCellRenderer
{
  protected Color m_textSelectionColor;
  protected Color m_textNonSelectionColor;
  protected Color m_bkSelectionColor;
  protected Color m_bkNonSelectionColor;
  protected Color m_borderSelectionColor;
  protected boolean m_selected;
  public IconCellRenderer()
  {
    super();
    m_textSelectionColor = UIManager.getColor(
      "Tree.selectionForeground");
    m_textNonSelectionColor = UIManager.getColor(
      "Tree.textForeground");
    m_bkSelectionColor = UIManager.getColor(
      "Tree.selectionBackground");
    m_bkNonSelectionColor = UIManager.getColor(
      "Tree.textBackground");
    m_borderSelectionColor = UIManager.getColor(
      "Tree.selectionBorderColor");
    setOpaque(false);
  }
  public Component getTreeCellRendererComponent(JTree tree, 
    Object value, boolean sel, boolean expanded, boolean leaf, 
    int row, boolean hasFocus) 
    
  {
    DefaultMutableTreeNode node = 
      (DefaultMutableTreeNode)value;
    Object obj = node.getUserObject();
    setText(obj.toString());
                if (obj instanceof Boolean)
                  setText("Retrieving data...");
    if (obj instanceof IconData)
    {
      IconData idata = (IconData)obj;
      if (expanded)
        setIcon(idata.getExpandedIcon());
      else
        setIcon(idata.getIcon());
    }
    else
      setIcon(null);
    setFont(tree.getFont());
    setForeground(sel ? m_textSelectionColor : 
      m_textNonSelectionColor);
    setBackground(sel ? m_bkSelectionColor : 
      m_bkNonSelectionColor);
    m_selected = sel;
    return this;
  }
    
  public void paintComponent(Graphics g) 
  {
    Color bColor = getBackground();
    Icon icon = getIcon();
    g.setColor(bColor);
    int offset = 0;
    if(icon != null && getText() != null) 
      offset = (icon.getIconWidth() + getIconTextGap());
    g.fillRect(offset, 0, getWidth() - 1 - offset,
      getHeight() - 1);
    
    if (m_selected) 
    {
      g.setColor(m_borderSelectionColor);
      g.drawRect(offset, 0, getWidth()-1-offset, getHeight()-1);
    }
    super.paintComponent(g);
    }
}
class IconData
{
  protected Icon   m_icon;
  protected Icon   m_expandedIcon;
  protected Object m_data;
  public IconData(Icon icon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = null;
    m_data = data;
  }
  public IconData(Icon icon, Icon expandedIcon, Object data)
  {
    m_icon = icon;
    m_expandedIcon = expandedIcon;
    m_data = data;
  }
  public Icon getIcon() 
  { 
    return m_icon;
  }
  public Icon getExpandedIcon() 
  { 
    return m_expandedIcon!=null ? m_expandedIcon : m_icon;
  }
  public Object getObject() 
  { 
    return m_data;
  }
  public String toString() 
  { 
    return m_data.toString();
  }
}
class FileNode
{
  protected File m_file;
  public FileNode(File file)
  {
    m_file = file;
  }
  public File getFile() 
  { 
    return m_file;
  }
  public String toString() 
  { 
    return m_file.getName().length() > 0 ? m_file.getName() : 
      m_file.getPath();
  }
  public boolean expand(DefaultMutableTreeNode parent)
  {
    DefaultMutableTreeNode flag = 
      (DefaultMutableTreeNode)parent.getFirstChild();
    if (flag==null)    // No flag
      return false;
    Object obj = flag.getUserObject();
    if (!(obj instanceof Boolean))
      return false;      // Already expanded
    parent.removeAllChildren();  // Remove Flag
    File[] files = listFiles();
    if (files == null)
      return true;
    Vector v = new Vector();
    for (int k=0; k<files.length; k++)
    {
      File f = files[k];
      if (!(f.isDirectory()))
        continue;
      FileNode newNode = new FileNode(f);
      
      boolean isAdded = false;
      for (int i=0; i<v.size(); i++)
      {
        FileNode nd = (FileNode)v.elementAt(i);
        if (newNode.rupareTo(nd) < 0)
        {
          v.insertElementAt(newNode, i);
          isAdded = true;
          break;
        }
      }
      if (!isAdded)
        v.addElement(newNode);
    }
    for (int i=0; i<v.size(); i++)
    {
      FileNode nd = (FileNode)v.elementAt(i);
      IconData idata = new IconData(FileTree3.ICON_FOLDER, 
        FileTree3.ICON_EXPANDEDFOLDER, nd);
      DefaultMutableTreeNode node = new 
        DefaultMutableTreeNode(idata);
      parent.add(node);
        
      if (nd.hasSubDirs())
        node.add(new DefaultMutableTreeNode( 
          new Boolean(true) ));
    }
    return true;
  }
  public boolean hasSubDirs()
  {
    File[] files = listFiles();
    if (files == null)
      return false;
    for (int k=0; k<files.length; k++)
    {
      if (files[k].isDirectory())
        return true;
    }
    return false;
  }
  
  public int compareTo(FileNode toCompare)
  { 
    return  m_file.getName().rupareToIgnoreCase(
      toCompare.m_file.getName() ); 
  }
  protected File[] listFiles()
  {
    if (!m_file.isDirectory())
      return null;
    try
    {
      return m_file.listFiles();
    }
    catch (Exception ex)
    {
      JOptionPane.showMessageDialog(null, 
        "Error reading directory "+m_file.getAbsolutePath(),
        "Warning", JOptionPane.WARNING_MESSAGE);
      return null;
    }
  }
}





Finding a Node in a JTree Component

  
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    // Search forward from first visible row looking for any visible node
    // whose name starts with prefix.
    int startRow = 0;
    String prefix = "b";
    TreePath path = tree.getNextMatch(prefix, startRow, Position.Bias.Forward);
    System.out.println(path);
  }
}





Find the path regardless of visibility that matches the specified sequence of names

  
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    TreePath path = findByName(tree, new String[] { "JTree", "A", "a" });
  }
  public static TreePath findByName(JTree tree, String[] names) {
    TreeNode root = (TreeNode) tree.getModel().getRoot();
    return find(tree, new TreePath(root), names, 0);
  }
  private static TreePath find(JTree tree, TreePath parent, Object[] nodes, int depth) {
    TreeNode node = (TreeNode) parent.getLastPathComponent();
    Object o = node;
    if (o.equals(nodes[depth])) {
      if (depth == nodes.length - 1) {
        return parent;
      }
      if (node.getChildCount() >= 0) {
        for (Enumeration e = node.children(); e.hasMoreElements();) {
          TreeNode n = (TreeNode) e.nextElement();
          TreePath path = parent.pathByAddingChild(n);
          TreePath result = find(tree, path, nodes, depth + 1);
          if (result != null) {
            return result;
          }
        }
      }
    }
    return null;
  }
}





Flush the internal cache of Row height

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeightCache {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    if (tree.getRowHeight() <= 0) {
      tree.setRowHeight(1);
    }
    tree.setRowHeight(0);
    JFrame frame = new JFrame("Image");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Genealogy Tree

  
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * A 1.4 example that uses the following files: GenealogyModel.java Person.java
 * 
 * Based on an example provided by tutorial reader Olivier Berlanger.
 */
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
public class GenealogyExample extends JPanel implements ActionListener {
  GenealogyTree tree;
  private static String SHOW_ANCESTOR_CMD = "showAncestor";
  public GenealogyExample() {
    super(new BorderLayout());
    //Construct the panel with the toggle buttons.
    JRadioButton showDescendant = new JRadioButton("Show descendants", true);
    final JRadioButton showAncestor = new JRadioButton("Show ancestors");
    ButtonGroup bGroup = new ButtonGroup();
    bGroup.add(showDescendant);
    bGroup.add(showAncestor);
    showDescendant.addActionListener(this);
    showAncestor.addActionListener(this);
    showAncestor.setActionCommand(SHOW_ANCESTOR_CMD);
    JPanel buttonPanel = new JPanel();
    buttonPanel.add(showDescendant);
    buttonPanel.add(showAncestor);
    //Construct the tree.
    tree = new GenealogyTree(getGenealogyGraph());
    JScrollPane scrollPane = new JScrollPane(tree);
    scrollPane.setPreferredSize(new Dimension(200, 200));
    //Add everything to this panel.
    add(buttonPanel, BorderLayout.PAGE_START);
    add(scrollPane, BorderLayout.CENTER);
  }
  /**
   * Required by the ActionListener interface. Handle events on the
   * showDescendant and showAncestore buttons.
   */
  public void actionPerformed(ActionEvent ae) {
    if (ae.getActionCommand() == SHOW_ANCESTOR_CMD) {
      tree.showAncestor(true);
    } else {
      tree.showAncestor(false);
    }
  }
  /**
   * Constructs the genealogy graph used by the model.
   */
  public Person getGenealogyGraph() {
    //the greatgrandparent generation
    Person a1 = new Person("Jack (great-granddaddy)");
    Person a2 = new Person("Jean (great-granny)");
    Person a3 = new Person("Albert (great-granddaddy)");
    Person a4 = new Person("Rae (great-granny)");
    Person a5 = new Person("Paul (great-granddaddy)");
    Person a6 = new Person("Josie (great-granny)");
    //the grandparent generation
    Person b1 = new Person("Peter (grandpa)");
    Person b2 = new Person("Zoe (grandma)");
    Person b3 = new Person("Simon (grandpa)");
    Person b4 = new Person("James (grandpa)");
    Person b5 = new Person("Bertha (grandma)");
    Person b6 = new Person("Veronica (grandma)");
    Person b7 = new Person("Anne (grandma)");
    Person b8 = new Person("Renee (grandma)");
    Person b9 = new Person("Joseph (grandpa)");
    //the parent generation
    Person c1 = new Person("Isabelle (mom)");
    Person c2 = new Person("Frank (dad)");
    Person c3 = new Person("Louis (dad)");
    Person c4 = new Person("Laurence (dad)");
    Person c5 = new Person("Valerie (mom)");
    Person c6 = new Person("Marie (mom)");
    Person c7 = new Person("Helen (mom)");
    Person c8 = new Person("Mark (dad)");
    Person c9 = new Person("Oliver (dad)");
    //the youngest generation
    Person d1 = new Person("Clement (boy)");
    Person d2 = new Person("Colin (boy)");
    Person.linkFamily(a1, a2, new Person[] { b1, b2, b3, b4 });
    Person.linkFamily(a3, a4, new Person[] { b5, b6, b7 });
    Person.linkFamily(a5, a6, new Person[] { b8, b9 });
    Person.linkFamily(b3, b6, new Person[] { c1, c2, c3 });
    Person.linkFamily(b4, b5, new Person[] { c4, c5, c6 });
    Person.linkFamily(b8, b7, new Person[] { c7, c8, c9 });
    Person.linkFamily(c4, c7, new Person[] { d1, d2 });
    return a1;
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("GenealogyExample");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    GenealogyExample newContentPane = new GenealogyExample();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}
class GenealogyModel implements TreeModel {
  private boolean showAncestors;
  private Vector treeModelListeners = new Vector();
  private Person rootPerson;
  public GenealogyModel(Person root) {
    showAncestors = false;
    rootPerson = root;
  }
  /**
   * Used to toggle between show ancestors/show descendant and to change the
   * root of the tree.
   */
  public void showAncestor(boolean b, Object newRoot) {
    showAncestors = b;
    Person oldRoot = rootPerson;
    if (newRoot != null) {
      rootPerson = (Person) newRoot;
    }
    fireTreeStructureChanged(oldRoot);
  }
  //////////////// Fire events //////////////////////////////////////////////
  /**
   * The only event raised by this model is TreeStructureChanged with the root
   * as path, i.e. the whole tree has changed.
   */
  protected void fireTreeStructureChanged(Person oldRoot) {
    int len = treeModelListeners.size();
    TreeModelEvent e = new TreeModelEvent(this, new Object[] { oldRoot });
    for (int i = 0; i < len; i++) {
      ((TreeModelListener) treeModelListeners.elementAt(i))
          .treeStructureChanged(e);
    }
  }
  //////////////// TreeModel interface implementation ///////////////////////
  /**
   * Adds a listener for the TreeModelEvent posted after the tree changes.
   */
  public void addTreeModelListener(TreeModelListener l) {
    treeModelListeners.addElement(l);
  }
  /**
   * Returns the child of parent at index index in the parent"s child array.
   */
  public Object getChild(Object parent, int index) {
    Person p = (Person) parent;
    if (showAncestors) {
      if ((index > 0) && (p.getFather() != null)) {
        return p.getMother();
      }
      return p.getFather();
    }
    return p.getChildAt(index);
  }
  /**
   * Returns the number of children of parent.
   */
  public int getChildCount(Object parent) {
    Person p = (Person) parent;
    if (showAncestors) {
      int count = 0;
      if (p.getFather() != null) {
        count++;
      }
      if (p.getMother() != null) {
        count++;
      }
      return count;
    }
    return p.getChildCount();
  }
  /**
   * Returns the index of child in parent.
   */
  public int getIndexOfChild(Object parent, Object child) {
    Person p = (Person) parent;
    if (showAncestors) {
      int count = 0;
      Person father = p.getFather();
      if (father != null) {
        count++;
        if (father == child) {
          return 0;
        }
      }
      if (p.getMother() != child) {
        return count;
      }
      return -1;
    }
    return p.getIndexOfChild((Person) child);
  }
  /**
   * Returns the root of the tree.
   */
  public Object getRoot() {
    return rootPerson;
  }
  /**
   * Returns true if node is a leaf.
   */
  public boolean isLeaf(Object node) {
    Person p = (Person) node;
    if (showAncestors) {
      return ((p.getFather() == null) && (p.getMother() == null));
    }
    return p.getChildCount() == 0;
  }
  /**
   * Removes a listener previously added with addTreeModelListener().
   */
  public void removeTreeModelListener(TreeModelListener l) {
    treeModelListeners.removeElement(l);
  }
  /**
   * Messaged when the user has altered the value for the item identified by
   * path to newValue. Not used by this model.
   */
  public void valueForPathChanged(TreePath path, Object newValue) {
    System.out.println("*** valueForPathChanged : " + path + " --> "
        + newValue);
  }
}
class Person {
  Person father;
  Person mother;
  Vector children;
  private String name;
  public Person(String name) {
    this.name = name;
    mother = father = null;
    children = new Vector();
  }
  /**
   * Link together all members of a family.
   * 
   * @param pa
   *            the father
   * @param ma
   *            the mother
   * @param kids
   *            the children
   */
  public static void linkFamily(Person pa, Person ma, Person[] kids) {
    int len = kids.length;
    Person kid = null;
    for (int i = 0; i < len; i++) {
      kid = kids[i];
      pa.children.addElement(kid);
      ma.children.addElement(kid);
      kid.father = pa;
      kid.mother = ma;
    }
  }
  /// getter methods ///////////////////////////////////
  public String toString() {
    return name;
  }
  public String getName() {
    return name;
  }
  public Person getFather() {
    return father;
  }
  public Person getMother() {
    return mother;
  }
  public int getChildCount() {
    return children.size();
  }
  public Person getChildAt(int i) {
    return (Person) children.elementAt(i);
  }
  public int getIndexOfChild(Person kid) {
    return children.indexOf(kid);
  }
}
class GenealogyTree extends JTree {
  GenealogyModel model;
  public GenealogyTree(Person graphNode) {
    super(new GenealogyModel(graphNode));
    getSelectionModel().setSelectionMode(
        TreeSelectionModel.SINGLE_TREE_SELECTION);
    DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
    Icon personIcon = null;
    renderer.setLeafIcon(personIcon);
    renderer.setClosedIcon(personIcon);
    renderer.setOpenIcon(personIcon);
    setCellRenderer(renderer);
  }
  /**
   * Get the selected item in the tree, and call showAncestor with this item
   * on the model.
   */
  public void showAncestor(boolean b) {
    Object newRoot = null;
    TreePath path = getSelectionModel().getSelectionPath();
    if (path != null) {
      newRoot = path.getLastPathComponent();
    }
    ((GenealogyModel) getModel()).showAncestor(b, newRoot);
  }
}





Get path for all expanded or not expanded tree pathes

  
import java.util.Enumeration;
import java.util.List;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
  public void getPaths(JTree tree, TreePath parent, boolean expanded, List<TreePath> list) {
    if (expanded && !tree.isVisible(parent)) {
      return;
    }
    list.add(parent);
    TreeNode node = (TreeNode) parent.getLastPathComponent();
    if (node.getChildCount() >= 0) {
      for (Enumeration e = node.children(); e.hasMoreElements();) {
        TreeNode n = (TreeNode) e.nextElement();
        TreePath path = parent.pathByAddingChild(n);
        getPaths(tree, path, expanded, list);
      }
    }
  }
}





Getting the Selected Nodes in a JTree Component

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    JFrame f = new JFrame();
    f.add(new JScrollPane(tree));
    f.setSize(300, 300);
    f.setVisible(true);
    // Get paths of all selected nodes
    TreePath[] paths = tree.getSelectionPaths();
  }
}





Get tree path from TreeNode

 
import java.util.ArrayList;
import java.util.List;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Utils {
  public static TreePath getPath(TreeNode treeNode) {
    List<Object> nodes = new ArrayList<Object>();
    if (treeNode != null) {
      nodes.add(treeNode);
      treeNode = treeNode.getParent();
      while (treeNode != null) {
        nodes.add(0, treeNode);
        treeNode = treeNode.getParent();
      }
    }
    return nodes.isEmpty() ? null : new TreePath(nodes.toArray());
  }
}





Have a popup attached to a JTree

  
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main extends JPanel {
  DefaultMutableTreeNode root = new DefaultMutableTreeNode("root", true),
      node1 = new DefaultMutableTreeNode("node 1", true), node2 = new DefaultMutableTreeNode(
          "node 2", true), node3 = new DefaultMutableTreeNode("node 3", true);
  MyJTree tree = new MyJTree(root);
  public Main() {
    root.add(node1);
    node1.add(node2);
    root.add(node3);
    setLayout(new BorderLayout());
    add(new JScrollPane((JTree) tree), "Center");
  }
  public static void main(String s[]) {
    JFrame frame = new JFrame("Tree With Popup");
    Main panel = new Main();
    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    frame.setBackground(Color.lightGray);
    frame.getContentPane().add(panel, "Center");
    frame.setSize(panel.getPreferredSize());
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}
class MyJTree extends JTree implements ActionListener {
  JPopupMenu popup = new JPopupMenu();
  JMenuItem mi = new JMenuItem("Insert a children");
  MyJTree(DefaultMutableTreeNode dmtn) {
    super(dmtn);    
    mi.addActionListener(this);
    mi.setActionCommand("insert");
    popup.add(mi);
    mi = new JMenuItem("Remove this node");
    mi.addActionListener(this);
    mi.setActionCommand("remove");
    popup.add(mi);
    addMouseListener(new MouseAdapter() {
      public void mouseReleased(MouseEvent e) {
        if (e.isPopupTrigger()) {
          popup.show((JComponent) e.getSource(), e.getX(), e.getY());
        }
      }
    });
  }
  public void actionPerformed(ActionEvent ae) {
    DefaultMutableTreeNode dmtn, node;
    TreePath path = this.getSelectionPath();
    dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
    if (ae.getActionCommand().equals("insert")) {
      node = new DefaultMutableTreeNode("children");
      dmtn.add(node);
      ((DefaultTreeModel) this.getModel()).nodeStructureChanged((TreeNode) dmtn);
    }
    if (ae.getActionCommand().equals("remove")) {
      node = (DefaultMutableTreeNode) dmtn.getParent();
      int nodeIndex = node.getIndex(dmtn);
      dmtn.removeAllChildren();
      node.remove(nodeIndex);
      ((DefaultTreeModel) this.getModel()).nodeStructureChanged((TreeNode) dmtn);
    }
  }
}





Have the row height for each row computed individually

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeightCalculation {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    tree.setRowHeight(0);
    JFrame frame = new JFrame("tree row height calculation");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





implements TreeSelectionListener to create your own listener

  
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class Tree1 
  extends JFrame 
{
  protected JTree  m_tree = null;
  protected DefaultTreeModel m_model = null;
  protected JTextField m_display;
  public Tree1()
  {
    super("Sample Tree [OID]");
    setSize(400, 300);
        Object[] nodes = new Object[5];
    DefaultMutableTreeNode top = new DefaultMutableTreeNode(
      new OidNode(1, "ISO"));
    DefaultMutableTreeNode parent = top;
    nodes[0] = top;
    DefaultMutableTreeNode node = new DefaultMutableTreeNode(
      new OidNode(0, "standard"));
    parent.add(node);
    node = new DefaultMutableTreeNode(new OidNode(2, 
      "member-body"));
    parent.add(node);
    node = new DefaultMutableTreeNode(new OidNode(3, "org"));
    parent.add(node);
    parent = node;
    nodes[1] = parent;
    node = new DefaultMutableTreeNode(new OidNode(6, "dod"));
    parent.add(node);
    parent = node;
    nodes[2] = parent;
    node = new DefaultMutableTreeNode(new OidNode(1, 
      "internet"));
    parent.add(node);
    parent = node;
    nodes[3] = parent;
    node = new DefaultMutableTreeNode(new OidNode(1, 
      "directory"));
    parent.add(node);
    node = new DefaultMutableTreeNode(new OidNode(2, 
      "mgmt"));
    parent.add(node);
    nodes[4] = node;
    node.add(new DefaultMutableTreeNode(new OidNode(1, 
      "mib-2")));
    node = new DefaultMutableTreeNode(new OidNode(3, 
      "experimental"));
    parent.add(node);
    node = new DefaultMutableTreeNode(new OidNode(4, 
      "private"));
    node.add(new DefaultMutableTreeNode(new OidNode(1, 
      "enterprises")));
    parent.add(node);
    node = new DefaultMutableTreeNode(new OidNode(5, 
      "security"));
    parent.add(node);
    node = new DefaultMutableTreeNode(new OidNode(6, 
      "snmpV2"));
    parent.add(node);
    node = new DefaultMutableTreeNode(new OidNode(7, 
      "mail"));
    parent.add(node);
    m_model = new DefaultTreeModel(top);
    m_tree = new JTree(m_model);
    DefaultTreeCellRenderer renderer = new 
      DefaultTreeCellRenderer();
    renderer.setOpenIcon(new ImageIcon("opened.gif"));
    renderer.setClosedIcon(new ImageIcon("closed.gif"));
    renderer.setLeafIcon(new ImageIcon("leaf.gif"));
    m_tree.setCellRenderer(renderer);
    m_tree.setShowsRootHandles(true); 
    m_tree.setEditable(false);
    TreePath path = new TreePath(nodes);
    m_tree.setSelectionPath(path);
    m_tree.addTreeSelectionListener(new 
      OidSelectionListener());
    JScrollPane s = new JScrollPane();
    s.getViewport().add(m_tree);
    getContentPane().add(s, BorderLayout.CENTER);
    m_display = new JTextField();
    m_display.setEditable(false);
    getContentPane().add(m_display, BorderLayout.SOUTH);
    WindowListener wndCloser = new WindowAdapter()
    {
      public void windowClosing(WindowEvent e) 
      {
        System.exit(0);
      }
    };
    addWindowListener(wndCloser);
    
    setVisible(true);
  }
  public static void main(String argv[]) 
  {
    new Tree1();
  }
  class OidSelectionListener 
    implements TreeSelectionListener 
  {
    public void valueChanged(TreeSelectionEvent e)
    {
      TreePath path = e.getPath();
      Object[] nodes = path.getPath();
      String oid = "";
      for (int k=0; k<nodes.length; k++)
      {
        DefaultMutableTreeNode node = 
          (DefaultMutableTreeNode)nodes[k];
        OidNode nd = (OidNode)node.getUserObject();
        oid += "."+nd.getId();
      }
      m_display.setText(oid);
    }
  }
}
class OidNode
{
  protected int    m_id;
  protected String m_name;
  public OidNode(int id, String name)
  {
    m_id = id;
    m_name = name;
  }
  public int getId() 
  { 
    return m_id;
  }
  public String getName() 
  { 
    return m_name;
  }
  public String toString() 
  { 
    return m_name;
  }
}





Installs custom icons

  
/*
Java Swing, 2nd Edition
By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole
ISBN: 0-596-00408-7
Publisher: O"Reilly 
*/
// TestTree3.java
//A variation on TestTree that installs custom icons. The icons installed
//will appear on *every* tree.
//
import java.awt.BorderLayout;
import java.util.Hashtable;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultTreeModel;
public class TestTree3 extends JFrame {
  JTree tree;
  DefaultTreeModel treeModel;
  public TestTree3() {
    super("Tree Test Example");
    setSize(200, 150);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    // Add our own customized tree icons.
    UIManager.put("Tree.leafIcon", new ImageIcon("world.gif"));
    UIManager.put("Tree.openIcon", new ImageIcon("door.open.gif"));
    UIManager.put("Tree.closedIcon", new ImageIcon("door.closed.gif"));
    UIManager.put("Tree.expandedIcon", new ImageIcon("unlocked.gif"));
    UIManager.put("Tree.collapsedIcon", new ImageIcon("locked.gif"));
  }
  public void init() {
    // Build the hierarchy of containers & objects.
    String[] schoolyard = { "School", "Playground", "Parking Lot", "Field" };
    String[] mainstreet = { "Grocery", "Shoe Shop", "Five & Dime",
        "Post Office" };
    String[] highway = { "Gas Station", "Convenience Store" };
    String[] housing = { "Victorian_blue", "Faux Colonial",
        "Victorian_white" };
    String[] housing2 = { "Mission", "Ranch", "Condo" };
    Hashtable homeHash = new Hashtable();
    homeHash.put("Residential 1", housing);
    homeHash.put("Residential 2", housing2);
    Hashtable cityHash = new Hashtable();
    cityHash.put("School grounds", schoolyard);
    cityHash.put("Downtown", mainstreet);
    cityHash.put("Highway", highway);
    cityHash.put("Housing", homeHash);
    Hashtable worldHash = new Hashtable();
    worldHash.put("My First VRML World", cityHash);
    // Build our tree out of our big hash table.
    tree = new JTree(worldHash);
    // Pick an angled line style.
    tree.putClientProperty("JTree.lineStyle", "Angled");
    getContentPane().add(tree, BorderLayout.CENTER);
  }
  public static void main(String args[]) {
    TestTree3 tt = new TestTree3();
    tt.init();
    tt.setVisible(true);
  }
}





Install ToolTips for Tree (JTree)

  
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.util.Dictionary;
import java.util.Properties;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.ToolTipManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;
public class TreeTips {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Tree Tips");
    Properties props = System.getProperties();
    JTree tree = new JTree(props);
    ToolTipManager.sharedInstance().registerComponent(tree);
    TreeCellRenderer renderer = new ToolTipTreeCellRenderer(props);
    tree.setCellRenderer(renderer);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}
class ToolTipTreeCellRenderer implements TreeCellRenderer {
  DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
  Dictionary tipTable;
  public ToolTipTreeCellRenderer(Dictionary tipTable) {
    this.tipTable = tipTable;
  }
  public Component getTreeCellRendererComponent(JTree tree, Object value,
      boolean selected, boolean expanded, boolean leaf, int row,
      boolean hasFocus) {
    renderer.getTreeCellRendererComponent(tree, value, selected, expanded,
        leaf, row, hasFocus);
    if (value != null) {
      Object tipKey;
      if (value instanceof DefaultMutableTreeNode) {
        tipKey = ((DefaultMutableTreeNode) value).getUserObject();
      } else {
        tipKey = tree.convertValueToText(value, selected, expanded,
            leaf, row, hasFocus);
      }
      Object tip = tipTable.get(tipKey);
      if (tip != null) {
        renderer.setToolTipText(tip.toString());
      } else {
        renderer.setToolTipText(null);
      }
    }
    return renderer;
  }
}





JTree drag and drop utilites

   
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
 
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.tree.TreePath;
/* This comes from "Denis" at http://forum.java.sun.ru/thread.jspa?forumID=57&threadID=296255 */
/*
 * My program use 4 classes. The application displays two trees.
 * You can drag (move by default or copy with ctrl pressed) a node from the left tree to the right one, from the right to the left and inside the same tree.
 * The rules for moving are :
 *   - you can"t move the root
 *   - you can"t move the selected node to its subtree (in the same tree).
 *   - you can"t move the selected node to itself (in the same tree).
 *   - you can"t move the selected node to its parent (in the same tree).
 *   - you can move a node to anywhere you want according to the 4 previous rules.
 *  The rules for copying are :
 *   - you can copy a node to anywhere you want.
 *
 * In the implementation I used DnD version of Java 1.3 because in 1.4 the DnD is too restrictive :
 * you can"t do what you want (displaying the image of the node while dragging, changing the cursor
 * according to where you are dragging, etc...). In 1.4, the DnD is based on the 1.3 version but
 * it is too encapsulated.
 */

public class JTreeUtil {
    private static final Insets DEFAULT_INSETS = new Insets(20, 20, 20, 20);
    private static final DataFlavor NODE_FLAVOR = new DataFlavor(
            DataFlavor.javaJVMLocalObjectMimeType, "Node");
    private static Object draggedNode;
    private static BufferedImage image = null; // buff image
    private static class TransferableNode implements Transferable {
        private Object node;
        private DataFlavor[] flavors = { NODE_FLAVOR };
        public TransferableNode(Object nd) {
            node = nd;
        }
        public synchronized Object getTransferData(DataFlavor flavor)
                throws UnsupportedFlavorException {
            if(flavor == NODE_FLAVOR) {
                return node;
            } else {
                throw new UnsupportedFlavorException(flavor);
            }
        }
        public DataFlavor[] getTransferDataFlavors() {
            return flavors;
        }
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return Arrays.asList(flavors).contains(flavor);
        }
    }
    /*
     * This class is the most important. It manages all the DnD behavior. It is
     * abstract because it contains two abstract methods:
     *   public abstract boolean canPerformAction(JTree target,
     *     Object draggedNode, int action, Point location);
     *   public abstract boolean executeDrop(DNDTree tree,
     *     Object draggedNode, Object newParentNode, int action);
     * we have to override to give the required behavior of DnD in your tree.
     */
    private static class TreeTransferHandler implements
            DragGestureListener, DragSourceListener, DropTargetListener {
        private JTree tree;
        private JTreeDragController controller;
        private DragSource dragSource; // dragsource
        private Rectangle rect2D = new Rectangle();
        private boolean drawImage;
        protected TreeTransferHandler(JTree tree, JTreeDragController controller,
                int action, boolean drawIcon) {
            this.tree = tree;
            this.controller = controller;
            drawImage = drawIcon;
            dragSource = new DragSource();
            dragSource.createDefaultDragGestureRecognizer(tree, action, this);
        }
        /* Methods for DragSourceListener */
        public void dragDropEnd(DragSourceDropEvent dsde) {
            /*
            if(dsde.getDropSuccess()
                    && dsde.getDropAction() == DnDConstants.ACTION_MOVE
                    && draggedNodeParent != null) {
                ((DefaultTreeModel) tree.getModel())
                        .nodeStructureChanged(draggedNodeParent);
            }
            */
        }
        public final void dragEnter(DragSourceDragEvent dsde) {
            int action = dsde.getDropAction();
            if(action == DnDConstants.ACTION_COPY) {
                dsde.getDragSourceContext().setCursor(
                        DragSource.DefaultCopyDrop);
            } else {
                if(action == DnDConstants.ACTION_MOVE) {
                    dsde.getDragSourceContext().setCursor(
                            DragSource.DefaultMoveDrop);
                } else {
                    dsde.getDragSourceContext().setCursor(
                            DragSource.DefaultMoveNoDrop);
                }
            }
        }
        public final void dragOver(DragSourceDragEvent dsde) {
            int action = dsde.getDropAction();
            if(action == DnDConstants.ACTION_COPY) {
                dsde.getDragSourceContext().setCursor(
                        DragSource.DefaultCopyDrop);
            } else {
                if(action == DnDConstants.ACTION_MOVE) {
                    dsde.getDragSourceContext().setCursor(
                            DragSource.DefaultMoveDrop);
                } else {
                    dsde.getDragSourceContext().setCursor(
                            DragSource.DefaultMoveNoDrop);
                }
            }
        }
        public final void dropActionChanged(DragSourceDragEvent dsde) {
            int action = dsde.getDropAction();
            if(action == DnDConstants.ACTION_COPY) {
                dsde.getDragSourceContext().setCursor(
                        DragSource.DefaultCopyDrop);
            } else {
                if(action == DnDConstants.ACTION_MOVE) {
                    dsde.getDragSourceContext().setCursor(
                            DragSource.DefaultMoveDrop);
                } else {
                    dsde.getDragSourceContext().setCursor(
                            DragSource.DefaultMoveNoDrop);
                }
            }
        }
        public final void dragExit(DragSourceEvent dse) {
            dse.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
        }
        /* Methods for DragGestureListener */
        public final void dragGestureRecognized(DragGestureEvent dge) {
            TreePath path = tree.getSelectionPath();
            if(path != null) {
                draggedNode = path.getLastPathComponent();
                if(drawImage) {
                    Rectangle pathBounds = tree.getPathBounds(path); // getpathbounds
                                                                        // of
                                                                        // selectionpath
                    JComponent lbl = (JComponent) tree
                            .getCellRenderer()
                            .getTreeCellRendererComponent(
                                    tree,
                                    draggedNode,
                                    false,
                                    tree.isExpanded(path),
                                    tree.getModel() .isLeaf(path.getLastPathComponent()),
                                    0, false);// returning the label
                    lbl.setBounds(pathBounds);// setting bounds to lbl
                    image = new BufferedImage(lbl.getWidth(), lbl.getHeight(),
                            java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE);// buffered
                                                                            // image
                                                                            // reference
                                                                            // passing
                                                                            // the
                                                                            // label"s
                                                                            // ht
                                                                            // and
                                                                            // width
                    Graphics2D graphics = image.createGraphics();// creating
                                                                    // the
                                                                    // graphics
                                                                    // for
                                                                    // buffered
                                                                    // image
                    graphics.setComposite(AlphaComposite.getInstance(
                            AlphaComposite.SRC_OVER, 0.5f)); // Sets the
                                                                // Composite for
                                                                // the
                                                                // Graphics2D
                                                                // context
                    lbl.setOpaque(false);
                    lbl.paint(graphics); // painting the graphics to label
                    graphics.dispose();
                }
                dragSource.startDrag(dge, DragSource.DefaultMoveNoDrop, image,
                        new Point(0, 0), new TransferableNode(draggedNode),
                        this);
            }
        }
        /* Methods for DropTargetListener */
        public final void dragEnter(DropTargetDragEvent dtde) {
            Point pt = dtde.getLocation();
            int action = dtde.getDropAction();
            if(drawImage) {
                paintImage(pt);
            }
            if(controller.canPerformAction(tree, draggedNode, action, pt)) {
                dtde.acceptDrag(action);
            } else {
                dtde.rejectDrag();
            }
        }
        public final void dragExit(DropTargetEvent dte) {
            if(drawImage) {
                clearImage();
            }
        }
        public final void dragOver(DropTargetDragEvent dtde) {
            Point pt = dtde.getLocation();
            int action = dtde.getDropAction();
            autoscroll(tree, pt);
            if(drawImage) {
                paintImage(pt);
            }
            if(controller.canPerformAction(tree, draggedNode, action, pt)) {
                dtde.acceptDrag(action);
            } else {
                dtde.rejectDrag();
            }
        }
        public final void dropActionChanged(DropTargetDragEvent dtde) {
            Point pt = dtde.getLocation();
            int action = dtde.getDropAction();
            if(drawImage) {
                paintImage(pt);
            }
            if(controller.canPerformAction(tree, draggedNode, action, pt)) {
                dtde.acceptDrag(action);
            } else {
                dtde.rejectDrag();
            }
        }
        public final void drop(DropTargetDropEvent dtde) {
            try {
                if(drawImage) {
                    clearImage();
                }
                int action = dtde.getDropAction();
                Transferable transferable = dtde.getTransferable();
                Point pt = dtde.getLocation();
                if(transferable
                        .isDataFlavorSupported(NODE_FLAVOR)
                        && controller.canPerformAction(tree, draggedNode, action, pt)) {
                    TreePath pathTarget = tree.getPathForLocation(pt.x, pt.y);
                    Object node = transferable.getTransferData(NODE_FLAVOR);
                    Object newParentNode = pathTarget.getLastPathComponent();
                    if(controller.executeDrop(tree, node, newParentNode, action)) {
                        dtde.acceptDrop(action);
                        dtde.dropComplete(true);
                        return;
                    }
                }
                dtde.rejectDrop();
                dtde.dropComplete(false);
            } catch(Exception e) {
                dtde.rejectDrop();
                dtde.dropComplete(false);
            }
        }
        private final void paintImage(Point pt) {
            tree.paintImmediately(rect2D.getBounds());
            rect2D.setRect((int) pt.getX(), (int) pt.getY(), image.getWidth(),
                    image.getHeight());
            tree.getGraphics().drawImage(image, (int) pt.getX(),
                    (int) pt.getY(), tree);
        }
        private final void clearImage() {
            tree.paintImmediately(rect2D.getBounds());
        }
    }
    
    public static void configureDragAndDrop(JTree tree, JTreeDragController controller) {
        tree.setAutoscrolls(true);
        new TreeTransferHandler(tree, controller, DnDConstants.ACTION_COPY_OR_MOVE, true);
    }
    private static void autoscroll(JTree tree, Point cursorLocation) {
        Insets insets = DEFAULT_INSETS;
        Rectangle outer = tree.getVisibleRect();
        Rectangle inner = new Rectangle(outer.x + insets.left, outer.y
                + insets.top, outer.width - (insets.left + insets.right),
                outer.height - (insets.top + insets.bottom));
        if(!inner.contains(cursorLocation)) {
            Rectangle scrollRect = new Rectangle(cursorLocation.x
                    - insets.left, cursorLocation.y - insets.top,
                    insets.left + insets.right, insets.top + insets.bottom);
            tree.scrollRectToVisible(scrollRect);
        }
    }
}
/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.ru/logisim/. */
 

/* This comes from "Denis" at http://forum.java.sun.ru/thread.jspa?forumID=57&threadID=296255 */
/*
 * My program use 4 classes. The application displays two trees.
 * You can drag (move by default or copy with ctrl pressed) a node from the left tree to the right one, from the right to the left and inside the same tree.
 * The rules for moving are :
 *   - you can"t move the root
 *   - you can"t move the selected node to its subtree (in the same tree).
 *   - you can"t move the selected node to itself (in the same tree).
 *   - you can"t move the selected node to its parent (in the same tree).
 *   - you can move a node to anywhere you want according to the 4 previous rules.
 *  The rules for copying are :
 *   - you can copy a node to anywhere you want.
 *
 * In the implementation I used DnD version of Java 1.3 because in 1.4 the DnD is too restrictive :
 * you can"t do what you want (displaying the image of the node while dragging, changing the cursor
 * according to where you are dragging, etc...). In 1.4, the DnD is based on the 1.3 version but
 * it is too encapsulated.
 */
interface JTreeDragController {
    public boolean canPerformAction(JTree target, Object draggedNode,
            int action, Point location);
    public boolean executeDrop(JTree tree, Object draggedNode,
            Object newParentNode, int action);
}





JTree.DynamicUtilTreeNode.createChildren

  
import java.awt.BorderLayout;
import java.util.Hashtable;
import java.util.Properties;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
public class TreeUtilSample {
  public static void main(String args[]) {
    JFrame frame = new JFrame("DynamicUtilTreeNode Hashtable");
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    Hashtable hashtable = new Hashtable();
    hashtable.put("One", args);
    hashtable.put("Two", new String[] { "Mercury", "Venus", "Mars" });
    Hashtable innerHashtable = new Hashtable();
    Properties props = System.getProperties();
    innerHashtable.put(props, props);
    innerHashtable.put("Two", new String[] { "Mercury", "Venus", "Mars" });
    hashtable.put("Three", innerHashtable);
    JTree.DynamicUtilTreeNode.createChildren(root, hashtable);
    JTree tree = new JTree(root);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}





JTree root cannot be removed with removeNodeFromParent(), use DefaultTreeModel.setRoot() to remove the root

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
public class TreeRootRemove {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
    model.setRoot(null);
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Listening for Expansion and Collapse Events in a JTree Component

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
public class Main {
  public static void main() {
    JTree tree = new JTree();
    tree.addTreeWillExpandListener(new MyTreeWillExpandListener());
    tree.addTreeExpansionListener(new MyTreeExpansionListener());
    JFrame f = new JFrame();
    f.add(new JScrollPane(tree));
    f.setSize(300, 300);
    f.setVisible(true);
  }
}
class MyTreeWillExpandListener implements TreeWillExpandListener {
  public void treeWillExpand(TreeExpansionEvent evt) throws ExpandVetoException {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    boolean veto = false;
    if (veto) {
      throw new ExpandVetoException(evt);
    }
  }
  public void treeWillCollapse(TreeExpansionEvent evt) throws ExpandVetoException {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    boolean veto = false;
    if (veto) {
      throw new ExpandVetoException(evt);
    }
  }
}
class MyTreeExpansionListener implements TreeExpansionListener {
  public void treeExpanded(TreeExpansionEvent evt) {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    System.out.println("treeExpanded");
  }
  public void treeCollapsed(TreeExpansionEvent evt) {
    JTree tree = (JTree) evt.getSource();
    TreePath path = evt.getPath();
    System.out.println("treeCollapsed");
  }
}





Listening for Selection Events in a JTree Component

  
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent evt) {
        TreePath[] paths = evt.getPaths();
        for (int i = 0; i < paths.length; i++) {
          if (evt.isAddedPath(i)) {
            System.out.println("This node has been selected");
          } else {
            System.out.println("This node has been deselected"); 
          }
        }
      }
    });
  }
}





Preventing Expansion or Collapse of a Node in a JTree: override JTree.setExpandedState()

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) {
    JTree tree = new JTree() {
      protected void setExpandedState(TreePath path, boolean state) {
        
        if (state) {
          super.setExpandedState(path, state);
        }
      }
    };
    JFrame frame = new JFrame("Ignore all collapse requests");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Preventing the Expansion or Collapse of a Node in a JTree Component

  
import javax.swing.JTree;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) {
    JTree tree = new JTree() {
      protected void setExpandedState(TreePath path, boolean state) {
        if (state) {
          super.setExpandedState(path, state);
        }
      }
    };
  }
}





Removing a Node to a JTree Component

  
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
public class TreeNodeRemove{
  public static void main(String[] argv) {
    Vector<String> v = new Vector<String>();
    v.add("a");
    v.add("b");
    v.add("c");
    JTree tree = new JTree(v);
    DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
    int startRow = 0;
    String prefix = "b";
    TreePath path = tree.getNextMatch(prefix, startRow, Position.Bias.Forward);
    MutableTreeNode node = (MutableTreeNode) path.getLastPathComponent();
    model.removeNodeFromParent(node);
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Returns a TreePath containing the specified node.

  
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
 
  public TreePath getPath(TreeNode node) {
    List<TreeNode> list = new ArrayList<TreeNode>();
    while (node != null) {
      list.add(node);
      node = node.getParent();
    }
    Collections.reverse(list);
    return new TreePath(list.toArray());
  }
}





Search backward from last visible row looking for any visible node whose name starts with prefix.

  
import javax.swing.JTree;
import javax.swing.text.Position;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    int startRow = tree.getRowCount() - 1;
    String prefix = "b";
    TreePath path = tree.getNextMatch(prefix, startRow, Position.Bias.Backward);
    System.out.println(path);
  }
}





Searching node in a JTree

  
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class EditableTree extends JFrame {
  private DefaultMutableTreeNode m_rootNode = new DefaultMutableTreeNode("AA");
  private DefaultTreeModel m_model = new DefaultTreeModel(m_rootNode);
  private JTree m_tree = new JTree(m_model);
  private JButton m_addButton = new JButton("Add Node");
  private JButton m_delButton = new JButton("Delete Node");
  private JButton m_searchButton = new JButton("Search Node");
  private JButton m_searchAndDeleteButton = new JButton("Search and Delete Node");
  private JTextField m_searchText;
  public EditableTree() {
    DefaultMutableTreeNode forums = new DefaultMutableTreeNode("A");
    forums.add(new DefaultMutableTreeNode("B"));
    DefaultMutableTreeNode articles = new DefaultMutableTreeNode("E");
    articles.add(new DefaultMutableTreeNode("F"));
    DefaultMutableTreeNode examples = new DefaultMutableTreeNode("G");
    examples.add(new DefaultMutableTreeNode("H"));
    m_rootNode.add(forums);
    m_rootNode.add(articles);
    m_rootNode.add(examples);
    m_tree.setEditable(true);
    m_tree.setSelectionRow(0);
    JScrollPane scrollPane = new JScrollPane(m_tree);
    getContentPane().add(scrollPane, BorderLayout.CENTER);
    JPanel panel = new JPanel();
    m_addButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
            .getLastSelectedPathComponent();
        if (selNode == null) {
          return;
        }
        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New Node");
        m_model.insertNodeInto(newNode, selNode, selNode.getChildCount());
        TreeNode[] nodes = m_model.getPathToRoot(newNode);
        TreePath path = new TreePath(nodes);
        m_tree.scrollPathToVisible(path);
        m_tree.setSelectionPath(path);
        m_tree.startEditingAtPath(path);
      }
    });
    panel.add(m_addButton);
    m_delButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) m_tree
            .getLastSelectedPathComponent();
        removeNode(selNode);
      }
    });
    panel.add(m_delButton);
    JPanel searchPanel = new JPanel();
    searchPanel.setBorder(BorderFactory.createEtchedBorder());
    m_searchText = new JTextField(10);
    searchPanel.add(m_searchText);
    m_searchButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        DefaultMutableTreeNode node = searchNode(m_searchText.getText());
        if (node != null) {
          TreeNode[] nodes = m_model.getPathToRoot(node);
          TreePath path = new TreePath(nodes);
          m_tree.scrollPathToVisible(path);
          m_tree.setSelectionPath(path);
        } else {
          System.out.println("Node with string " + m_searchText.getText() + " not found");
        }
      }
    });
    searchPanel.add(m_searchButton);
    m_searchAndDeleteButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        DefaultMutableTreeNode node = searchNode(m_searchText.getText());
        if (node != null) {
          removeNode(node);
        } else {
          System.out.println("Node with string " + m_searchText.getText() + " not found");
        }
      }
    });
    searchPanel.add(m_searchAndDeleteButton);
    panel.add(searchPanel);
    getContentPane().add(panel, BorderLayout.SOUTH);
    setSize(700, 400);
    setVisible(true);
  }
  public DefaultMutableTreeNode searchNode(String nodeStr) {
    DefaultMutableTreeNode node = null;
    Enumeration e = m_rootNode.breadthFirstEnumeration();
    while (e.hasMoreElements()) {
      node = (DefaultMutableTreeNode) e.nextElement();
      if (nodeStr.equals(node.getUserObject().toString())) {
        return node;
      }
    }
    return null;
  }
  public void removeNode(DefaultMutableTreeNode selNode) {
    if (selNode == null) {
      return;
    }
    MutableTreeNode parent = (MutableTreeNode) (selNode.getParent());
    if (parent == null) {
      return;
    }
    MutableTreeNode toBeSelNode = getSibling(selNode);
    if (toBeSelNode == null) {
      toBeSelNode = parent;
    }
    TreeNode[] nodes = m_model.getPathToRoot(toBeSelNode);
    TreePath path = new TreePath(nodes);
    m_tree.scrollPathToVisible(path);
    m_tree.setSelectionPath(path);
    m_model.removeNodeFromParent(selNode);
  }
  private MutableTreeNode getSibling(DefaultMutableTreeNode selNode) {
    MutableTreeNode sibling = (MutableTreeNode) selNode.getPreviousSibling();
    if (sibling == null) {
      sibling = (MutableTreeNode) selNode.getNextSibling();
    }
    return sibling;
  }
  public static void main(String[] arg) {
    EditableTree editableTree = new EditableTree();
  }
}





Set the Tree Line

  
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
public class TreeLineSample {
  public static void main(String args[]) {
    String title = "JTree Sample";
    JFrame frame = new JFrame(title);
    
    UIManager.put("Tree.line", Color.green);
    JTree tree = new JTree();
    tree.putClientProperty("JTree.lineStyle", "Horizontal");
    tree.setSelectionModel(null);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}





Setting the Row Height of a JTree

  
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeRowHeight {
  public static void main(String[] argv) {
    JTree tree = new JTree();
    tree.setRowHeight(15);
    JFrame frame = new JFrame("tree row height");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new JScrollPane(tree));
    frame.setSize(380, 320);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}





Traverse all expanded nodes in tree

  
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    visitAllExpandedNodes(tree);  
  }
  public static void visitAllExpandedNodes(JTree tree) {
    TreeNode root = (TreeNode) tree.getModel().getRoot();
    visitAllExpandedNodes(tree, new TreePath(root));
  }
  public static void visitAllExpandedNodes(JTree tree, TreePath parent) {
    if (!tree.isVisible(parent)) {
      return;
    }
    TreeNode node = (TreeNode) parent.getLastPathComponent();
    System.out.println(node);
    if (node.getChildCount() >= 0) {
      for (Enumeration e = node.children(); e.hasMoreElements();) {
        TreeNode n = (TreeNode) e.nextElement();
        TreePath path = parent.pathByAddingChild(n);
        visitAllExpandedNodes(tree, path);
      }
    }
  }
}





Traverse Tree

  
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.*;
import java.util.*;
public class TraverseTree {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Traverse Tree");
    Object footballNodes[] = { "Giants", "Jets", "Bills" };
    Vector footballVector = new NamedVector("Football", footballNodes);
    Object newYorkNodes[] = { "Mets", "Yankees", "Rangers", footballVector };
    Vector newYorkVector = new NamedVector("New York", newYorkNodes);
    Object bostonNodes[] = { "Red Sox", "Celtics", "Bruins" };
    Vector bostonVector = new NamedVector("Boston", bostonNodes);
    Object denverNodes[] = { "Rockies", "Avalanche", "Broncos" };
    Vector denverVector = new NamedVector("Denver", denverNodes);
    Object rootNodes[] = { newYorkVector, bostonVector, denverVector };
    Vector rootVector = new NamedVector("Root", rootNodes);
    JTree tree = new JTree(rootVector);
    tree.setRootVisible(true);
    TreeModel model = tree.getModel();
    Object rootObject = model.getRoot();
    if ((rootObject != null)
        && (rootObject instanceof DefaultMutableTreeNode)) {
      DefaultMutableTreeNode root = (DefaultMutableTreeNode) rootObject;
      //    printDescendents(root);
      Enumeration breadth = root.breadthFirstEnumeration();
      Enumeration depth = root.depthFirstEnumeration();
      Enumeration preOrder = root.preorderEnumeration();
      printEnumeration(breadth, "Breadth");
      //      printEnumeration(depth, "Depth");
      //      printEnumeration(preOrder, "Pre");
    }
    TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
        JTree treeSource = (JTree) treeSelectionEvent.getSource();
        TreePath path = treeSource.getSelectionPath();
        System.out.println(path);
        System.out.println(path.getPath());
        System.out.println(path.getParentPath());
        System.out.println(((DefaultMutableTreeNode) path
            .getLastPathComponent()).getUserObject());
        System.out.println(path.getPathCount());
      }
    };
    tree.addTreeSelectionListener(treeSelectionListener);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 400);
    frame.setVisible(true);
  }
  private static void printEnumeration(Enumeration e, String label) {
    System.out.println("-----" + label + "-----");
    while (e.hasMoreElements()) {
      System.out.println(e.nextElement());
    }
  }
  public static void printDescendents(TreeNode root) {
    System.out.println(root);
    Enumeration children = root.children();
    if (children != null) {
      while (children.hasMoreElements()) {
        printDescendents((TreeNode) children.nextElement());
      }
    }
  }
}
class NamedVector extends Vector {
  String name;
  public NamedVector(String name) {
    this.name = name;
  }
  public NamedVector(String name, Object elements[]) {
    this.name = name;
    for (int i = 0, n = elements.length; i < n; i++) {
      add(elements[i]);
    }
  }
  public String toString() {
    return "[" + name + "]";
  }
}





Tree based on Array structure

  
import java.awt.BorderLayout;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeArraySample {
  public static void main(String args[]) {
    JFrame frame = new JFrame("JTreeSample");
    Vector oneVector = new NamedVector("One", args);
    Vector twoVector = new NamedVector("Two", new String[] { "Mercury",
        "Venus", "Mars" });
    Vector threeVector = new NamedVector("Three");
    threeVector.add(System.getProperties());
    threeVector.add(twoVector);
    Object rootNodes[] = { oneVector, twoVector, threeVector };
    Vector rootVector = new NamedVector("Root", rootNodes);
    JTree tree = new JTree(rootVector);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    //    frame.getContentPane().add(tree, BorderLayout.CENTER);
    frame.setSize(300, 300);
    frame.setVisible(true);
  }
}
class NamedVector extends Vector {
  String name;
  public NamedVector(String name) {
    this.name = name;
  }
  public NamedVector(String name, Object elements[]) {
    this.name = name;
    for (int i = 0, n = elements.length; i < n; i++) {
      add(elements[i]);
    }
  }
  public String toString() {
    return "[" + name + "]";
  }
}





Tree: Drag and Drop

  
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.Autoscroll;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Iterator;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class TreeTester {
  public static void main(String args[]) {
    JFrame f = new JFrame("Tree Dragging Tester");
    DndTree tree1 = new DndTree();
    JScrollPane leftPane = new JScrollPane(tree1);
    DndTree tree2 = new DndTree();
    JScrollPane rightPane = new JScrollPane(tree2);
    JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
        leftPane, rightPane);
    f.getContentPane().add(splitPane, BorderLayout.CENTER);
    f.setSize(300, 200);
    f.setVisible(true);
  }
}
class DndTree extends JTree implements Autoscroll {
  private Insets insets;
  private int top = 0, bottom = 0, topRow = 0, bottomRow = 0;
  public DndTree() {
    DragSource dragSource = DragSource.getDefaultDragSource();
    dragSource
        .createDefaultDragGestureRecognizer(this,
            DnDConstants.ACTION_COPY_OR_MOVE,
            new TreeDragGestureListener());
    DropTarget dropTarget = new DropTarget(this,
        new TreeDropTargetListener());
  }
  public DndTree(TreeModel model) {
    super(model);
    DragSource dragSource = DragSource.getDefaultDragSource();
    dragSource
        .createDefaultDragGestureRecognizer(this,
            DnDConstants.ACTION_COPY_OR_MOVE,
            new TreeDragGestureListener());
    DropTarget dropTarget = new DropTarget(this,
        new TreeDropTargetListener());
  }
  public Insets getAutoscrollInsets() {
    return insets;
  }
  public void autoscroll(Point p) {
    // Only support up/down scrolling
    top = Math.abs(getLocation().y) + 10;
    bottom = top + getParent().getHeight() - 20;
    int next;
    if (p.y < top) {
      next = topRow--;
      bottomRow++;
      scrollRowToVisible(next);
    } else if (p.y > bottom) {
      next = bottomRow++;
      topRow--;
      scrollRowToVisible(next);
    }
  }
  private static class TreeDragGestureListener implements DragGestureListener {
    public void dragGestureRecognized(DragGestureEvent dragGestureEvent) {
      // Can only drag leafs
      JTree tree = (JTree) dragGestureEvent.getComponent();
      TreePath path = tree.getSelectionPath();
      if (path == null) {
        // Nothing selected, nothing to drag
        System.out.println("Nothing selected - beep");
        tree.getToolkit().beep();
      } else {
        DefaultMutableTreeNode selection = (DefaultMutableTreeNode) path
            .getLastPathComponent();
        if (selection.isLeaf()) {
          TransferableTreeNode node = new TransferableTreeNode(
              selection);
          dragGestureEvent.startDrag(DragSource.DefaultCopyDrop,
              node, new MyDragSourceListener());
        } else {
          System.out.println("Not a leaf - beep");
          tree.getToolkit().beep();
        }
      }
    }
  }
  private class TreeDropTargetListener implements DropTargetListener {
    public void dragEnter(DropTargetDragEvent dropTargetDragEvent) {
      // Setup positioning info for auto-scrolling
      top = Math.abs(getLocation().y);
      bottom = top + getParent().getHeight();
      topRow = getClosestRowForLocation(0, top);
      bottomRow = getClosestRowForLocation(0, bottom);
      insets = new Insets(top + 10, 0, bottom - 10, getWidth());
    }
    public void dragExit(DropTargetEvent dropTargetEvent) {
    }
    public void dragOver(DropTargetDragEvent dropTargetDragEvent) {
    }
    public void dropActionChanged(DropTargetDragEvent dropTargetDragEvent) {
    }
    public synchronized void drop(DropTargetDropEvent dropTargetDropEvent) {
      // Only support dropping over nodes that aren"t leafs
      Point location = dropTargetDropEvent.getLocation();
      TreePath path = getPathForLocation(location.x, location.y);
      Object node = path.getLastPathComponent();
      if ((node != null) && (node instanceof TreeNode)
          && (!((TreeNode) node).isLeaf())) {
        try {
          Transferable tr = dropTargetDropEvent.getTransferable();
          if (tr
              .isDataFlavorSupported(TransferableTreeNode.DEFAULT_MUTABLE_TREENODE_FLAVOR)) {
            dropTargetDropEvent
                .acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
            Object userObject = tr
                .getTransferData(TransferableTreeNode.DEFAULT_MUTABLE_TREENODE_FLAVOR);
            addElement(path, userObject);
            dropTargetDropEvent.dropComplete(true);
          } else if (tr
              .isDataFlavorSupported(DataFlavor.stringFlavor)) {
            dropTargetDropEvent
                .acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
            String string = (String) tr
                .getTransferData(DataFlavor.stringFlavor);
            addElement(path, string);
            dropTargetDropEvent.dropComplete(true);
          } else if (tr
              .isDataFlavorSupported(DataFlavor.plainTextFlavor)) {
            dropTargetDropEvent
                .acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
            Object stream = tr
                .getTransferData(DataFlavor.plainTextFlavor);
            if (stream instanceof InputStream) {
              InputStreamReader isr = new InputStreamReader(
                  (InputStream) stream);
              BufferedReader reader = new BufferedReader(isr);
              String line;
              while ((line = reader.readLine()) != null) {
                addElement(path, line);
              }
              dropTargetDropEvent.dropComplete(true);
            } else if (stream instanceof Reader) {
              BufferedReader reader = new BufferedReader(
                  (Reader) stream);
              String line;
              while ((line = reader.readLine()) != null) {
                addElement(path, line);
              }
              dropTargetDropEvent.dropComplete(true);
            } else {
              System.err.println("Unknown type: "
                  + stream.getClass());
              dropTargetDropEvent.rejectDrop();
            }
          } else if (tr
              .isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
            dropTargetDropEvent
                .acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
            List fileList = (List) tr
                .getTransferData(DataFlavor.javaFileListFlavor);
            Iterator iterator = fileList.iterator();
            while (iterator.hasNext()) {
              File file = (File) iterator.next();
              addElement(path, file.toURL());
            }
            dropTargetDropEvent.dropComplete(true);
          } else {
            System.err.println("Rejected");
            dropTargetDropEvent.rejectDrop();
          }
        } catch (IOException io) {
          io.printStackTrace();
          dropTargetDropEvent.rejectDrop();
        } catch (UnsupportedFlavorException ufe) {
          ufe.printStackTrace();
          dropTargetDropEvent.rejectDrop();
        }
      } else {
        System.out.println("Can"t drop on a leaf");
        dropTargetDropEvent.rejectDrop();
      }
    }
    private void addElement(TreePath path, Object element) {
      DefaultMutableTreeNode parent = (DefaultMutableTreeNode) path
          .getLastPathComponent();
      DefaultMutableTreeNode node = new DefaultMutableTreeNode(element);
      System.out.println("Added: " + node + " to " + parent);
      DefaultTreeModel model = (DefaultTreeModel) (DndTree.this
          .getModel());
      model.insertNodeInto(node, parent, parent.getChildCount());
    }
  }
  private static class MyDragSourceListener implements DragSourceListener {
    public void dragDropEnd(DragSourceDropEvent dragSourceDropEvent) {
      if (dragSourceDropEvent.getDropSuccess()) {
        int dropAction = dragSourceDropEvent.getDropAction();
        if (dropAction == DnDConstants.ACTION_MOVE) {
          System.out.println("MOVE: remove node");
        }
      }
    }
    public void dragEnter(DragSourceDragEvent dragSourceDragEvent) {
      DragSourceContext context = dragSourceDragEvent
          .getDragSourceContext();
      int dropAction = dragSourceDragEvent.getDropAction();
      if ((dropAction & DnDConstants.ACTION_COPY) != 0) {
        context.setCursor(DragSource.DefaultCopyDrop);
      } else if ((dropAction & DnDConstants.ACTION_MOVE) != 0) {
        context.setCursor(DragSource.DefaultMoveDrop);
      } else {
        context.setCursor(DragSource.DefaultCopyNoDrop);
      }
    }
    public void dragExit(DragSourceEvent dragSourceEvent) {
    }
    public void dragOver(DragSourceDragEvent dragSourceDragEvent) {
    }
    public void dropActionChanged(DragSourceDragEvent dragSourceDragEvent) {
    }
  }
}
class TransferableTreeNode extends DefaultMutableTreeNode implements
    Transferable {
  final static int TREE = 0;
  final static int STRING = 1;
  final static int PLAIN_TEXT = 1;
  final public static DataFlavor DEFAULT_MUTABLE_TREENODE_FLAVOR = new DataFlavor(
      DefaultMutableTreeNode.class, "Default Mutable Tree Node");
  static DataFlavor flavors[] = { DEFAULT_MUTABLE_TREENODE_FLAVOR,
      DataFlavor.stringFlavor, DataFlavor.plainTextFlavor };
  private DefaultMutableTreeNode data;
  public TransferableTreeNode(DefaultMutableTreeNode data) {
    this.data = data;
  }
  public DataFlavor[] getTransferDataFlavors() {
    return flavors;
  }
  public Object getTransferData(DataFlavor flavor)
      throws UnsupportedFlavorException, IOException {
    Object returnObject;
    if (flavor.equals(flavors[TREE])) {
      Object userObject = data.getUserObject();
      if (userObject == null) {
        returnObject = data;
      } else {
        returnObject = userObject;
      }
    } else if (flavor.equals(flavors[STRING])) {
      Object userObject = data.getUserObject();
      if (userObject == null) {
        returnObject = data.toString();
      } else {
        returnObject = userObject.toString();
      }
    } else if (flavor.equals(flavors[PLAIN_TEXT])) {
      Object userObject = data.getUserObject();
      String string;
      if (userObject == null) {
        string = data.toString();
      } else {
        string = userObject.toString();
      }
      returnObject = new ByteArrayInputStream(string.getBytes("Unicode"));
    } else {
      throw new UnsupportedFlavorException(flavor);
    }
    return returnObject;
  }
  public boolean isDataFlavorSupported(DataFlavor flavor) {
    boolean returnValue = false;
    for (int i = 0, n = flavors.length; i < n; i++) {
      if (flavor.equals(flavors[i])) {
        returnValue = true;
        break;
      }
    }
    return returnValue;
  }
}





Tree Expand Event Demo

  
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * TreeExpandEventDemo.java is a 1.4 example that requires no other files.
 */
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
public class TreeExpandEventDemo extends JPanel {
  DemoArea demoArea;
  JTextArea textArea;
  final static String newline = "\n";
  public TreeExpandEventDemo() {
    super(new GridBagLayout());
    GridBagLayout gridbag = (GridBagLayout) getLayout();
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.BOTH;
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.weightx = 1.0;
    c.weighty = 1.0;
    c.insets = new Insets(1, 1, 1, 1);
    demoArea = new DemoArea();
    gridbag.setConstraints(demoArea, c);
    add(demoArea);
    c.insets = new Insets(0, 0, 0, 0);
    textArea = new JTextArea();
    textArea.setEditable(false);
    JScrollPane scrollPane = new JScrollPane(textArea);
    scrollPane
        .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setPreferredSize(new Dimension(200, 75));
    gridbag.setConstraints(scrollPane, c);
    add(scrollPane);
    setPreferredSize(new Dimension(450, 450));
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  void saySomething(String eventDescription, TreeExpansionEvent e) {
    textArea.append(eventDescription + "; " + "path = " + e.getPath()
        + newline);
  }
  class DemoArea extends JScrollPane implements TreeExpansionListener {
    Dimension minSize = new Dimension(100, 100);
    JTree tree;
    public DemoArea() {
      TreeNode rootNode = createNodes();
      tree = new JTree(rootNode);
      tree.addTreeExpansionListener(this);
      setViewportView(tree);
    }
    private TreeNode createNodes() {
      DefaultMutableTreeNode root;
      DefaultMutableTreeNode grandparent;
      DefaultMutableTreeNode parent;
      DefaultMutableTreeNode child;
      root = new DefaultMutableTreeNode("San Francisco");
      grandparent = new DefaultMutableTreeNode("Potrero Hill");
      root.add(grandparent);
      //
      parent = new DefaultMutableTreeNode("Restaurants");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Thai Barbeque");
      parent.add(child);
      child = new DefaultMutableTreeNode("Goat Hill Pizza");
      parent.add(child);
      //
      parent = new DefaultMutableTreeNode("Grocery Stores");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Good Life Grocery");
      parent.add(child);
      child = new DefaultMutableTreeNode("Safeway");
      parent.add(child);
      grandparent = new DefaultMutableTreeNode("Noe Valley");
      root.add(grandparent);
      //
      parent = new DefaultMutableTreeNode("Restaurants");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Hamano Sushi");
      parent.add(child);
      child = new DefaultMutableTreeNode("Hahn"s Hibachi");
      parent.add(child);
      //
      parent = new DefaultMutableTreeNode("Grocery Stores");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Real Foods");
      parent.add(child);
      child = new DefaultMutableTreeNode("Bell Market");
      parent.add(child);
      return root;
    }
    public Dimension getMinimumSize() {
      return minSize;
    }
    public Dimension getPreferredSize() {
      return minSize;
    }
    // Required by TreeExpansionListener interface.
    public void treeExpanded(TreeExpansionEvent e) {
      saySomething("Tree-expanded event detected", e);
    }
    // Required by TreeExpansionListener interface.
    public void treeCollapsed(TreeExpansionEvent e) {
      saySomething("Tree-collapsed event detected", e);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("TreeExpandEventDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    JComponent newContentPane = new TreeExpandEventDemo();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}





Tree Expand Event Demo 2

  
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * TreeExpandEventDemo2.java is a 1.4 example that requires no other files.
 */
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreeNode;
public class TreeExpandEventDemo2 extends JPanel {
  DemoArea demoArea;
  JTextArea textArea;
  final static String newline = "\n";
  public TreeExpandEventDemo2() {
    super(new GridBagLayout());
    GridBagLayout gridbag = (GridBagLayout) getLayout();
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.BOTH;
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.weightx = 1.0;
    c.weighty = 1.0;
    c.insets = new Insets(1, 1, 1, 1);
    demoArea = new DemoArea();
    gridbag.setConstraints(demoArea, c);
    add(demoArea);
    c.insets = new Insets(0, 0, 0, 0);
    textArea = new JTextArea();
    textArea.setEditable(false);
    JScrollPane scrollPane = new JScrollPane(textArea);
    scrollPane
        .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setPreferredSize(new Dimension(200, 75));
    gridbag.setConstraints(scrollPane, c);
    add(scrollPane);
    setPreferredSize(new Dimension(450, 450));
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  void saySomething(String eventDescription, TreeExpansionEvent e) {
    textArea.append(eventDescription + "; " + "path = " + e.getPath()
        + newline);
  }
  class DemoArea extends JScrollPane implements TreeExpansionListener,
      TreeWillExpandListener {
    Dimension minSize = new Dimension(100, 100);
    JTree tree;
    Object[] willExpandOptions = { "Cancel Expansion", "Expand" };
    String willExpandText = "A branch node is about to be expanded.\n"
        + "Click \"Cancel Expansion\" to prevent it.";
    String willExpandTitle = "Tree Will Expand";
    public DemoArea() {
      TreeNode rootNode = createNodes();
      tree = new JTree(rootNode);
      tree.addTreeExpansionListener(this);
      tree.addTreeWillExpandListener(this);
      setViewportView(tree);
    }
    private TreeNode createNodes() {
      DefaultMutableTreeNode root;
      DefaultMutableTreeNode grandparent;
      DefaultMutableTreeNode parent;
      DefaultMutableTreeNode child;
      root = new DefaultMutableTreeNode("San Francisco");
      grandparent = new DefaultMutableTreeNode("Potrero Hill");
      root.add(grandparent);
      //
      parent = new DefaultMutableTreeNode("Restaurants");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Thai Barbeque");
      parent.add(child);
      child = new DefaultMutableTreeNode("Goat Hill Pizza");
      parent.add(child);
      //
      parent = new DefaultMutableTreeNode("Grocery Stores");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Good Life Grocery");
      parent.add(child);
      child = new DefaultMutableTreeNode("Safeway");
      parent.add(child);
      grandparent = new DefaultMutableTreeNode("Noe Valley");
      root.add(grandparent);
      //
      parent = new DefaultMutableTreeNode("Restaurants");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Hamano Sushi");
      parent.add(child);
      child = new DefaultMutableTreeNode("Hahn"s Hibachi");
      parent.add(child);
      //
      parent = new DefaultMutableTreeNode("Grocery Stores");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Real Foods");
      parent.add(child);
      child = new DefaultMutableTreeNode("Bell Market");
      parent.add(child);
      return root;
    }
    public Dimension getMinimumSize() {
      return minSize;
    }
    public Dimension getPreferredSize() {
      return minSize;
    }
    //Required by TreeWillExpandListener interface.
    public void treeWillExpand(TreeExpansionEvent e)
        throws ExpandVetoException {
      saySomething("Tree-will-expand event detected", e);
      int n = JOptionPane.showOptionDialog(this, willExpandText,
          willExpandTitle, JOptionPane.YES_NO_OPTION,
          JOptionPane.QUESTION_MESSAGE, null, willExpandOptions,
          willExpandOptions[1]);
      if (n == 0) {
        //User said cancel expansion.
        saySomething("Tree expansion cancelled", e);
        throw new ExpandVetoException(e);
      }
    }
    //Required by TreeWillExpandListener interface.
    public void treeWillCollapse(TreeExpansionEvent e) {
      saySomething("Tree-will-collapse event detected", e);
    }
    // Required by TreeExpansionListener interface.
    public void treeExpanded(TreeExpansionEvent e) {
      saySomething("Tree-expanded event detected", e);
    }
    // Required by TreeExpansionListener interface.
    public void treeCollapsed(TreeExpansionEvent e) {
      saySomething("Tree-collapsed event detected", e);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    //Make sure we have nice window decorations.
    JFrame.setDefaultLookAndFeelDecorated(true);
    //Create and set up the window.
    JFrame frame = new JFrame("TreeExpandEventDemo2");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Create and set up the content pane.
    JComponent newContentPane = new TreeExpandEventDemo2();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);
    //Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}





TreeExpansionListener and TreeExpansionEvent

  
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * TreeExpandEventDemo.java requires no other files.
 */
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
public class TreeExpandEventDemo extends JPanel {
  DemoArea demoArea;
  JTextArea textArea;
  final static String newline = "\n";
  public TreeExpandEventDemo() {
    super(new GridBagLayout());
    GridBagLayout gridbag = (GridBagLayout) getLayout();
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.BOTH;
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.weightx = 1.0;
    c.weighty = 1.0;
    c.insets = new Insets(1, 1, 1, 1);
    demoArea = new DemoArea();
    gridbag.setConstraints(demoArea, c);
    add(demoArea);
    c.insets = new Insets(0, 0, 0, 0);
    textArea = new JTextArea();
    textArea.setEditable(false);
    JScrollPane scrollPane = new JScrollPane(textArea);
    scrollPane
        .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    scrollPane.setPreferredSize(new Dimension(200, 75));
    gridbag.setConstraints(scrollPane, c);
    add(scrollPane);
    setPreferredSize(new Dimension(450, 450));
    setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
  }
  void saySomething(String eventDescription, TreeExpansionEvent e) {
    textArea
        .append(eventDescription + "; " + "path = " + e.getPath() + newline);
  }
  class DemoArea extends JScrollPane implements TreeExpansionListener {
    Dimension minSize = new Dimension(100, 100);
    JTree tree;
    public DemoArea() {
      TreeNode rootNode = createNodes();
      tree = new JTree(rootNode);
      tree.addTreeExpansionListener(this);
      setViewportView(tree);
    }
    private TreeNode createNodes() {
      DefaultMutableTreeNode root;
      DefaultMutableTreeNode grandparent;
      DefaultMutableTreeNode parent;
      DefaultMutableTreeNode child;
      root = new DefaultMutableTreeNode("San Francisco");
      grandparent = new DefaultMutableTreeNode("Potrero Hill");
      root.add(grandparent);
      //
      parent = new DefaultMutableTreeNode("Restaurants");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Thai Barbeque");
      parent.add(child);
      child = new DefaultMutableTreeNode("Goat Hill Pizza");
      parent.add(child);
      //
      parent = new DefaultMutableTreeNode("Grocery Stores");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Good Life Grocery");
      parent.add(child);
      child = new DefaultMutableTreeNode("Safeway");
      parent.add(child);
      grandparent = new DefaultMutableTreeNode("Noe Valley");
      root.add(grandparent);
      //
      parent = new DefaultMutableTreeNode("Restaurants");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Hamano Sushi");
      parent.add(child);
      child = new DefaultMutableTreeNode("Hahn"s Hibachi");
      parent.add(child);
      //
      parent = new DefaultMutableTreeNode("Grocery Stores");
      grandparent.add(parent);
      child = new DefaultMutableTreeNode("Real Foods");
      parent.add(child);
      child = new DefaultMutableTreeNode("Bell Market");
      parent.add(child);
      return root;
    }
    public Dimension getMinimumSize() {
      return minSize;
    }
    public Dimension getPreferredSize() {
      return minSize;
    }
    // Required by TreeExpansionListener interface.
    public void treeExpanded(TreeExpansionEvent e) {
      saySomething("Tree-expanded event detected", e);
    }
    // Required by TreeExpansionListener interface.
    public void treeCollapsed(TreeExpansionEvent e) {
      saySomething("Tree-collapsed event detected", e);
    }
  }
  /**
   * Create the GUI and show it. For thread safety, this method should be
   * invoked from the event-dispatching thread.
   */
  private static void createAndShowGUI() {
    // Create and set up the window.
    JFrame frame = new JFrame("TreeExpandEventDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // Create and set up the content pane.
    JComponent newContentPane = new TreeExpandEventDemo();
    newContentPane.setOpaque(true); // content panes must be opaque
    frame.setContentPane(newContentPane);
    // Display the window.
    frame.pack();
    frame.setVisible(true);
  }
  public static void main(String[] args) {
    // Schedule a job for the event-dispatching thread:
    // creating and showing this application"s GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        createAndShowGUI();
      }
    });
  }
}





Tree Icon Demo

  
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/**
 * A 1.4 application that requires the following additional files:
 *   TreeDemoHelp.html
 *    arnold.html
 *    bloch.html
 *    chan.html
 *    jls.html
 *    swingtutorial.html
 *    tutorial.html
 *    tutorialcont.html
 *    vm.html
 */
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.ImageIcon;
import java.net.URL;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;
public class TreeIconDemo extends JPanel 
                          implements TreeSelectionListener {
    private JEditorPane htmlPane;
    private JTree tree;
    private URL helpURL;
    private static boolean DEBUG = false;
    public TreeIconDemo() {
        super(new GridLayout(1,0));
        //Create the nodes.
        DefaultMutableTreeNode top =
            new DefaultMutableTreeNode("The Java Series");
        createNodes(top);
        //Create a tree that allows one selection at a time.
        tree = new JTree(top);
        tree.getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);
        //Set the icon for leaf nodes.
        ImageIcon leafIcon = createImageIcon("images/middle.gif");
        if (leafIcon != null) {
            DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
            renderer.setLeafIcon(leafIcon);
            tree.setCellRenderer(renderer);
        } else {
            System.err.println("Leaf icon missing; using default.");
        }
        //Listen for when the selection changes.
        tree.addTreeSelectionListener(this);
        //Create the scroll pane and add the tree to it. 
        JScrollPane treeView = new JScrollPane(tree);
        //Create the HTML viewing pane.
        htmlPane = new JEditorPane();
        htmlPane.setEditable(false);
        initHelp();
        JScrollPane htmlView = new JScrollPane(htmlPane);
        //Add the scroll panes to a split pane.
        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        splitPane.setTopComponent(treeView);
        splitPane.setBottomComponent(htmlView);
        Dimension minimumSize = new Dimension(100, 50);
        htmlView.setMinimumSize(minimumSize);
        treeView.setMinimumSize(minimumSize);
        splitPane.setDividerLocation(100); //XXX: ignored in some releases
                                           //of Swing. bug 4101306
        //workaround for bug 4101306:
        //treeView.setPreferredSize(new Dimension(100, 100)); 
        splitPane.setPreferredSize(new Dimension(500, 300));
        //Add the split pane to this panel.
        add(splitPane);
    }
    /** Required by TreeSelectionListener interface. */
    public void valueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                           tree.getLastSelectedPathComponent();
        if (node == null) return;
        Object nodeInfo = node.getUserObject();
        if (node.isLeaf()) {
            BookInfo book = (BookInfo)nodeInfo;
            displayURL(book.bookURL);
            if (DEBUG) {
                System.out.print(book.bookURL + ":  \n    ");
            }
        } else {
            displayURL(helpURL); 
        }
        if (DEBUG) {
            System.out.println(nodeInfo.toString());
        }
    }
    private class BookInfo {
        public String bookName;
        public URL bookURL;
        public BookInfo(String book, String filename) {
            bookName = book;
            bookURL = TreeIconDemo.class.getResource(filename);
            if (bookURL == null) {
                System.err.println("Couldn"t find file: "
                                   + filename);
            }
        }
        public String toString() {
            return bookName;
        }
    }
    private void initHelp() {
        String s = "TreeDemoHelp.html";
        helpURL = TreeIconDemo.class.getResource(s);
        if (helpURL == null) {
            System.err.println("Couldn"t open help file: " + s);
        } else if (DEBUG) {
            System.out.println("Help URL is " + helpURL);
        }
        displayURL(helpURL);
    }
    private void displayURL(URL url) {
        try {
            if (url != null) {
                htmlPane.setPage(url);
            } else { //null url
    htmlPane.setText("File Not Found");
                if (DEBUG) {
                    System.out.println("Attempted to display a null URL.");
                }
            }
        } catch (IOException e) {
            System.err.println("Attempted to read a bad URL: " + url);
        }
    }
    private void createNodes(DefaultMutableTreeNode top) {
        DefaultMutableTreeNode category = null;
        DefaultMutableTreeNode book = null;
        category = new DefaultMutableTreeNode("Books for Java Programmers");
        top.add(category);
        //original Tutorial
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Tutorial: A Short Course on the Basics",
            "tutorial.html"));
        category.add(book);
        //Tutorial Continued
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Tutorial Continued: The Rest of the JDK",
            "tutorialcont.html"));
        category.add(book);
        //JFC Swing Tutorial
        book = new DefaultMutableTreeNode(new BookInfo
            ("The JFC Swing Tutorial: A Guide to Constructing GUIs",
            "swingtutorial.html"));
        category.add(book);
        //Bloch
        book = new DefaultMutableTreeNode(new BookInfo
            ("Effective Java Programming Language Guide",
       "bloch.html"));
        category.add(book);
        //Arnold/Gosling
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Programming Language", "arnold.html"));
        category.add(book);
        //Chan
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Developers Almanac",
             "chan.html"));
        category.add(book);
        category = new DefaultMutableTreeNode("Books for Java Implementers");
        top.add(category);
        //VM
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Virtual Machine Specification",
             "vm.html"));
        category.add(book);
        //Language Spec
        book = new DefaultMutableTreeNode(new BookInfo
            ("The Java Language Specification",
             "jls.html"));
        category.add(book);
    }
    /** Returns an ImageIcon, or null if the path was invalid. */
    protected static ImageIcon createImageIcon(String path) {
        java.net.URL imgURL = TreeIconDemo.class.getResource(path);
        if (imgURL != null) {
            return new ImageIcon(imgURL);
        } else {
            System.err.println("Couldn"t find file: " + path);
            return null;
        }
    }
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);
        //Create and set up the window.
        JFrame frame = new JFrame("TreeIconDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Create and set up the content pane.
        TreeIconDemo newContentPane = new TreeIconDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application"s GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}





Tree Lines

  
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
public class TreeLines {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Tree Lines");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container content = frame.getContentPane();
    Box box = Box.createHorizontalBox();
    JTree tree1 = new JTree();
    tree1.putClientProperty("JTree.lineStyle", "Angled");
    JScrollPane scrollPane1 = new JScrollPane(tree1);
    tree1.setAutoscrolls(true);
    JTree tree2 = new JTree();
    JScrollPane scrollPane2 = new JScrollPane(tree2);
    box.add(scrollPane1, BorderLayout.WEST);
    box.add(scrollPane2, BorderLayout.EAST);
    frame.getContentPane().add(box, BorderLayout.CENTER);
    frame.setSize(300, 240);
    frame.setVisible(true);
  }
}





Tree open Icon

  
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.LookAndFeel;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
public class LazySample {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Lazy Example");
    Object iconObject = LookAndFeel.makeIcon(LazySample.class, "World.gif");
    UIManager.put("Tree.leafIcon", iconObject);
    Integer fifteen = new Integer(15);
    Object lazyArgs[] = new Object[] { Color.green, Boolean.TRUE, fifteen,
        fifteen };
    Object lazyDiamond = new UIDefaults.ProxyLazyValue("DiamondIcon",
        lazyArgs);
    UIManager.put("Tree.openIcon", lazyDiamond);
    JTree tree = new JTree();
    JScrollPane scrollPane = new JScrollPane(tree);
    Container contentPane = frame.getContentPane();
    contentPane.add(scrollPane, BorderLayout.CENTER);
    frame.setSize(200, 200);
    frame.setVisible(true);
  }
}





Tree Selection Row

  
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
public class TreeSelectionRow {
  public static void main(String args[]) {
    String title = "JTree Sample";
    JFrame frame = new JFrame(title);
    JTree tree = new JTree();
    TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
        JTree treeSource = (JTree) treeSelectionEvent.getSource();
        System.out.println("Min: " + treeSource.getMinSelectionRow());
        System.out.println("Max: " + treeSource.getMaxSelectionRow());
        System.out.println("Lead: " + treeSource.getLeadSelectionRow());
        System.out.println("Row: " + treeSource.getSelectionRows()[0]);
      }
    };
    tree.addTreeSelectionListener(treeSelectionListener);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}





Tree will Expand event and listener

  
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;
public class TreeExpandSample {
  public static void main(String args[]) {
    String title = ("JTree Expand Sample");
    JFrame frame = new JFrame(title);
    JTree tree = new JTree();
    TreeWillExpandListener treeWillExpandListener = new TreeWillExpandListener() {
      public void treeWillCollapse(TreeExpansionEvent treeExpansionEvent)
          throws ExpandVetoException {
        TreePath path = treeExpansionEvent.getPath();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
            .getLastPathComponent();
        String data = node.getUserObject().toString();
        if (data.equals("colors")) {
          throw new ExpandVetoException(treeExpansionEvent);
        }
      }
      public void treeWillExpand(TreeExpansionEvent treeExpansionEvent)
          throws ExpandVetoException {
        TreePath path = treeExpansionEvent.getPath();
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
            .getLastPathComponent();
        String data = node.getUserObject().toString();
        if (data.equals("sports")) {
          throw new ExpandVetoException(treeExpansionEvent);
        }
      }
    };
    tree.addTreeWillExpandListener(treeWillExpandListener);
    JScrollPane scrollPane = new JScrollPane(tree);
    frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}





Use UIManager to change the default icon for JTree

  
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
public class Main {
  public static void main(String[] argv) throws Exception {
    Icon leafIcon = new ImageIcon("leaf.gif");
    Icon openIcon = new ImageIcon("open.gif");
    Icon closedIcon = new ImageIcon("closed.gif");
    UIManager.put("Tree.leafIcon", leafIcon);
    UIManager.put("Tree.openIcon", openIcon);
    UIManager.put("Tree.closedIcon", closedIcon);
    
    JTree tree = new JTree();
    JFrame f = new JFrame();
    f.add(new JScrollPane(tree));
    f.setSize(300, 300);
    f.setVisible(true);
  }
}





Visiting All the Nodes in a JTree Component

  
import java.util.Enumeration;
import javax.swing.JTree;
import javax.swing.tree.TreeNode;
public class Main {
  public static void main(String[] argv) throws Exception {
    JTree tree = new JTree();
    visitAllNodes(tree);
  }
  public static void visitAllNodes(JTree tree) {
    TreeNode root = (TreeNode) tree.getModel().getRoot();
    visitAllNodes(root);
  }
  public static void visitAllNodes(TreeNode node) {
    System.out.println(node);
    if (node.getChildCount() >= 0) {
      for (Enumeration e = node.children(); e.hasMoreElements();) {
        TreeNode n = (TreeNode) e.nextElement();
        visitAllNodes(n);
      }
    }
  }
}