Creating Dynamic JTrees (Controlling Root Node Visibility) - java

I have a question about how to dynamically generate JTrees. Is there a way to set the Root Node invisible without making its children invisible too? I have tried to do the following but it shows all nodes as invisible. Keep in mind that I want to add and remove children of the Root Node at any point in time. I've added comments so you can follow what I intend to do. Let me know if they are doing something I dont need, as I am new to JTrees and don't know the conventions. I would also like to be able to select multiple children for the listener.
DefaultMutableTreeNode rootNode;
rootNode = new DefaultMutableTreeNode(); //I want this invisible.
DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
JTree tree = new JTree(treeModel);
treeModel.addTreeModelListener(this);
tree.setRootVisible(false); // Sets everything invisible
tree.setEditable(true); //makes tree dynamic
tree.setShowsRootHandles(true); //supposedly allows you to see the children of the nodes.
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
//I would like the line above to be multi-select; however, this doesn't seem to be an option.
DefaultMutableTreeNode table = new DefaultMutableTreeNode( "table1");
rootNode.add(book);
DefaultMutableTreeNode value = new DefaultMutableTreeNode( "value");
table.add(value);
In the above example. Nothing is shown and when I remove the "tree.setRootVisible(false)" everything is visible including the node.

A very late answer, but I have just had the same problem.
Ensure to expand your root node, so that its children become visible :
yourTree.expandPath(new TreePath(root.getPath()))

I'd say the difference between the code in the question and in the TreeDemo is that the tree demo creates and adds all its nodes before creating the actual tree. If the nodes are to be added dynamically (after the tree is created) it should be done through the TreeModel. Otherwise no events saying the tree has changed will be generated. At least that is what the tutorial seems to say about editing the node's "content", might be the same issue:
Note that although DefaultMutableTreeNode has methods for changing a
node's content, changes should go through the DefaultTreeModel cover
methods. Otherwise, the tree model events would not be generated, and
listeners such as the tree would not know about the updates.
Someone's solution

Works fine for me. I based my tests on the TreeDemo from the Swing tutorial on How to Use Trees. Compare your code with the tutorial code to see what the difference is.

A very late answer also, I'm a java beginner and had the same problem so it may help.
setRootVisible(false) also hides all nodes for me so I added setShowsRootHandles(true) to show all nodes :
tree.setRootVisible(false);
tree.setShowsRootHandles(true)
I hope it helps !
https://docs.oracle.com/javase/tutorial/uiswing/components/tree.html#display

Related

Select the TreeNode before (java swing, tree)

I am looking for a way to select the TreeNode before the actually selected node (if no Node is selected, the first Node AFTER the root should be selected) on Button click. I am basically having a Hashtable ht and a JTree filled with nodes (all Nodes allowing Children).
Once i click a node, i want to look up in the Hashtable for that Object and the system should write something like "You selected the 'Object.name'". Then the user should be able to click a JButton and select the node before the clicked node. Of course there should also be this line with an updated 'Object.name'. Maybe there is even a way to update the GUI of the tree, so that the other TreeNode is shown as selected.
I have been trying around for quite a while with the treePath-Methods of the selectionModel and the TreeNodes (e.g. saving them in Lists and trying to select the Element before), but nothing seems to work. I am also not finding anything useful on Google or StackOverflow. I was thinking that it might work somehow with the getPreviousSibling-Method from the DefaultMutableTreeNode?
Last thing I tried:
DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode();
treeNode = (DefaultMutableTreeNode) getLastSelectedPathComponent();
setSelectionPath(new TreePath(((DefaultTreeModel) treeModel).getPathToRoot(treeNode.getPreviousSibling())));
Unfortunately I keep getting a NullPointerException:
in line 2 of this snippet (although I selected another TreeNode before, wich has a sibling before).
Can anyone please tell me what I did wrong or tell me what other way might work? :D If you need more information please have no regard in asking me.

Java: How to select all descendants of a given ancestor on the Jtree?

I would like to select an ancestor DefaultMutableTreeNode and get all descendant DefaultMutableTreeNode of this ancestor in the JTree.
I am using TreeSelectionListener to catch selection event on the current JTree.
Basically, what I would like to be able to do is, select an ancestor node, and be able to copy it's descendant tree into another ancestor.
You should be able to walk the subtree recursively through the children() of the DMTN.
FWIW:
Maybe this will help a little, but ExampleDepot is a good site for Java example code, and they have a lot of Swing examples.
Here is a link to their set of JTree examples. I hope you find what you need.
http://www.exampledepot.com/egs/javax.swing.tree/pkg.html

expand Jtree at last modified area?

I am using dom4j to create a DocumentTreeModel from a dom4j document.
I display this DocumentTreeModel inside JScrollPane.
I have a button that adds a new node to the dom4j document, and recreates the DocumentTreeModel
I am using getPathForRow but this seems pretty limited. I need to be able to work with multiple tree depth. Basically looking for something like tree.getPathOfLastModifiedChildrensParent()
onAddNewNodeButtonClickEventFired {
dom4jdocument.addElement( "1" );
tree.setModel(new DocumentTreeModel(dom4jdocument));
tree.expandPath(tree.getPathForRow(1));
}
Basically I am trying to get the Jtree to redraw the document everytime document is edited.
Seeing you setting a new model whenever you edit the document looks like you still don't have the notification running, right? If so, you don't need any special method on the JTree - what you need is a well-behaved implementation of TreeModel ;-)
Just for fun, I looked up the DocumentTreeModel: that's an extremely small cover on top of DefaultTreeModel with no support whatever to glue changes in the Document to changes in the DocumentTreeModel. The fact that the Leaf-/BranchTreeNode implement TreeNode only (as opposed to going a step further and implement MutableTreeNode) even disables the models helper methods to insert/remove node. Short story: all the hard work is left to you.
Basically, you have to make the treeModel aware of any change in the underlying Document. Something like (pseudo-code):
DocNode newElement = document.addElement(...)
DocNode parentElement = newElement.getParent();
// walk the tree until you find the TreeNode which represents the DocNode
BranchTreeNode root = treeModel.getRoot();
BranchTreeNode parentNode = null;
forEach (root.child)
if child.getXMLNode().equals(parentElement)
parentNode = child;
// now find the childNode which corresponds to the new element
forEach (parentNode.child)
if (parentNode.child.getXMLNode().equals(newElement)
childNode = child;
// now notify the treeModel that an insertion has happened
treeModel.nodesWhereInserted(parentNode, childNode ...)
Hmm ... in your shoes I would look for a more comfortable implementation, can't believe that there isn another implementation around somewhere?
CU
Jeanette
Try - tree.revalidate();
It should refresh the component tree.

Add 'expand' button to JTree node that has no children?

I'd like to add the 'expand' button to my JTree's nodes to indicate that they are expandable. The catch is that they have no children until the user clicks on them (due to processing that happens in the background).
Is there any way I can set a node as a parent or having children without it actually having children?
Thanks
It's possible using your own DefaultMutableTreeNode implementation overriding isLeaf():
Returns true if this node has no children.
Swing Tutorial: JTree explains it under 4.1 Dynamic Tree.
Have a fake child/child count and replace it with real children using TreeWillExpandListener

Java Swing JTree Expansion

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
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.
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.
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!?!

Categories

Resources