File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Swing / AWT / SWT and the fly likes JTree - Compare Nodes problem Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "JTree - Compare Nodes problem" Watch "JTree - Compare Nodes problem" New topic
Author

JTree - Compare Nodes problem

Derek Boring
Ranch Hand

Joined: Aug 15, 2006
Posts: 63
Hi everyone,

I am making a program that displays the contents of a JAR file in a JTree. The contents of the JAR are returned as an Enumeration<JarEntry> and each name has the full path of the file. Here is an example:

tree name string
+-folder1
| +-file1.txt folder1/file1.txt
+-folder2
+-folder3
| +-file2.txt folder2/folder3/file2.txt
| +-file3.txt folder2/folder3/file3.txt
+-file4.txt folder2/file4.txt

The problem I'm having is checking if a node already exists in the tree. For example, folder3 has multiple files in it. When I get to file3.txt I want to find the node that folder 3 is at and add file3.txt as a child node to folder3. However, when I try to check if two nodes are equal, it always returns false unless the pointers point to the exact same node object. I've also tried the .equals(otherNode) method and I've tried comparing the UserObjects of the nodes too and still the same story.

I'm using the DefaultMutableTreeNode object for my nodes and a JTree for my tree. The UserObjects are strings defined at the instantiation of the node object. If you need more information or anything else just ask.

Thanks in advance for all your help guys.


Life is 10% what happens and 90% how you react to it.
Attitude is everything.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19692
    
  20

DefaultMutableTreeNode doesn't override equals, so it still uses the Object way: using ==.

Create a subclass (or a complete new TreeNode implementation) that overrides equals to compare the object values.

I wrote a class that uses a SortedSet as a backing collection; if an "existing" child node was added to a node the two nodes were merged. It's not that complex to create a similar class yourself.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Derek Boring:
I've tried comparing the UserObjects of the nodes too and still the same story.


What type of objects are you using for the user objects? These are under your control, so you should be able to control how equals() works on them.


bitguru blog
Derek Boring
Ranch Hand

Joined: Aug 15, 2006
Posts: 63
Thanks guys. I'm using string objects for the userobjects and I just figured out that the toString() method returns the string value, so I just compared those instead of the whatever the getUserObject() methods returned. Thanks for the help guys.

I now have another problem though. If this should be put into a new topic, just let me know.

I need to know how to clear all the nodes out of an entire tree without loosing the root node. (i.e. remove all children from the root node) I tried rootNode.removeAllChildren() but it doesn't work, all the children are still in the tree but no longer connected to the root node. Logically this seems to be the correct functionality for this method, but I want all the nodes except the root to be disposed of. After looking through some APIs it seems that the quickest way is to recreate the root node, but since you can only set the root node in the JTree's constructor, that requires recreating the JTree.

Is there a better way to do this? or do I need to modify my code to create a new JTree every time I want to clear it?
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Derek Boring:
I need to know how to clear all the nodes out of an entire tree without loosing the root node. (i.e. remove all children from the root node) I tried rootNode.removeAllChildren() but it doesn't work, all the children are still in the tree but no longer connected to the root node. Logically this seems to be the correct functionality for this method


It's hard to know what to suggest without more details. For instance, are you using DefaultTreeModel or some other class?

One thing you can try: If you're using DefaultTreeModel make sure you are calling yourModel.insertNodeInto() and yourModel.removeNodeFromParent() and that you are not calling someNode.insert() or someNode.remove() or someNode.removeAllChildren().

You can also make sure the adding/removing of nodes happens on the event tread.

(That response was mostly copied from an older thread.)

Note that the DefaultTreeModel doesn't have a method analogous to removeAllChildren() so you have to iterate through the children to remove them all. It's more work, but it will fire the correct TreeModelEvents for the display to be updated correctly. Alternatively you can fire your own event after calling rootNode.removeAllChildren(). That's what you need to do if you're not using DefaultTreeModel (presuming I've guessed your problem correctly).
[ January 19, 2008: Message edited by: Brian Cole ]
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19692
    
  20

Originally posted by Derek Boring:
Is there a better way to do this? or do I need to modify my code to create a new JTree every time I want to clear it?

If your model is a DefaultTreeModel, it has a setRoot method which you can use. Then you call its nodeStructureChanged(TreeNode node) method, which will inform the view (JTree) that the structure for the root node has changed.
Derek Boring
Ranch Hand

Joined: Aug 15, 2006
Posts: 63
All of my nodes are of type DefaultMutableTreeNode and soon will be node types that extend DefaultMutableTreeNode for custom functionality. What I was using is rootNode.removeAllChildren() This however leaves the nodes in the tree, they are just not connected to anything. It seems like what you guys are saying is I need something like this:



And then call:



Look correct?
Brian Cole
Author
Ranch Hand

Joined: Sep 20, 2005
Posts: 862
Originally posted by Derek Boring:
I was using is rootNode.removeAllChildren() This however leaves the nodes in the tree, they are just not connected to anything.


No, it should actually remove the nodes (from the TreeModel). What it doesn't do is send an event to the JTree, so the JTree doesn't realize that it needs to redraw itself.

It seems like what you guys are saying is I need something like this:



That's not what I said. To do what I said you would replace the arrowed line with

((DefaultTreeModel)myTree.getTreeModel()).removeNodeFromParent(t);

Of course that won't work if your tree model isn't a DefaultTreeModel.


And then call:



Look correct?


You don't need this code at all if you do the DefaultTreeModel.removeNodeFromParent() above, because removeNodeFromParent() does fire off TreeModelEvents.

Otherwise the purpose of calling setRoot(myRoot), even though the root is already myRoot, is to force the JTree to update. There are other ways to do this, such as calling ((DefaultTreeModel)myTree.getTreeModel()).nodeStructureChanged(myRoot), if it is needed but setRoot() is probably easiest.
Derek Boring
Ranch Hand

Joined: Aug 15, 2006
Posts: 63
Thanks, that helped alot. You guys are awesome!
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: JTree - Compare Nodes problem