Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding and removing nodes from a JTree

Tags:

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++;
        }
    }
}
like image 369
Roman Rdgz Avatar asked Oct 28 '11 11:10

Roman Rdgz


1 Answers

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().

like image 58
camickr Avatar answered Oct 14 '22 04:10

camickr