The Convert’s Guide to Java Swing: JTree

This is several of the common code snippets for the Swing JTree component in Java.

Make root visible (or not)

jTree1.setRootVisible(false);

Show/hide the handle of the root node

jTree1.setShowsRootHandles(false);

Set Displayed Node Height

jTree1.setRowHeight(60);

Expand/Collapse node path

TreeNode[] pPath = ((DefaultMutableTreeNode)jTree1.getModel().getRoot()).getPath(); //just an example Node
TreePath path = new TreePath(pPath);

jTree1.expandPath(path);

jTree1.collapsePath(path);

Scroll Node to be visible

TreeNode[] pPath = ((DefaultMutableTreeNode)jTree1.getModel().getRoot()).getPath(); //just an example Node
TreePath path = new TreePath(pPath);

jTree1.scrollPathToVisible(path);

Set the object class type for the Nodes

It is whatever you pass to node.setUserObject() .... the toString() is what is displayed for the Node

Update the UserObject value of a Node

node.setUserObject("UPDATED"); //uses toString() of the user object as text for Node
jTree1.repaint();

Find Node by User Object

Start Editing a Node (programmically)

jTree1.setEditable(true); // must be called at some point before the following code

TreeNode root = (TreeNode)jTree1.getModel().getRoot();
DefaultMutableTreeNode theNode = (DefaultMutableTreeNode)root.getChildAt(1).getChildAt(1); // example node to edit

TreePath path = new TreePath(theNode.getPath());
jTree1.startEditingAtPath(path);

Stop editing programmically (accept the current edit)

jTree1.stopEditing(); //works for DefaultTreeCellEditor (look at custom editor for more details)

Cancel editing programmically (discard the current edit)

jTree1.cancelEditing(); //works for DefaultTreeCellEditor (look at custom editor for more details)

Get Node Path

TreeNode root = (TreeNode)jTree1.getModel().getRoot();
DefaultMutableTreeNode theNode = (DefaultMutableTreeNode)root.getChildAt(1).getChildAt(1);
TreePath path = new TreePath(theNode.getPath());

Is a node fully expanded

jTree1.isVisible(nodePath);

Scroll to Node on expansion (look at setScrollsOnDemand)

Number of mouse clicks for editing

//Default is three clicks in TreeCellEditor->isCellEditable->canEditImmediately

((DefaultCellEditor)jTree1.getCellEditor()).setClickCountToStart(4);

Number of mouse clicks for expansion

jTree1.setToggleClickCount(6); //default is 2

Is path selected

TreeNode[] pPath = ((DefaultMutableTreeNode)jTree1.getModel().getRoot()).getPath();
TreePath path = new TreePath(pPath);

boolean selected = jTree1.isPathSelected(path);

Expand/Collapse Root

TreeNode[] pPath = ((DefaultMutableTreeNode)jTree1.getModel().getRoot()).getPath();
TreePath path = new TreePath(pPath);
jTree1.expandPath(path);
jTree1.collapsePath(path);

Add Child Node

DefaultMutableTreeNode node = new DefaultMutableTreeNode("The user object");
((DefaultMutableTreeNode)jTree1.getModel().getRoot()).add(node);
((DefaultTreeModel)jTree1.getModel()).reload();

Remove Child Node

TreeNode node = ((DefaultMutableTreeNode)jTree1.getModel().getRoot()).getFirstChild();

((DefaultMutableTreeNode)jTree1.getModel().getRoot()).remove((DefaultMutableTreeNode)node);
((DefaultTreeModel)jTree1.getModel()).reload();

Select a Node

TreeNode[] pPath = ((DefaultMutableTreeNode)jTree1.getModel().getRoot()).getPath(); //example Node
TreePath path = new TreePath(pPath);
jTree1.addSelectionPath(path);

Set Node Selection Mode

//TreeSelectionModel.SINGLE_TREE_SELECTION - Allow single Node selections
//TreeSelectionModel.CONTIGUOUS_TREE_SELECTION - Allow for a selection range - if RowMapper instance is set appropriately
//TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION - Allow for multiple Node selections (default)

jTree1.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

Set Renderer (predefined)

jTree1.setCellRenderer(new DefaultTreeCellRenderer()); //default that is extended from a JLabel

Set Renderer (custom)

jTree1.setCellRenderer(new TreeCellRenderer() {
    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
        JLabel label = new JLabel();
        label.setText(value.toString());
        return label;
    }
});

Disable Editing

jTree1.setEditable(false);

Set an Editor (predefined)

jTree1.setEditable(true); //may need to be called, but probably not

jTree1.setCellEditor(new DefaultCellEditor(new JTextField())); // default

jTree1.setCellEditor(new DefaultCellEditor(new JComboBox<>(new String[]{"cats1", "cats2", "cats3"}))); // combobox

jTree1.setCellEditor(new DefaultCellEditor(new JCheckBox())); // checkbox

Set an Editor (custom)

jTree1.setEditable(true); //may need to be called, but probably not

DefaultTreeCellEditor editor = new DefaultTreeCellEditor(jTree1, (DefaultTreeCellRenderer)jTree1.getCellRenderer()){

    JComboBox<String> comboBox = new JComboBox<>(new String[]{"cats and more1", "cats and more2", "cats and more3"});

    @Override
    public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
        
        comboBox.setSelectedItem(value);
        return comboBox;
    }

    @Override
    public Object getCellEditorValue() {
        return comboBox.getSelectedItem(); //return the combobox current value
    }

    @Override
    public boolean isCellEditable(EventObject event) {
        if (event != null) {
            if (event instanceof MouseEvent) {
                if (((MouseEvent) event).getClickCount() == 4) { //four clicks to start editing
                    return true;
                }
            }
            return false;
        }
        return true;
    }
};
jTree1.setCellEditor(editor); //also need to add "pressing enter" and "focus lost" to stop editing ... if you want

Optimize the model for large data sets

Events

JComponent
Container
Component