手动在特定行的JTree中插入节点

时间:2017-12-24 09:03:39

标签: java swing dynamic jtree

我正在使用docs.oracle.com教程中的DynamicTree和DynamicTreeDemo类。给定示例允许在所选节点上动态添加子节点。

我修改了

DefaultMutableTreeNode addObject(Object child) 

更改TreePath的功能。那就是我修复了树路径,这样每当我点击Add按钮时,它只会将子节点添加到该路径。

    Object[] o = { new DefaultMutableTreeNode("Root Node"), new DefaultMutableTreeNode("Parent 2"),
            new DefaultMutableTreeNode("Child 2") };

    parentPath = new TreePath(o);

但在我修改后,添加按钮无效。我如何解决这个问题,以便我可以通过更改代码中的路径来添加节点?

import java.awt.GridLayout;
import java.awt.Toolkit;
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.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;

public class DynamicTree extends JPanel {
protected DefaultMutableTreeNode rootNode;
protected DefaultTreeModel treeModel;
protected JTree tree;
private Toolkit toolkit = Toolkit.getDefaultToolkit();

public DynamicTree() {
    super(new GridLayout(1, 0));

    rootNode = new DefaultMutableTreeNode("Root Node");
    treeModel = new DefaultTreeModel(rootNode);
    treeModel.addTreeModelListener(new MyTreeModelListener());
    tree = new JTree(treeModel);
    tree.setEditable(true);
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setShowsRootHandles(true);

    JScrollPane scrollPane = new JScrollPane(tree);
    add(scrollPane);
}

/** Remove all nodes except the root node. */
public void clear() {
    rootNode.removeAllChildren();
    treeModel.reload();
}

/** Remove the currently selected node. */
public void removeCurrentNode() {
    TreePath currentSelection = tree.getSelectionPath();
    if (currentSelection != null) {
        DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) (currentSelection.getLastPathComponent());
        MutableTreeNode parent = (MutableTreeNode) (currentNode.getParent());
        if (parent != null) {
            treeModel.removeNodeFromParent(currentNode);
            return;
        }
    }

    // Either there was no selection, or the root was selected.
    toolkit.beep();
}

/** Add child to the currently selected node. */
public DefaultMutableTreeNode addObject(Object child) {
    DefaultMutableTreeNode parentNode = null;
    TreePath parentPath = tree.getSelectionPath();

    //////////////////////////// Modification for fixing place /////////////    

    Object[] o = { new DefaultMutableTreeNode("Root Node"), new DefaultMutableTreeNode("Parent 2"),
            new DefaultMutableTreeNode("Child 2") };

    parentPath = new TreePath(o);

    //////////////////////////// end of modification///////////////////////


    if (parentPath == null) {
        parentNode = rootNode;
    } else {
        parentNode = (DefaultMutableTreeNode) (parentPath.getLastPathComponent());
    }

    return addObject(parentNode, child, true);
}

public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent, Object child) {
    return addObject(parent, child, false);
}

public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent, Object child, boolean shouldBeVisible) {
    DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);

    if (parent == null) {
        parent = rootNode;
    }

    // It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode
    treeModel.insertNodeInto(childNode, parent, parent.getChildCount());

    // Make sure the user can see the lovely new node.
    if (shouldBeVisible) {
        tree.scrollPathToVisible(new TreePath(childNode.getPath()));
    }
    return childNode;
}

class MyTreeModelListener implements TreeModelListener {
    public void treeNodesChanged(TreeModelEvent e) {
        DefaultMutableTreeNode node;
        node = (DefaultMutableTreeNode) (e.getTreePath().getLastPathComponent());

        /*
         * If the event lists children, then the changed node is the child of the node
         * we've already gotten. Otherwise, the changed node and the specified node are
         * the same.
         */

        int index = e.getChildIndices()[0];
        node = (DefaultMutableTreeNode) (node.getChildAt(index));

        System.out.println("The user has finished editing the node.");
        System.out.println("New value: " + node.getUserObject());
    }

    public void treeNodesInserted(TreeModelEvent e) {
    }

    public void treeNodesRemoved(TreeModelEvent e) {
    }

    public void treeStructureChanged(TreeModelEvent e) {
    }
}
}





import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
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.tree.DefaultMutableTreeNode;

public class DynamicTreeDemo extends JPanel implements ActionListener {
private int newNodeSuffix = 1;
private static String ADD_COMMAND = "add";
private static String REMOVE_COMMAND = "remove";
private static String CLEAR_COMMAND = "clear";

private DynamicTree treePanel;

public DynamicTreeDemo() {
    super(new BorderLayout());

    // Create the components.
    treePanel = new DynamicTree();
    populateTree(treePanel);

    JButton addButton = new JButton("Add");
    addButton.setActionCommand(ADD_COMMAND);
    addButton.addActionListener(this);

    JButton removeButton = new JButton("Remove");
    removeButton.setActionCommand(REMOVE_COMMAND);
    removeButton.addActionListener(this);

    JButton clearButton = new JButton("Clear");
    clearButton.setActionCommand(CLEAR_COMMAND);
    clearButton.addActionListener(this);

    // Lay everything out.
    treePanel.setPreferredSize(new Dimension(300, 150));
    add(treePanel, BorderLayout.CENTER);

    JPanel panel = new JPanel(new GridLayout(0, 3));
    panel.add(addButton);
    panel.add(removeButton);
    panel.add(clearButton);
    add(panel, BorderLayout.SOUTH);
}

public void populateTree(DynamicTree treePanel) {
    String p1Name = new String("Parent 1");
    String p2Name = new String("Parent 2");
    String c1Name = new String("Child 1");
    String c2Name = new String("Child 2");

    DefaultMutableTreeNode p1, p2;

    p1 = treePanel.addObject(null, p1Name);
    p2 = treePanel.addObject(null, p2Name);

    treePanel.addObject(p1, c1Name);
    treePanel.addObject(p1, c2Name);

    treePanel.addObject(p2, c1Name);
    treePanel.addObject(p2, c2Name);
}

public void actionPerformed(ActionEvent e) {
    String command = e.getActionCommand();

    if (ADD_COMMAND.equals(command)) {
        // Add button clicked
        treePanel.addObject("New Node " + newNodeSuffix++);
    } else if (REMOVE_COMMAND.equals(command)) {
        // Remove button clicked
        treePanel.removeCurrentNode();
    } else if (CLEAR_COMMAND.equals(command)) {
        // Clear button clicked.
        treePanel.clear();
    }
}

/**
 * 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("DynamicTreeDemo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Create and set up the content pane.
    DynamicTreeDemo newContentPane = new DynamicTreeDemo();
    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();
        }
    });
}
}

1 个答案:

答案 0 :(得分:0)

您所做的修改不正确,因为通过创建一些与现有节点同名的新DefaultMutableTreeNode,新TreePath将不是同一个TreePath对象。他们的参考不一样。然后,在TreeModel中找不到您正在创建的新路径,并且您看到的结果没有任何结果。

您应该从TreeModel本身获取插入新节点的路径。例如,如果您想要将新子项添加到 Child 2 ,您可以像这样获得它的引用:

// ////////////////////////// Modification for fixing place // /////////////

Object[] o = { rootNode.getLastLeaf() }; // For you testing purposes 
                                         // this will return the Child 2" reference, 
                                         // next time it will return "New Node 2" and so on.

parentPath = new TreePath(o);

// ////////////////////////// end of modification///////////////////////

如果要在特定位置添加新节点,您应该获得对TreeModel中现有节点的引用,而不是动态TreeNode中的新节点,该节点当前不存在TreeModel

希望这有帮助。