-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
6
-
x86
-
windows_xp
FULL PRODUCT VERSION :
java version "1.6.0-ea"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b29)
Java HotSpot(TM) Client VM (build 1.6.0-ea-b29, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
The JTable(TableModel) constructor passes null to the JTable(TableModel, TableColumnModel, ListSelectionModel) constructor.
According to the javadoc for that constructor:
The autoCreateColumnsFromModel flag is set to false if cm is non-null, otherwise it is set to true and the column model is populated with suitable TableColumns for the columns in dm.
The autoCreateColumnsFromModel flag is in fact set to true, but the column model is not auto-populated (ie: neither setAutoCreateColumnsFromModel or createDefaultColumnsFromModel is called). createDefaultColumnsFromModel is called from setAutoCreateColumnsFromModel and from tableChanged.
I believe the correct solution would be to call setAutoCreateColumnsFromModel instead of just setting the flag.
If you create an extension to JTable that implements TableModelListener, then your implementation has to be sure to call the default JTable.tableChanged method first or the TableModel and TableColumnModel do not match and it throws an ArrayIndexOutOfBoundsException when trying to access the columns.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Extend JTable, implement TableModelListener. Do NOT call super.tableChanged from your tableChanged method, but instead iterate through the TableColumnModel columns.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TableColumnModel should have the same number of columns as the TableModel, per the constructor javadoc.
ACTUAL -
The TableColumnModel is not populated until tableChanged has been called.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Caused by: java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Vector.java:432)
at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:280)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.table.*;
import javax.swing.*;
import javax.swing.event.*;
public class JTableBugTest
extends JFrame
{
public static void main(String[] args)
{
JTableBugTest tst = new JTableBugTest();
tst.setSize(100, 100);
tst.setVisible(true);
}
public JTableBugTest()
{
super("Bug Test");
DefaultTableModel myModel = new DefaultTableModel();
myModel.addColumn("Col1");
myModel.addColumn("Col2");
myModel.addColumn("Col3");
myModel.addRow(new Object[]{"item1.1", "item1.2", "item1.3"});
myModel.addRow(new Object[]{"item2.1", "item2.2", "item2.3"});
MyTable tbl = new MyTable(myModel);
this.getContentPane().add(tbl);
}
class MyTable
extends JTable
implements TableModelListener
{
public MyTable(TableModel model)
{
super(model);
}
public void tableChanged(TableModelEvent event)
{
System.out.println("Model has " + this.getModel().getColumnCount() + " columns.");
System.out.println("ColumnModel has " + this.getColumnModel().getColumnCount() + " columns");
// try to get the "affected" column
TableColumn column = null;
if(event.getColumn() == TableModelEvent.ALL_COLUMNS)
{
for(int col=0; col<this.getModel().getColumnCount(); col++)
column = this.getColumnModel().getColumn(col);
}else{
column = this.getColumnModel().getColumn(event.getColumn());
}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
ensure that you call super.tableChanged(event) before doing any of your own logic.
###@###.### 2005-04-18 20:50:37 GMT
java version "1.6.0-ea"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b29)
Java HotSpot(TM) Client VM (build 1.6.0-ea-b29, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
The JTable(TableModel) constructor passes null to the JTable(TableModel, TableColumnModel, ListSelectionModel) constructor.
According to the javadoc for that constructor:
The autoCreateColumnsFromModel flag is set to false if cm is non-null, otherwise it is set to true and the column model is populated with suitable TableColumns for the columns in dm.
The autoCreateColumnsFromModel flag is in fact set to true, but the column model is not auto-populated (ie: neither setAutoCreateColumnsFromModel or createDefaultColumnsFromModel is called). createDefaultColumnsFromModel is called from setAutoCreateColumnsFromModel and from tableChanged.
I believe the correct solution would be to call setAutoCreateColumnsFromModel instead of just setting the flag.
If you create an extension to JTable that implements TableModelListener, then your implementation has to be sure to call the default JTable.tableChanged method first or the TableModel and TableColumnModel do not match and it throws an ArrayIndexOutOfBoundsException when trying to access the columns.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Extend JTable, implement TableModelListener. Do NOT call super.tableChanged from your tableChanged method, but instead iterate through the TableColumnModel columns.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TableColumnModel should have the same number of columns as the TableModel, per the constructor javadoc.
ACTUAL -
The TableColumnModel is not populated until tableChanged has been called.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Caused by: java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Vector.java:432)
at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:280)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.table.*;
import javax.swing.*;
import javax.swing.event.*;
public class JTableBugTest
extends JFrame
{
public static void main(String[] args)
{
JTableBugTest tst = new JTableBugTest();
tst.setSize(100, 100);
tst.setVisible(true);
}
public JTableBugTest()
{
super("Bug Test");
DefaultTableModel myModel = new DefaultTableModel();
myModel.addColumn("Col1");
myModel.addColumn("Col2");
myModel.addColumn("Col3");
myModel.addRow(new Object[]{"item1.1", "item1.2", "item1.3"});
myModel.addRow(new Object[]{"item2.1", "item2.2", "item2.3"});
MyTable tbl = new MyTable(myModel);
this.getContentPane().add(tbl);
}
class MyTable
extends JTable
implements TableModelListener
{
public MyTable(TableModel model)
{
super(model);
}
public void tableChanged(TableModelEvent event)
{
System.out.println("Model has " + this.getModel().getColumnCount() + " columns.");
System.out.println("ColumnModel has " + this.getColumnModel().getColumnCount() + " columns");
// try to get the "affected" column
TableColumn column = null;
if(event.getColumn() == TableModelEvent.ALL_COLUMNS)
{
for(int col=0; col<this.getModel().getColumnCount(); col++)
column = this.getColumnModel().getColumn(col);
}else{
column = this.getColumnModel().getColumn(event.getColumn());
}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
ensure that you call super.tableChanged(event) before doing any of your own logic.
###@###.### 2005-04-18 20:50:37 GMT