Adding and removing nodes from a JTree
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().
Comments
-
Roman Rdgz almost 2 years
I have a very basic
JTree
. As I am on a rush, I'd prefer not to useTreeModel
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 pushRemove
, 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++; } } }
-
kleopatra over 12 years+1 - ecept for the reload ;-) The model has nodesWhereInsertedRremoved/Changed - dont nail me on the eact names, though) to notify its listeners after-the-fact. Reload is the last measure, f.i. after doing complex modifications in several depths of the tree
-
Roman Rdgz over 12 yearsThanks a lot, I was making it way more complex than it really was
-
Nitesh Verma almost 11 yearsHow about deleting a child value?
-
glend over 8 yearsfor clarification; when removing nodes the
nodeChanged()
method causes buggy behaviour,reload()
works fine though. this is becausenodeChanged()
doesn't collapse trees,reload()
does.