Wednesday, February 3, 2010

Stupid JXTreeTable Tricks

For one project for one of my clients, I've been using the new SwingX JXTreeTable. It works. Not sure if it is all that much better than some of the earlier code you'll find on the web, but it basically works. And I never used tree tables much before, so, being "new" is not an issue.  Now, it's a bit offputting to look at the source code and see two data model adapter classes and four TreeTableHacker classes, most of which have comments like:

     * Temporary class to have all the hacking at one place. Naturally, it will
     * change a lot. The base class has the "stable" behaviour as of around
     * jun2006 (before starting the fix for 332-swingx).

or

     * Note: currently this class looks a bit funny

or, my favorite

     * A more (or less, depending in pov :-) aggressiv hacker.

Anyway, I found a few weird bugs or features that cost me some hours and were easily fixed.

1)  JXTreeTable ignores your attempts to resize the columns.  You can resize them, but as soon as any of the table data changes, it takes over like a bad episode of Twilight Zone and ignores your settings.  After an hour of debugging to convince myself that my code to resize the columns was really working, and trying every possible combination of  setMinWidth(), setWidth, and/or setPreferredWidth(), a little Googleing found this thread.  When changing the content of the table, JXTreetable always recreates the columns, even in the most common case where the number of columns hasn't changed.  Silly.  Anyway, you can complain about their design. or you can simply add this line of code somewhere:

setAutoCreateColumnsFromModel(false);

2) JXTreeTable messes with the colors of your Renderers.  If you are used to "traditional" JTable Renderers, you are in for a surprise as JXTreetable will, by default, apply one of their newfangled Highlighters to your renderer.  (For the record, Highlighters look like a good idea, but forcing them on you isn't)  Here is part of a comment from JXTable source:

     * Client code which solves the problem at the core (that is in a
     * well-behaved DefaultTableCellRenderer) can disable the hack
     * by removing the client property or by subclassing and override this
     * to do nothing.

So, lets review.  Well-behaved code must go out of it's way to avoid getting broken, while poorly written code is automatically "fixed".  Seems bass-ackwards to me.  I guess I have to start writing lousy, ill-behaved renderers.  :-)

Anyway, you can get around this issue by adding this line to your code:

putClientProperty(USE_DTCR_COLORMEMORY_HACK, null);

(the "null" could also be Boolean.FALSE as well).

Hope this helps and save you some time.