tags:

views:

302

answers:

3

This method works as expected - it creates a JTree with a root node and two child container nodes (each with a respective leaf node):

private JComponent createSideBar()
{
    final DefaultMutableTreeNode top = new DefaultMutableTreeNode("Projects");
    final JTree tree = new JTree(top);

    DefaultMutableTreeNode project = new DefaultMutableTreeNode("project 1");
    DefaultMutableTreeNode version = new DefaultMutableTreeNode("version 1");
    project.add(version);
    top.add(project);
    TreePath treePath = new TreePath(project.getPath());
    // tree.expandPath(treePath);

    project = new DefaultMutableTreeNode("project 2");
    version = new DefaultMutableTreeNode("version 2");
    project.add(version);
    top.add(project);

    return tree;
}

In this case, the tree starts out closed. I'd like the application to start with all nodes fully expanded so I started by adding the following:

    tree.expandPath(treePath);

but when I un-comment it from the code above, the second set of child nodes don't show up, ie: Project 2 and Version 2 do not show up. In fact, all subsequently added nodes never show up.

For what its worth, I'm using JDK 1.5. From the docs, I can't seem to see any restrictions or why this method would have such ill-effects ... I'm going to try to look at the source but was hoping someone might have a good idea what and why this is expected behavior. I'm wondering if each subsequent node 'add' is somehow disallowed somehow - but I can't imagine would work for most run-time use cases.

Thanks,

-Luther

+1  A: 

If nodes are added to a node which has already been expanded, you need to reload the model.

((DefaultTreeModel)tree.getModel()).reload();

or

((DefaultTreeModel)tree.getModel()).reload(top);

This second version is more useful if you want to reload only a small part of a large tree.

Michael Myers
+2  A: 

Unfortunately, Swing is often "helpful". In this case, it is creating a model for you from the data supplied, much the same as a JList would create a model if you supplied a Vector.

JTree and accomplices (primarily the Pluggable Look & Feel) will add listeners to the model to keep informed of updates. If you just change the data behind the (implicit) model's back, nothing will get updated other than by chance.

So, what you should do is explicitly create a model. When the model data changes (always on the EDT, of course), cause the relevant event to be fired.

Tom Hawtin - tackline
+1, I didn't know that.
Michael Myers
A: 

Ah ... the model.

Your answers are elaborated on a bit here and here .... and even here.

I ended up doing something like:

DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
model.insertNodeInto(newNode, parent, index);

which keeps the model directly informed. In my case, that scales just fine.

Now, how to mark one of these as the answer!?!

Luther Baker