Search code examples
javaswingjtree

Getting the correct row position of JTree nodes


I'm working with Java's swing's JTree, and need to find the appropriate row index of the selected node within it's path. For example, when I select Polygon 2 in the picture below,

enter image description here

-and use this piece of code,

tree.getRowForPath(/*path of polygon node*/);

-I get the value 2, which is correct. However, when I select Polygon 3, I get the value 6. This is because it takes the nodes that Polygon 2 expanded into count when finding the appropriate node. I don't want this, as I need to return the value 3 when Polygon 3 is selected, regardless if any or the nodes prior are expanded or not.

I thought of looping through all nodes, finding which ones are before the row index of the selected, seeing if they're expanded, and counting how many nodes they contain. Then add that to the row returned from the method above.

The issue is I don't know how to approach this. I have some attempted spaghetti code, but I doubt that's useful.

Any help is appreciated.


Solution

  • I ended up writing a solution based off of @MadProgrammer's suggestion in his comment. I created a tree node class like so:

    public class CustomTreeNode extends DefaultMutableTreeNode {
    
        private int position;
    
        public CustomTreeNode(String text, int position){
            super(text);
            this.position = position;
        }
    
        public int getPosition(){
            return this.position;
        }
    
    }
    

    This allows me to hold the index of whatever object I want, regardless of the name (referencing @Sergiy Medvynskyy's also helpful solution).

    I initialized the objects like so (this was in a for loop):

    //root node
    CustomTreeNode polygon = new CustomTreeNode("Polygon " + (i+1), i);
    

    I used the nodes like this:

    @Override
    public void valueChanged(TreeSelectionEvent e) {
    
        TreePath[] selectedPaths = tree.getSelectionPaths();
        TreePath parentPath = tree.getClosestPathForLocation(1, 1);
    
        if (selectedPaths == null)
            return;
    
        ArrayList<Integer> validRows = new ArrayList<>();
    
        for (TreePath tp : selectedPaths){
    
            if (tp.getParentPath() != parentPath)
                continue;
    
            //get node that current selected path points too, then get the custom index of that
            CustomTreeNode selectedNode = (CustomTreeNode) tp.getLastPathComponent();
    
            System.out.println(selectedNode.getPosition());
    
            validRows.add(selectedNode.getPosition());
    
    }
    

    Notice how I'm easily able to populate the ArrayList validRows without iterating over every node and eliminating the expanded ones.