在 JTree 中添加和删除节点

发布于 2024-12-12 13:40:22 字数 4098 浏览 0 评论 0原文

我有一个非常基本的JTree。由于我很匆忙,如果不需要,我不想使用 TreeModel 。我写了一个SSCCE来暴露这个问题:

有时我会添加一个节点。其他时候我会删除它们。当我按下 Add 时,节点已正确添加。当我按下Remove时,它应该删除该节点,但事实并非如此。另外,如果我尝试添加多个节点,树将仅保留我添加的第一个节点。

我为 JTree 编写了一个更新方法,首先删除挂在根节点上的所有节点,然后查看必须创建哪些节点和子节点。

除了不使用 TreeModel 来操作树之外,我在这里做错了什么?

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;


public class TreeTest {
    private JFrame myFrame;
    private JTree myTree;
    private JButton addButton, removeButton;

    private int numberOfNodes;
    private DefaultMutableTreeNode rootNode;

    private ArrayList<String> graphicIDS;
    private ArrayList<String> graphicInfo;

    public static void main (String [ ] args){
        new TreeTest();
    }

    public TreeTest() {
        graphicIDS = new ArrayList<String>();
        numberOfNodes = 0;
        graphicInfo = new ArrayList<String>();
        graphicInfo.add("Info A");
        graphicInfo.add("Info B");
        graphicInfo.add("Info C");
        graphicInfo.add("Info D");

        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        myFrame = new JFrame("JTree test");
        myFrame.setResizable(false);
        myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.NORTH;
        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 2;
        c.insets = new Insets(5,5,5,5);

        rootNode = new DefaultMutableTreeNode("Root node");
        myTree = new JTree(rootNode);
        myTree.setPreferredSize(new Dimension(200, 500));
        panel.add(myTree, c);

        c.gridwidth = 1;
        c.gridy++;
        removeButton = new JButton("Remove");
        removeButton.setEnabled(false);
        removeButton.addActionListener(new ActionListener (){
            @Override
            public void actionPerformed(ActionEvent e) {    
                System.out.println("Removed curve "+(graphicIDS.size()));
                graphicIDS.remove(graphicIDS.size()-1);
                numberOfNodes--;
                updateMeasurementsTree();
            }
        });
        panel.add(removeButton, c);

        c.gridx++;
        addButton = new JButton("Add");
        addButton.addActionListener(new ActionListener (){
            @Override
            public void actionPerformed(ActionEvent e) {
                graphicIDS.add("Curve "+(numberOfNodes+1));
                System.out.println("Added curve "+(numberOfNodes+1));
                numberOfNodes++;
                updateMeasurementsTree();
            }
        });
        panel.add(addButton, c);

        myFrame.getContentPane().add(panel);
        myFrame.pack();
        myFrame.setVisible(true);
    }

    public void updateMeasurementsTree(){
        rootNode.removeAllChildren();

        for(int i=0; i<numberOfNodes;i++){  
            String idString = graphicIDS.get(i);
            DefaultMutableTreeNode idNode = new DefaultMutableTreeNode("Graphic "+idString);
            rootNode.add(idNode);
            int randomValue = (int) Math.floor(Math.random()*graphicInfo.size());
            String infoString = graphicInfo.get(randomValue);
            DefaultMutableTreeNode infoNode = new DefaultMutableTreeNode("Info "+infoString);
            idNode.add(infoNode);
        }
        if(numberOfNodes==0) removeButton.setEnabled(false);
        else{
            removeButton.setEnabled(true);
            expandAll();
        }
    }

    public void expandAll() {
        int row = 0;
        while (row < myTree.getRowCount()) {
          myTree.expandRow(row);
          row++;
        }
    }
}

I have a very basic JTree. As I am on a rush, I'd prefer not to use TreeModel if it is not needed. I wrote a SSCCE to expose the problem:

Sometimes I add a node. Other times I remove them. When I push Add, a node is correctly added. When I push Remove, it is supposed to remove the node, but it doesn't. Also, if I try adding more than one node, the tree stays with just the first node I added.

I wrote an update method for the JTree, where I first erase all the nodes hanging from the root node, and then I look at which nodes and sub-nodes I have to create.

What I am doing wrong here, apart from not using a TreeModel to operate into the tree?

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;


