JTable's handling of variable height rows.

I've been working on a JTable that makes of a TextAreaRenderer that uses a JTextArea to display multi-line text columns. Since JTable doesn't honor a renderer's preferred size the row height's have to be altered by the renderer itself when it's prepared. This preparation does not happen until the row and column of that renderer become visible. Consequently, the height of rows that have not had all of their columns made visible since the last change in their data are not reported accurately. This behavior is very undesirable. For example, if a JTable is in a JScrollPane and the selection changes these erroneous row heights will be used to calculate the change needed to make the selection visible. The JScrollBar's value is then set erroneously resulting in only partially visible selections or selections off the pane.

Since the renderer simply needs to be prepared so that a proper row height can be set and doesn't need to be displayed, one possible workaround is to invoke getTableCellRenderer() yourself when the data changes or a row is added. This strategy works with existing rows, but runs into serious problems when rows are added.

The culprit seems to be JTable's use of SizeSequence. Use of a TableModelListener will result in unpredictable behavior because there is no guarantee what order listeners will be called. It is possible for the row to be added to the TableModel and recieve notification before the JTable does. The result is the SizeSequence hasn't had the entry for that row added. So if you add a TabelModelListener that prepares the renderer and sets the row height the results are unpredictable. JTable doesn't check to see if the row height being set is being set on a valid row and simply forwards it to SizeSequence. SizeSequence's documentation states that an index out of bounds has undetermined behavior. So, in other words, there's nothing stopping you from changing the height of a row that doersn't exist resulting in undetermined behavior. There doesn't seem to be any events fired by the JTable itself when a row is added, so there's no way to update the row height after the row is added to the JTable.

The logical solution might be to get the row model (SizeSequence), add the entry yourself and update it's value. However, this won't work because the JTable code will override this value anyway. In fact, since there's no guarantee of the order listeners are called the behavior would be unpredictable depending on which order they're called.

I'm not seeing any good workarounds that don't involve changing JTable and using a modified version in my application. This is of course very undesirable. I'm posting here to see if anyone has ideas and to get feedback on whether or not this should be submitted as a bug or perhaps an RFE. I'm assuming that there was a good reason they did it this way, but I don't see it and it seems to pretty much wreck true variable row heights.

[2980 byte] By [kablaira] at [2007-10-2 3:58:02]
# 1

Didn't really take the time to read your whole description of the problem. Here a a text area renderer that seems to work reasonably:

http://www.javaspecialists.co.za/archive/Issue106.html

The editor doesn't work, but the renderer might be what you want or at least give you some ideas.

camickra at 2007-7-15 23:19:40 > top of Java-index,Desktop,Core GUI APIs...
# 2
I'm long past that part. My TextAreaRenderer is much better than the one Kabutz did.
kablaira at 2007-7-15 23:19:40 > top of Java-index,Desktop,Core GUI APIs...