刷新 JTree 而不折叠

Refresh JTree without collapsing

我有一个以 JButton 作为节点的树。

我希望能够在两组值之间切换按钮名称及其调用的方法。

我认为如果树在每次单击按钮后都会刷新,这会很好用。

This method 似乎可行,但它会在刷新时折叠树,我需要树保持打开状态。

我不是 adding/deleting 节点,所以我在网上看到的许多其他方法都不适用。

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);
        }
}; 

使用 Jakub Zaverka to a somewhat similar question (Compound JTree Node allowing events to pass through to objects underneath) 的优秀答案,你可以这样做:

// 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;
    }
}