Dawson
Dawson

Reputation: 457

Refresh JTree without collapsing

I have a tree with a JButton as a node.

I want to be able to toggle the buttons name and the method called by it between two sets of values.

I think this would work fine if the tree would refresh after each button click.

This method seems to work, but it collapses the tree on refreshing, I need the tree to stay open.

I'm not adding/deleting a node so many of the other methods I've seen online do not apply.

public void valueChanged(TreeSelectionEvent e) 
{
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
            tree.getLastSelectedPathComponent();

    /* if nothing is selected */ 
    if (node == null) return;

    /* retrieve the node that was selected */ 
    Object obj = node.getUserObject();
    if (obj instanceof EmployeeButton)

        EmployeeButton eb = (EmployeeButton) obj;
        if (eb.getText().contains("Add Employee"));
        {
            eb.setText("Remove Employee");
            addEmp(eb.point);
        }
        if (eb.getText().contains("Remove Employee"));
        {
            eb.setText("Add Employee");
            delEmployee(eb.point);
        }
}; 

Upvotes: 1

Views: 342

Answers (1)

Freek de Bruijn
Freek de Bruijn

Reputation: 3622

Using the excellent answer from Jakub Zaverka to a somewhat similar question (Compound JTree Node allowing events to pass through to objects underneath), you could do something like this:

// Class RefreshTree.java:

import javax.swing.*;
import javax.swing.tree.*;

public class RefreshTree {
    public static final String ADD_EMPLOYEE = "Add Employee";
    public static final String REMOVE_EMPLOYEE = "Remove Employee";

    public static void main(final String[] arguments) {
        new RefreshTree().launchGui();
    }

    private void launchGui() {
        final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("root");
        rootNode.add(new DefaultMutableTreeNode(ADD_EMPLOYEE));
        rootNode.add(new DefaultMutableTreeNode(ADD_EMPLOYEE));
        rootNode.add(new DefaultMutableTreeNode(ADD_EMPLOYEE));

        final JTree tree = new JTree(rootNode);
        tree.setEditable(true);
        tree.setCellRenderer(new ButtonCellRenderer());
        tree.setCellEditor(new ButtonCellEditor());

        final JFrame frame = new JFrame("Refresh JTree with JButton");
        frame.getContentPane().add(new JScrollPane(tree));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setBounds(400, 200, 600, 600);
        frame.setVisible(true);
    }
}


// Class ButtonCellEditor.java:

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

public class ButtonCellEditor extends AbstractCellEditor implements TreeCellEditor {
    private JButton button;

    public ButtonCellEditor() {
        button = new JButton(RefreshTree.ADD_EMPLOYEE);
        button.addActionListener(actionEvent -> {
            final boolean add = RefreshTree.ADD_EMPLOYEE.equals(button.getText());
            if (add)
                System.out.println("Call addEmp(eb.point)");
            else
                System.out.println("Call delEmployee(eb.point)");
            button.setText(add ? RefreshTree.REMOVE_EMPLOYEE : RefreshTree.ADD_EMPLOYEE);
            stopCellEditing();
        });
    }

    @Override
    public Object getCellEditorValue() {
        return button.getText();
    }

    @Override
    public Component getTreeCellEditorComponent(final JTree tree,
                                                final Object value,
                                                final boolean isSelected,
                                                final boolean expanded,
                                                final boolean leaf,
                                                final int row) {
        button.setText(value.toString());
        return button;
    }
}


// Class ButtonCellRenderer.java:

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

public class ButtonCellRenderer extends JButton implements TreeCellRenderer {
    @Override
    public Component getTreeCellRendererComponent(final JTree tree,
                                                  final Object value,
                                                  final boolean selected,
                                                  final boolean expanded,
                                                  final boolean leaf,
                                                  final int row,
                                                  final boolean hasFocus) {
        setText(value.toString());
        return this;
    }
}

Upvotes: 1

Related Questions