JavaSwingJTable and TableModel: Dynamic column changes


Dynamic column changes

This text assumes you have knowledge of the basic facts of the TableColumnModel description.

Modifying the column count/structure in a TableModel

Adding and removing columns to/from a TableModel (without regarding the representation in a JTable) must be followed by sending a "table structure changed" event. This event means that all information in the TableModel must be regarded as changed. There is no event to notify only of column adding/removal or even of change of a column name.

There are two ways a JTable acts on receiving this event, depending on the its property "autoCreateColumnsFromModel". This property corresponds to the way you want the TableColumnModel handled: If true, JTable will itself update the TableColumnModel according to the model (possibly discard changes you made yourself); if false, you have to do it on your own.

JTable's column handling

Automatic handling

If the property is set to true, JTable will throw away the old TableColumns, including their information of header values, renderers, editors and widths, and create new ones with a default preferred width, no column-wise renderers and editors, and the TableModel's getColumnName() as header value.

For anything but the most simple tabular data (where the widths of the columns don't matter, and only default renderers and editors have been set on the JTable itself, this isn't desired.

This about the only place the JTable code calls getColumnName() at all.

Manual handling

With "autoCreateColumnsFromModel" set to false, JTable itself will not modify the TableColumnModel on receiving a table structure changed event.

Instead either the code that modifies the model, or, probably cleaner, a specialized TableModelListener, adds/removes TableColumns.

Removing TableColumns

If a column has been removed from the TableModel, the code must find the corresponding column in the JTable's TableColumnModel and remove it there.

int index = table.convertColumnIndexToView(<old model index>);

if (index != -1)
    table.getColumnModel().removeColumn(index);

Adding TableColumns

Adding to a general TableColumnModel can only happen at the end. If the column should be the last, you need to add a moveColumn() call afterwards.

int index = <new model index>;

TableColumn c = new TableColumn(index);
c.setHeaderValue(model.getColumnName(index));
c.setPreferredWidth(...);
// ... additional settings
c.setCellRenderer(...);

TableColumnModel columns = table.getColumnModel();
columns.addColumn(c);
columns.moveColumn(columns.getColumnCount() - 1, <desired index>); // if needed

As the columns are probably in some way reordered by the user or by explicit manipulation of the TableColumnModel, the only places that make sense in general are the beginning and the end (the latter does not require any move).


(C) 2001-2009 Christian Kaufhold (swing@chka.de)