tags:

views:

835

answers:

4

I'm writing a Java Tree in which tree nodes could have children that take a long time to compute (in this case, it's a file system, where there may be network timeouts that prevent getting a list of files from an attached drive).

The problem I'm finding is this:

  1. getChildCount() is called before the user specifically requests opening a particular branch of the tree. I believe this is done so the JTree knows whether to show a + icon next to the node.

  2. An accurate count of children from getChildCount() would need to perform the potentially expensive operation

  3. If I fake the value of getChildCount(), the tree only allocates space for that many child nodes before asking for an enumeration of the children. (If I return '1', I'll only see 1 child listed, despite that there are more)

The enumeration of the children can be expensive and time-consuming, I'm okay with that. But I'm not okay with getChildCount() needing to know the exact number of children.

Any way I can work around this?

Added: The other problem is that if one of the nodes represents a floppy drive (how archaic!), the drive will be polled before the user asks for its files; if there's no disk in the drive, this results in a system error.

Update: Unfortunately, implementing the TreeWillExpand listener isn't the solution. That can allow you to veto an expansion, but the number of nodes shown is still restricted by the value returned by TreeNode.getChildCount().

A: 

I'm not sure if it's entirely applicable, but I recently worked around problems with a slow tree by pre-computing the answers to methods that would normally require going through the list of children. I only recompute them when children are added or removed or updated. In my case, some of the methods would have had to go recursively down the tree to figure out things like 'how many bytes are stored' for each node.

Paul Tomblin
A: 

If you need a lot of access to a particular feature of your data structure that is expensive to compute, it may make sense to pre-compute it.

In the case of TreeNodes, this means that your TreeNodes would have to store their Child count. To explain it a bit more in detail: when you create a node n0 this node has a childcount (cc) of 0. When you add a node n1 as a child of this one, you n1.cc + cc++.

The tricky bit is the remove operation. You have to keep backlinks to parents and go up the hierarchy to subtract the cc of your current node.

In case you just want to have the a hasChildren feature for your nodes or override getChildCount, a boolean might be enough and would not force you to go up the whole hierarchy in case of removal. Or you could remove the backlinks and just say that you lose precision on remove operations. The TreeNode interface actually doesn't force you to provide a remove operation, but you probably want one anyway.

Well, that's the deal. In order to come up with precomputed precise values, you will have to keep backlinks of some sorts. If you don't you'd better call your method hasHadChildren or the more amusing isVirgin.

Aleksandar Dimitrov
+3  A: 

http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html#data

scroll a little down, there is the exact tutorial on how to create lazy loading nodes for the jtree, complete with examples and documentation

Lorenzo Boccaccia
A: 

There are a few parts to the solution:

  • Like Lorenzo Boccaccia said, use the TreeWillExpandListener

  • Also, need to call nodesWereInserted on the tree, so the proper number of nodes will be displayed. See this code

  • I have determined that if you don't know the child count, TreeNode.getChildCount() needs to return at least 1 (it can't return 0)

David