This possible bug had me on a wild goose chase today. I am using JDK
1.5.0_02.
public void DefaultTableModel.setColumnIdentifiers(Object[])
When I call this method to change column identifiers, all my JTable row
heights are effectively reset back to the default height. This doesn't
seem like the proper result for what is supposed to be a "convenient"
feature that is "not used by JTable." (Actually, it is used for more
than just "tagging and location of columns" since it can be used to
change column header values, but that is another story.)
Here is a partial trace:
javax.swing.table.DefaultTableModel (457)
javax.swing.table.DefaultTableModel.setColumnIdentifiers() (458)
javax.swing.table.DefaultTableModel.setDataVector() (199)
javax.swing.table.AbstractTableModel.fireTableStructureChanged() (200)
javax.swing.table.AbstractTableModel.fireTableChanged(new
TableModelEvent(this, TableModelEvent.HEADER_ROW)) (280)
javax.swing.table.JTable.tableChanged() (2988)
Snippet of JTable.tableChanged():
-----------------------
public void tableChanged(TableModelEvent e) {
if (e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW)
{
// The whole thing changed
clearSelection();
checkLeadAnchor();
rowModel = null;
-----------------------
e.firstRow is set to -1 = HEADER_ROW in the TableMOdelEvent
constructor. Do we really want to set rowModel = null in response to a
setColumnIdentifiers() call? I don't think the TableModelEvent was
constructed properly, because I don't believe that
setColumnIdentifiers() changes anything but the column identifiers
(and, yes, the header values). The table data is still there, so in
fact the "whole thing" did not change.
Do you agree that this is a bug? Test code follows.
import javax.swing.*;
import javax.swing.table.*;
import java.awt.event.*;
import java.awt.*;
public class Test extends JFrame implements ActionListener {
private DefaultTableModel model;
public Test() {
model = new DefaultTableModel(null, new Object[] {"FOO", "BAR"});
JTable table = new JTable(model);
model.addRow(new Object[] {"00", "01"});
model.addRow(new Object[] {"10", "11"});
model.addRow(new Object[] {"20", "21"});
for (int row = 0; row < table.getRowCount(); row++) {
table.setRowHeight(row, 100);
}
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
JButton button = new JButton("Set Column Identifiers");
button.addActionListener(this);
getContentPane().add(button, BorderLayout.SOUTH);
pack();
}
public void actionPerformed(ActionEvent e) {
model.setColumnIdentifiers(new Object[] {"Check", "it out!"});
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Test().setVisible(true);
}
});
}
}
John McGrath - 26 May 2005 18:28 GMT
> This possible bug had me on a wild goose chase today. I am using JDK
> 1.5.0_02.
[quoted text clipped - 5 lines]
> seem like the proper result for what is supposed to be a "convenient"
> feature that is "not used by JTable."
I suspect you are using the column identifier for a different purpose than
it was intended, which is to attach objects to the columns of the table
model so that they can be used to identify the column and match them with
the corresponding TableColumns of the JTable. Generally, an identifier is
unique and does not change, so I would expect that it would be set when
the TableColumn is created and then not changed after that.
This seems to be what the author of DefaultTableModel has in mind. When
you set the ColumnIdentifiers, it initializes the columns. So if you set
them, it assumes that the entire structure of the table has changed, and
it fires a TableStructureChanged. The old columns are gone and new ones
are created.
> (Actually, it is used for more than just "tagging and location of
> columns" since it can be used to change column header values, but
> that is another story.)
To be a little more precise, JTable has a feature to automatically create
TableColumns from the TableModel. When it does this, it uses the column
identifiers for the column headers.

Signature
Regards,
John McGrath