This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Swing / AWT / SWT and the fly likes JTree: How to update nodes? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "JTree: How to update nodes?" Watch "JTree: How to update nodes?" New topic
Author

JTree: How to update nodes?

Tom Rodrigo
Greenhorn

Joined: Dec 07, 2001
Posts: 26
Hi all,
after editing a node in a jtree, how do i refresh this node so that the changes appear immediately.
tree.updateUI(); works fine, but all nodes collapse, so i want to update only the changed node (or prevent the collapse-thing).
I know there are lots of topics posted already concerning this question but i didn�t find a solution yet... [maybe because i`m new to java & couldn�t use them in the right way...]
Any ideas?
Thanks in advance!
Tom
Joe Gilvary
Ranch Hand

Joined: May 11, 2001
Posts: 152
Use DefaultTreeModel to track the changes in the
tree structure. You can add and delete nodes without
forcing the tree to collapse and redraw all nodes.
I have used code like:
// Wrap the child in a DefaultMutableTreeNode and
// add it to the tree.
// Notify the model of the change.
target.add(new DefaultMutableTreeNode(newItem));
myModel.nodeStructureChanged(target);
// Add the new child to the parent.
userObject.addChild(newItem);
This was when a new node was dropped on the tree.
By specifying in the nodeStructureChanged call
the highest level node which was directly affected
by the change, the app could avoid collapsing the
entire tree. The node target changed by getting a
new child. All of the new child's siblings changed.
But nothing above target was changed.
HTH,
Joe
Tom Rodrigo
Greenhorn

Joined: Dec 07, 2001
Posts: 26
Hey Joe,
thanks for your help! Your reply gave me some new ideas but the problem is still unsolved.
I didn�t quite understand why to add childs as I am only editing existing nodes (but may change in the future...).
myTreeModel.reload(TreeNode); and
myTreeModel.nodeStructureChanged(TreeNode);
do the same as tree.updateUI(), which means the changes are displayed but all branches collapse.
And myTreeModel.nodeChanged(TreeNode); doesn't do anything at all...
any thoughts?
TIA
Tom
Alex Ku
Ranch Hand

Joined: Jan 15, 2002
Posts: 47
Hi,
I am working on a JTree project also.
How do you edit the node? by clicking (or F2) on the node and edit? Or you change the data on somewhere and want to reflect the changes on the JTree?
Some idea on this if you know the position of the node to be changed, after do a reload, you can
childNode is the node being changed. This might not be the best idea but hope can give you some hints.
And here is my question which I posted few days ago and no one answer, yet.
My case is : When the user clicks on the node and starts editing, I want the text be highlighted as you double-click a text on a text field(the component which holds the display value of a node is, indeed, a text field). I got it working when you select the node and then press F2 to edit, but no clicking. Anyone has any idea?
Thanks
kawaii
[ January 25, 2002: Message edited by: kawaii desu ]
Joe Gilvary
Ranch Hand

Joined: May 11, 2001
Posts: 152
Tom,
Sorry I misunderstood you originally. I guess
you need to edit the icon or the text for the
TreeNode, correct?
I think you need to work with the TreeCellRenderer
classes. Take a look at the Java Tutorial section
on how to use trees, especially the cell renderer
stuff at
http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html#display
And kawaii, I would think you need to work with
a MouseListener to find the click events and
have your tree node respond. To enable right
click (mouse button number 2) editing in a tree,
I used
public void mousePressed(MouseEvent me){
if (SwingUtilities.isRightMouseButton(me)){
pcsTree.setSelectionPath(pcsTree.getPathForLocation(me.getX(), me.getY()));
pcsEditor.setItem(pcsTree.getSelected());
pcsEditor.setVisible(true);
}
}
HTH,
Joe
Tom Rodrigo
Greenhorn

Joined: Dec 07, 2001
Posts: 26
Kawaii, Joe,
many thanks for your help.
tree.scrollPathToVisible(new TreePath) doesn't change anything, but the tutorial gave me some hints which will work - although they are really complicated.
I should've mentioned [sorry, my mistake] that the data displayed by my JTree is stored in a database. One can select a node (its text is retrieved from the db), press a key or a button and - whow! - a menu appears containing even more data than the node shows. It�s possible to change the data (which may be part of the nodes text) and by clicking the 'Apply' - button, the data is saved to the db, but the nodes text is still the same. (It should have changed, because it was changed in the menu and saved to the db.)
By using MyTreeModelListener(); (thanks for the link, Joe), there is a way to solve the problem, but as already mentioned, it is not the romantic kind of way I've thought of:
I could get the data by pressing 'Apply',
format it in the nodes text way,
get the nodes position (which may be the hardest part to work through, as the listener doesn�t provide the correct path to the node),
tree.setEditable(true);
tree.startEditingAtPath(path);
insert the changed data,
tree.stopEditing();
tree.setEditable(false);
I would really appreciate every other way to achieve the node-update.
Any ideas ?
[Joe, I don�t know in which way the TreeCellRenderer classes may be useful, as I am already extending DefaultTreeCellRenderer to customize the nodes icons and there seems to be no way to change the nodes text. Any methods suggested ?]
I'll light a candle for everyone, who can help me out of this and solve the problem!
Thanks!
Tom
Joe Gilvary
Ranch Hand

Joined: May 11, 2001
Posts: 152
Well, DefaultTreeCellRenderer extends JLabel, which
does let you call setText().
When the user clicks Apply, you save something
back to the database. Presumably you also change
the tree node user object at that time.
In your TreeCellRenderer, I imagine you have overriden
public Component getTreeCellRendererComponent
for the sake of your icons. In a quick and
dirty test of this solution, I modified some
working code to look like:

in that method. The setText() is a JLabel call.
My nodes get a String by calling getTitle() on
the user object, so I had to add some support in
that class for a new boolean, updated. I do not
allow any changes to the title field to make it
back to the database, or I could update the user
object and the db, then call
setText(item.getTitle())
instead. That might be closer to what you need.
When I ran this modified code in a rudimentary test,
I saw the node labels change to be prefaced with
Updated!
and the tree expansion did not change.
HTH,
Joe
[ January 28, 2002: Message edited by: Joe Gilvary ]
Tom Rodrigo
Greenhorn

Joined: Dec 07, 2001
Posts: 26
Hi Joe [& all the others],
your assumptions are right, i am overwriting getTreeCellRendererComponent for the icons-sake.
Now, I've played with your suggestions and several other ideas and something strange happened:
By clicking 'Apply' a new CellRenderer-Object is generated and to the currently selected nodes text ' - Updated!' is added.
The strange thing is that only the size of the selected nodes label changes but not the nodes text. So there is still the old text visible, but if you select that node/text there is also the added ' - Updated!' - String marked, which is invisible.
I've tried to fix this with this.setVisible(true) , this.updateUI(), this.validate(),... no reaction.
Here is the code sequence:

Hope you have still some ideas remaining...
Thanks !
Tom
Joe Gilvary
Ranch Hand

Joined: May 11, 2001
Posts: 152
The user object is updated and the CellRenderer (a JLabel)
is updated. Now you will need to tell the tree model
that the tree node is updated.
The 1.3 Javadocs for DefaultTreeModel say to call
nodeChanged(node):
Invoke this method after you've changed how node is to be represented in the tree.

You will have to find a good place in your code for
that call. In the method we have been looking at
is not a good place. I put it in a selection listener
in my class that wraps JTree. It did not change until
I changed selection that way. (Not a problem for
me; just a rudimentary test before I proposed a
solution to you. My labels are not allowed to change.)
It should work, once you find the correct place to
make that call to your TreeModel.
HTH,
Joe
Tom Rodrigo
Greenhorn

Joined: Dec 07, 2001
Posts: 26
Hello Joe,
updating the DefaultTreeModel undos the (invisible) changes. I've put

on several places all along my code (also in the TreeSelectionListener) and when the selection changes and returns back to the edited node, the ' - Updated!' - String is gone & only the old text remains marked.
[As I'm new to Java it's possible that I didn`t find the right place for the call, so I will try it on other places & with other methods, but I doubt this will do...]
Any suggestions?
Many thanks, Joe!
Tom
Joe Gilvary
Ranch Hand

