when to reimplement hashcode()? JTree with custom nodes, expandPath() fails

Hello,

I found thatJTree.expandPath(path) failed with my JTree consisting of custom nodes.

Here,class MyTreeNodeextends DefaultMutableTreeNode.

TreePath displayNode(MyTreeNode node){

TreePath newPath =new TreePath(node.getPath());

// for some reason this is necessary

// otherwise node does not display

tree.scrollPathToVisible (newPath);

// expand

// TODO fix bug. does not work

tree.expandPath(newPath);

// also does not work

//tree.expandPath(tree.getPathForRow(0));

// also does not work

//tree.makeVisible(newPath);

// System.out.println("tree.isExpanded(" + newPath + ") " + tree.isExpanded(newPath));

return newPath;

}

After some googling, I found this thread reporting the same problem:

http://groups.google.com/group/comp.lang.java.gui/browse_frm/thread/cf52cacb3d9b686f/49602f5d70869687#49602f5d70869687

the OP advised

"I learned not too long ago the error of my ways. I had implemented my own tree nodes (interface TreeNode) without implementing the hashCode method in the nodes. As a result, each instance of a node was interpreted as unique by tree-processing classes. The problem was solved when I implemented hashCode in every class that implemented TreeNode."

However, I reimplemented hashcode but itdid not work:

publicint hashCode(){

return myId;// myId is unique for a tree node.

}

publicboolean equals(Object arg0){

return id == ((MyTreeNode) arg0).id;

}

Anyone knows what the solution is?

thanks,

Anil

[2465 byte] By [anilp1a] at [2007-10-3 2:44:12]
# 1
expandPath and expandRow will not do anything if the last node in the path is a leaf.How about tryingTreePath newPath = new TreePath(node.getParent().getPath());
mpmarronea at 2007-7-14 20:32:37 > top of Java-index,Desktop,Core GUI APIs...
# 2

> expandPath and expandRow will not do anything if the

> last node in the path is a leaf.How about trying

>

> TreePath newPath = new

> TreePath(node.getParent().getPath());

Thanks for replying.

Yes, I was aware that expandPath() does nothing on a leaf and did try that. However, displayNode() is called on the internal nodes too so it should still work. But it does not work.

Context: I am visiting each node in the tree. If it is inside a sub-tree, expand path so it is visible.

anilp1a at 2007-7-14 20:32:37 > top of Java-index,Desktop,Core GUI APIs...
# 3

How are you creating the tree structure.? The tree model needs to be made aware of changes to nodes via

DefaultTreeModel.nodeChanged(TreeNode),

DefaultTreeModel.nodeStructureChanged(TreeNode), or

DefaultTreeModel.reload()

each time you add/remove children from a TreeNode.

Without code to look at it's just guesswork.

mpmarronea at 2007-7-14 20:32:37 > top of Java-index,Desktop,Core GUI APIs...
# 4

Here is code that works, how is yours different?

public static void main(String[] args) {

DefaultMutableTreeNode a = new DefaultMutableTreeNode("A");

DefaultMutableTreeNode b = new DefaultMutableTreeNode("B");

DefaultMutableTreeNode c = new DefaultMutableTreeNode("C");

DefaultMutableTreeNode d = new DefaultMutableTreeNode("D");

DefaultMutableTreeNode e = new DefaultMutableTreeNode("E");

DefaultTreeModel model = new DefaultTreeModel(a);

JTree tree = new JTree(model);

a.add(b);

b.add(c);

c.add(d);

d.add(e);

tree.expandPath(new TreePath(d.getPath()));

JFrame f = new JFrame("Tree Test");

f.add(tree);

f.setBounds(100,100,300,300);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.setVisible(true);

}

mpmarronea at 2007-7-14 20:32:37 > top of Java-index,Desktop,Core GUI APIs...
# 5

Thanks for replying.

1) Inserting and deleting are done thus:

treeModel.removeNodeFromParent(node);

treeModel.insertNodeInto(nodeToInsert, (MutableTreeNode) parent, parent.getIndex(node));

treeModel.insertNodeInto(nodeToInsert, (MutableTreeNode) node, node.getChildCount());

2) my tree nodes extend DefaultMutableTreeNode with their own renderer.

3) I am able to get a simple toy program that also extends DefaultMutableTreeNode, to expandPath().

I am trying to isolate the reason it is not expanding in my application.

thanks,

Anil

anilp1a at 2007-7-14 20:32:37 > top of Java-index,Desktop,Core GUI APIs...
# 6

The strange thing I am finding is - when I override hashcode() and equals() in MyTreeNode, it expands partially ie. only the first level expands. 2nd and greater levels of nesting do not expand.

Another thing I find is - I have a user object for MyTreeNode viz. VisualNode.

When I register a tree expansion listener:

tree.addTreeExpansionListener(new TreeExpansionListener() {

public void treeExpanded(TreeExpansionEvent evt) {

TreePath tp = evt.getPath();

System.out.println("Expansion event, path " + tp);

}

public void treeCollapsed(TreeExpansionEvent evt) {

TreePath tp = evt.getPath();

System.out.println("Collapse event, path " + tp );

}

});

It prints out the user object?

Expansion event, path [VisualNode@a, VisualNode@a] VisualNode@a

I wonder why it partially expands the tree, and only at the first level.

-

Anil

anilp1a at 2007-7-14 20:32:37 > top of Java-index,Desktop,Core GUI APIs...
# 7

Interestingly,

System.out.println("has tree been expanded? " + tree.hasBeenExpanded(newPath));

shows up "true" even though the internal node is still collapsed.

However, the TreeWillCollapse event listener trace does not print that it has immediately collapsed after the claimed "expanding" - ruling that out.

anilp1a at 2007-7-14 20:32:37 > top of Java-index,Desktop,Core GUI APIs...
# 8

Question: Why does it claim to have been expanded even though it is still collapsed?

> Interestingly,

> System.out.println("has tree been expanded? " +

> tree.hasBeenExpanded(newPath));

> shows up "true" even though the internal node is

> still collapsed.

> However, the TreeWillCollapse event listener trace

> does not print that it has immediately

> collapsed after the claimed "expanding" - ruling that

> out.

anilp1a at 2007-7-14 20:32:38 > top of Java-index,Desktop,Core GUI APIs...
# 9
update: As a workaround, I used the expandAll() method listed in Java Almanac to expand the entire tree - not just the subtree under that node. I was surprised to find it says that expanding must be done bottom up!-Anil
anilp1a at 2007-7-14 20:32:38 > top of Java-index,Desktop,Core GUI APIs...
# 10
Your my hero, the hashcode-equals-thing was the solution for my problem (searched about 6h)
haschibaschia at 2007-7-14 20:32:38 > top of Java-index,Desktop,Core GUI APIs...