从 JTree 添加和删除节点
Posted
技术标签:
【中文标题】从 JTree 添加和删除节点【英文标题】:Adding and removing nodes from a JTree 【发布时间】:2011-12-17 05:58:07 【问题描述】:我有一个非常基本的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++;
【问题讨论】:
“匆忙”可能会让你慢下来;正如@camickr 所建议的那样,使用该模型是正确的方法。 +1,顺便说一句,一个完整的例子。 匆忙与否,如果您更改其脚下的节点,您必须通知模型。没办法。 @camickr 显示,你怎么做,用我的评论装饰:-) 【参考方案1】:我不知道您为什么要删除并重新创建所有节点。
更新应始终通过模型完成。您有两种选择:
直接更新模型:
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()。
【讨论】:
+1 - 接受重新加载 ;-) 模型有 nodesWhereInsertedRremoved/Changed - 不过不要把我钉在 eact 名称上)在事后通知它的听众。重新加载是最后的措施,f.i.在树的几个深度进行复杂修改后 非常感谢,我让它变得比实际复杂得多 删除一个子值怎么样? 澄清一下;删除节点时,nodeChanged()
方法会导致错误行为,但reload()
可以正常工作。这是因为nodeChanged()
不会折叠树,reload()
会。以上是关于从 JTree 添加和删除节点的主要内容,如果未能解决你的问题,请参考以下文章