Joined: May 11, 2001
Posts: 152
Sorry, I misunderstood again.
My app will not allow changes to the title.
(I use my item.getTitle() call in the cell renderer
but item.setTitle would throw an exception here),
so I showed you an example that put temporary text
into the label.
When the user clicks your Apply button, update the
user object that supplies the text for the label.
In my example, that might be something like

if it were allowed.
In addition, if you handle the model.nodeChanged()
call in the same place, you would not need any of
the changes in the TreeCellRenderer.
Sorry about the confusion on my part. I have been
working my examples with a program that does not
match up to your needs very well.
In summary, use the event handling for the Apply
button to
1) Update your object with the user's changes
2) Persist (or prepare to persist) those changes
back to your database
3) Notify the tree model that the node has changed.
That should cover it. The tree will draw itself,
retrieving the String it needs for the Label from
your (now updated) user object. It should not collapse
any branches, and it should attempt to display the
full String as the viewable Label for the TreeCell.
(If you update the String to something very large,
the tree may not be able show the whole thing.)
Again, sorry for the misunderstanding on my part.
BTW, you helped me find a possible usability
improvement in my app. I think I will add some
sort of visual identification of edited nodes,
per session, based on the code I sent to you.
Thanks,
Joe
Tom Rodrigo
Greenhorn

Joined: Dec 07, 2001
Posts: 26
Hey Joe,
I got it!
By pressing 'Apply' the changes are saved to the database and 'newNodeString' is filled with the changed nodes text. Now call:

and everything works fine => the nodes text is updated and no branch collapses. I already tried it with valueForPathChanged(...) some time ago, but maybe I filled it with the wrong values ? Don't know...
When a node is added or removed [which happens not to often, so it�s acceptable], I still call updateUI(); [=> branches collapse; This will do it for now, but maybe I will work on this later...]
As I've read your last posting 5 minutes ago, I'm happy to know you've had the same solution in the meantime, so this might be the most common way for this problem [as i'm new to java; good to know...]
Many thanks Joe for all the support [I'll go and get the candle lit..] and good luck for your project! Have a great day!
Tom
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: JTree: How to update nodes?
 
Similar Threads
Searching a JTree
Expand Lazy Loaded JTree
JTree
JTREE Refreshing Problems!!
Lazy fetching JTree