JTree programatically selecting a leaf node

allmer
allmer used Ask the Experts™
on
Hi Experts,
I constructed a JTree with some data in it.
3 node types: root, ProjectNode, and leaf (string)
I would like to retrieve a leaf's treepath so that I can select it in the JTree.
I can do it for the nodes immediately following root but I couldn't find how to do it for the leaves.

The code below seems to work fine and I get the project node selected.
Now below that are leaves one of which I would like to have selected instead of the project node.

Any ideas?
TreePath tp = projectTree.getNextMatch("someString",0,Position.Bias.Forward);
projectTree.setSelectionPath(tp);
projectTree.expandPath(tp);
//Here I need to get the leaf with the name "x" for instance.
//that one should then be selected instead of the parent as currently
projectTree.setSelectionPath(tp);
projectTree.scrollPathToVisible(tp);
projectTree.repaint();

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Have you tried the JTree.getNextMatch(String, Position.Bias) method? I think it may be what you're looking for.

E.g.

tp = projectTree.getNextMatch("x",Position.Bias.Forward);

Assuming that the name "x" is unique.

Hope this helps.

Author

Commented:
x is unique within the node.

If you check my code above I am using getNextMatch.
Maybe I am missing something here but it only selects the nodes directly following root
and I was not able to select their children.

Does this work for you?
Then my problem must be elsewhere.
A TreePath for a given node encapsulates the path from the root and a list of it children. It doesn't provide direct access to grandchildren and other descendants. In order to access these you need to traverse the sub-tree in the same way that you've traversed the root.

Tree traversal is usually done recursively, but can be done iteratively. Alternatively, if you know in advance (and you're confident this will never change) that your tree will have a depth of three. This can be done without recursion or iteration.
C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

Author

Commented:
Sounds great.
Lines 3 and 5 in the code above show where I am stuck in trying the iterative approach.
tp points to a node which contains the leaves that I am interested in.
The only problem is to get a treepath to one of the children.
How can I do that?
To iterate over a tree, first get the root node then access the children using an appropriate method. I've used the getChildAt(int) method in my example code below. As you iterate you can build up the path as you go.

Remember, when traversing a tree looking for a node, that you are actually traversing the model used by the Swing component, not the swing component itself. Therefore you get the first node from the model and its path from the tree component.

Hope this helps.
// Get Root Node from the model ...
TreeNode rootNode  = (TreeNode)model.getRoot();
// ... and its path in the tree from the tree.
TreePath path = new TreePath(rootNode);
  
// Iterate over the roots children (projects?)
for(int i=0; i<rootNode.getChildCount(); i++) {
  TreeNode child = rootNode.getChildAt(i);
  if(child.equals(myProject)) { //you have project objects, right?
    path = path.pathByAddingChild(child);
    // Iterate of the project's children (root's grandchildren)
    for(int j=0; j<child.getChildCount(); j++) {
      TreeNode grandchild = child.getChildAt(j);
      if(grandchild.toString().equals("someString")) {
        path = path.pathByAddingChild(grandchild);
        tree.expandPath(path);
        tree.setSelectionPath(path);
        break;
      }
    }
    break;
  }
}

Open in new window

Just to correct myself above:

The a path is independent of both model and component. A model knows how to produce a well formed path and a tree component knows how to interpret one, but a TreePath object is not connected (by reference) to either!

Also, my solution uses a JTree object named tree, but I'm sure you realise that.

Have fun!

Author

Commented:
Unfortunately this didn't work for me for some internal reasons about updating tree and user object which at that point are not really equal :(

Slightly modifying your code did the trick for me however :)

Since the suffix of the node changed I just looked for the prefix et voila.

Thank you for your help!
private TreePath getTreePath() {
        // Get Root Node from the model ...
        TreeNode rootNode  = (TreeNode)projectTree.getModel().getRoot();
        // ... and its path in the tree from the tree.
        TreePath path = new TreePath(rootNode);
        // Iterate over the roots children (projects?)
        for(int i=0; i<rootNode.getChildCount(); i++) {
            TreeNode child = rootNode.getChildAt(i);
            if(child.toString().startsWith(selProject.getName())) { //you have project objects, right?
                path = path.pathByAddingChild(child);
                // Iterate of the project's children (root's grandchildren)
                for(int j=0; j<child.getChildCount(); j++) {
                    TreeNode grandchild = child.getChildAt(j);
                    if(grandchild.toString().equals(selBlastRes.getID())) {
                        path = path.pathByAddingChild(grandchild);
                        return(path);
                    }
                }
                break;
            }
        }
        return(null);
    }

Open in new window

Excellent, we can both get on with some work now :-)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial