Skip to main content

Duplicate tree node on TreeModelSupport.fireChildAdded

Please note these java.net forums are being decommissioned and use the new and improved forums at https://community.oracle.com/community/java.
3 replies [Last post]
sbozian
Offline
Joined: 2010-08-30

Hello,

To inform my JXTreeTable of a newly inserted node, I use the TreeModelSupport of AbstractTreeTableModel to fireChildAdded.

The problem is: if I do that after resetting the treetablemodel (i.e. JXTreeTable.setTreeTableModel) at some point before, I am getting a duplicate node of the one being added (appearing as a blank row).

Now if you are wondering what resetting the treetablemodel has to do with the way TreeModelSupport.fireChildAdded works, I'll tell you:

fireChildAdded will fire the added TreeModelListeners.

I noticed that the TreeModelListeners that get added to the modelSupport are the following:
1. JXTreeTable$TreeTableModelAdapter
2. BasicTreeUI$Handler
3. JXTree$XTreeModelHandler

When I reset the treetablemodel, due to removing/adding of listeners, they result in the following order:
1. JXTree$XTreeModelHandler
2. JXTreeTable$TreeTableModelAdapter
3. BasicTreeUI$Handler

While debugging, I queried the number of rows in the treetable, and I found that the duplicate row is being inserted after the last listener is fired.

To make sure, I manually reshuffled the listeners and put them back in their original order, and the duplication problem disappeared.

To workaround this issue, I built an internal tree structure in my model, which I populate as the getChild method of TreeModel gets invoked. Before firing a listener, I check: if the node already exists in my structure, this means it was already inserted by some listener, and hence I no longer fire the remaining listeners.

But this workaround prevents me of using TreeModelSupport.fireChildAdded, and forces me to manipulate the listeners myself.

Any idea about this? Your help is greatly appreciated.

Thanks a lot,
Shant

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kleopatra
Offline
Joined: 2003-06-11

sounds like you hit a bug - could you please show a short runnable example that demonstrates the problem?

Thanks
Jeanette

sbozian
Offline
Joined: 2010-08-30

Hi Jeanette,

I attached two java files - which are basically modifications of some of the files attached in SWINGX-1439, which I came across while debugging my issue and kept using.

The sample shows how resetting the treetablemodel reproduces the problem, as the reset will shuffle the order of the TreeModelListeners.

After further debugging, I reached some more precise information:
On the initial set of the model, the TreeModelListeners are added in the following order:
1. JXTree$XTreeModelHandler
2. BasicTreeUI$Handler
3. JXTreeTable$TreeTableModelAdapter

And they are retrieved and fired in the reverse order:
3. JXTreeTable$TreeTableModelAdapter
2. BasicTreeUI$Handler
1. JXTree$XTreeModelHandler

When I call treeTable.setTreeTableModel(model); the JXTree$XTreeModelHandler listener will be removed and added back, however since I am passing the same 'model' instance (and hence no firePropertyChange on TREE_MODEL_PROPERTY), the two other listeners will stay intact (they are not removed/added back).

Hence, the removing then adding of one of the listeners will shuffle their order, and hence they will be retrieved and fired in the following order:
1. JXTree$XTreeModelHandler
2. JXTreeTable$TreeTableModelAdapter
3. BasicTreeUI$Handler

And for some reason, firing them in this new order is causing a node duplication.

Hope the information was useful.

Thanks a lot,
Shant

kleopatra
Offline
Joined: 2003-06-11

thanks for the example, makes it easy to point fingers ... away from SwingX :-)

I can't reproduce a duplicate node, what I see is a gap between the first child node and the second. Fortunately (for me:-) that happens for a plain ol' JTree as well. So I'm fairly sure it's unrelated to JXTreeTable.

Your model setup looks fishy, too lazy to dig into that. Anyway, never-ever change the datastructure under the feet of the model and never-ever fire events on behalf of the model. Instead, implement (and thoroughly test - amen :-) modification methods as custom model api.

In your shoes, I wouldn't try too hard to go into the innards of the tree ui - instead, make the model well-behaved (read: make it work well in a JTree, after all, it is-a TreeModel). If that's working fine and you see a different behaviour in JXTreeTable, it will be time to revisit.

Cheers!
Jeanette