Skip to main content

JXTreeTable response to TreeStructureChanged() surprising, calls TableDataChanged()

3 replies [Last post]
ceclauson
Offline
Joined: 2008-03-27
Points: 0

So this is a thread to report some very strange behavior I found in JXTreeTable, which is making a project that I'm working on very difficult. Of course, if there's a case to be made that this behavior in fact makes sense and there is some other way to do what I am trying to do, then I would welcome someone to point this out.

It seems that this issue was reported and discussed in 2007:
http://www.java.net/node/667646
(EDIT: I just skimmed this thread again, and noticed that the issue reported was the *opposite* of the one that I'm reporting, the user wanted to report a change in the number of columns, but didn't know how to do this except to call treeStructureChanged(), and noticed that this did not trigger "table structure changed", but there is a long discussion on the thread that overlaps some of the issues here, but the solution to have it trigger a table data change event I think is wrong for the reasons I describe below)

The issue is that if a treeStructureChanged() event is sent by the model to a JXTreeTable, the JXTreeTable at least some of the time triggers a JTable "table structure changed" event to implement this. The problem is that "table structure changed" causes column editors and renderers to be reset to the defaults. The fact that this has not been fixed in all this time makes me think that apparently not many people have run in to this issue, but in my application, where the tree table uses custom editors/renderers, and the structure can change in response to user event, the issue is really obvious.

It seems to me that the way to solve this is to modify the implementation of a treeStructureChanged() event so that it does not trigger "table structure changed" in the JTable. It seems like this should be possible since I believe that JTable supports events for rows added/deleted which does not reset all the columns. If the user actually does want the columns reset, there should be a different event for that.

Because I'm having to modify legacy code committed to JXTreeTable, probably I'll have to hack something around this problem. If someone sees something that I've missed and would like to point it out, I would definitely appreciate it. However, currently to me this seems like a significant problem for applications like those that I am working on.

Thanks in advance!

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ceclauson
Offline
Joined: 2008-03-27
Points: 0

I'm not sure why it didn't appear on this thread, but I got this reply in my email:

************************

Afair (didn't check, though), the current mapping is to fire a (tableModel)
structureChanged only on a treeModel.structureChanged on the root. That's the
outcome of several longish debates, no much options for the general case.
Biased me doesn't consider the current behaviour incorrect :-)

For you concrete case, you could simply disable the auto-creation of columns
on the treeTable (after all, it's a JTable :-)

Something like:

// let the auto-creation happen on setting the model
treeTable.setTreeTableModel(ttModel)
treeTable.setAutoCreateColumnsFromModel(false);
// configure the columns
...

Cheers
Jeanette

************************

Thanks for replying!

>For you concrete case, you could simply disable the auto-creation of columns
>on the treeTable (after all, it's a JTable :-)
>
>Something like:
>
>// let the auto-creation happen on setting the model
>treeTable.setTreeTableModel(ttModel)
>treeTable.setAutoCreateColumnsFromModel(false);
>// configure the columns

I gave this a try, and it is definitely an improvement, the editors/renderers are not replaced. However, the "structure changed" event still causes the column widths to reset, which isn't acceptable in the application that I am working on. I might have time later to search for a solution to this, but for now I'll have to continue to use my hacked version of the swingx library.

>Afair (didn't check, though), the current mapping is to fire a (tableModel)
>structureChanged only on a treeModel.structureChanged on the root.
Yes, I think this is true.

>That's the outcome of several longish debates, no much options for the general case.
As I mentioned earlier, my opinion is that it would be best to have an additional "table structure changed" event which is totally different from a "tree structure changed" event. This allows the model to indicate in a more finely grained way what the change is exactly that has occurred, and is consistent with how events issued by Swing UI models usually work.

It's somewhat complicated because the decision has already been made to use the existing TreeModelListener interface, but given that this can't be redone now, probably what I would do is create a TreeTableModelListener interface that extends TreeModelListener, pass that to the "addTreeModelListener()" method of TreeTableModel, and let the model implementors cast it to access the full range of operations. This would be similar to how the "Graphics" type was superceded by "Graphics2D" in the Swing graphics API to add additional operations but not break legacy code. That's just my two cents.

Thanks again.

kleopatra
Offline
Joined: 2003-06-11
Points: 0

forum is running nuts occasionally, hope this comes through ...

Certainly there might be different solutions for mapping tree --> table model notifications (there's a huge impedance mismatch), but at the end of the day a decision had to be made and that's unlikely to change - but not impossible as long as it is half-way backward compatible and doesn't break existing code :-).

Please consider an enhancement issue in the swingx issue tracker and copy your suggestion. Would be cool if you could come up with a better solution.

As to keeping editors/renderers but resetting widths: that sounds fishy - the columns shouldn't be touched at all. You might have stumbled across a bug in JXTreeTable, would be great if you would file an issue in the tracker, best with a short code example demonstrating the problem.

Thanks (and keep them coming, knowing about glitches is the first step to fixing them :-)
Jeanette

ceclauson
Offline
Joined: 2008-03-27
Points: 0

*UPDATE*

So some background: the version of the library that I am working with now is 0.9.3. When I discovered this issue, the first thing that I tried was to download the newest .jar version and see if that fixed the problem, which it didn't.

In order to work around the problem, I downloaded the source for 0.9.3, changed the source code so that it does not do a "table structure changed", but "table data changed" instead, and rebuilt the jar, and it seems to work fine now.

The only problem that I could see in applying this to the standard version of JXTreeTable is that it leaves no mechanism for the model to signal that the columns have changed. I think the right way to fix this is to add a "table structure changed" event to the listener interface and delegate that call to the same method in JTable, rather than trying to handle it as a special case of "tree structure changed".

Thanks