| 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
|
 |
 |
|
|
subject: JTree: How to update nodes?
|
|
|