public class TreeTest {
    private JFrame myFrame;
    private JTree myTree;
    private JButton addButton, removeButton;

    private int numberOfNodes;
    private DefaultMutableTreeNode rootNode;

    private ArrayList<String> graphicIDS;
    private ArrayList<String> graphicInfo;

    public static void main (String [ ] args){
        new TreeTest();
    }

    public TreeTest() {
        graphicIDS = new ArrayList<String>();
        numberOfNodes = 0;
        graphicInfo = new ArrayList<String>();
        graphicInfo.add("Info A");
        graphicInfo.add("Info B");
        graphicInfo.add("Info C");
        graphicInfo.add("Info D");

        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        myFrame = new JFrame("JTree test");
        myFrame.setResizable(false);
        myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        c.fill = GridBagConstraints.BOTH;
        c.anchor = GridBagConstraints.NORTH;
        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 2;
        c.insets = new Insets(5,5,5,5);

        rootNode = new DefaultMutableTreeNode("Root node");
        myTree = new JTree(rootNode);
        myTree.setPreferredSize(new Dimension(200, 500));
        panel.add(myTree, c);

        c.gridwidth = 1;
        c.gridy++;
        removeButton = new JButton("Remove");
        removeButton.setEnabled(false);
        removeButton.addActionListener(new ActionListener (){
            @Override
            public void actionPerformed(ActionEvent e) {    
                System.out.println("Removed curve "+(graphicIDS.size()));
                graphicIDS.remove(graphicIDS.size()-1);
                numberOfNodes--;
                updateMeasurementsTree();
            }
        });
        panel.add(removeButton, c);

        c.gridx++;
        addButton = new JButton("Add");
        addButton.addActionListener(new ActionListener (){
            @Override
            public void actionPerformed(ActionEvent e) {
                graphicIDS.add("Curve "+(numberOfNodes+1));
                System.out.println("Added curve "+(numberOfNodes+1));
                numberOfNodes++;
                updateMeasurementsTree();
            }
        });
        panel.add(addButton, c);

        myFrame.getContentPane().add(panel);
        myFrame.pack();
        myFrame.setVisible(true);
    }

    public void updateMeasurementsTree(){
        rootNode.removeAllChildren();

        for(int i=0; i<numberOfNodes;i++){  
            String idString = graphicIDS.get(i);
            DefaultMutableTreeNode idNode = new DefaultMutableTreeNode("Graphic "+idString);
            rootNode.add(idNode);
            int randomValue = (int) Math.floor(Math.random()*graphicInfo.size());
            String infoString = graphicInfo.get(randomValue);
            DefaultMutableTreeNode infoNode = new DefaultMutableTreeNode("Info "+infoString);
            idNode.add(infoNode);
        }
        if(numberOfNodes==0) removeButton.setEnabled(false);
        else{
            removeButton.setEnabled(true);
            expandAll();
        }
    }

    public void expandAll() {
        int row = 0;
        while (row < myTree.getRowCount()) {
          myTree.expandRow(row);
          row++;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

爱*していゐ 2024-12-19 13:40:22

我不知道你为什么要删除并重新创建所有节点。

更新应始终通过模型完成。您有多种选择:

直接更新模型:

DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
model.insertNodeInto(new DefaultMutableTreeNode("another_child"), root, root.getChildCount());

更新树节点,然后通知模型:

DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
root.add(new DefaultMutableTreeNode("another_child"));
model.reload(root);

这同样适用于删除节点。

DefaultTreeModel 有一个 removeNodeFromParent(...) ,它将直接更新模型。

或者您可以使用 DefaultMutableTreeNode 类的 remove(...) 方法;在这种情况下,您需要执行reload()

I don't know why you are deleting and recreating all the nodes.

Update should always be done through the model. You have a couple of choices:

Update the model directly:

DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
model.insertNodeInto(new DefaultMutableTreeNode("another_child"), root, root.getChildCount());

Update the tree nodes and then notify the model:

DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
root.add(new DefaultMutableTreeNode("another_child"));
model.reload(root);

The same applies for removing nodes.

The DefaultTreeModel has a removeNodeFromParent(...) which will update the model directly.

Or you can use the remove(...) method of the DefaultMutableTreeNode class; in which case you would need to do the reload().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文