File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Swing / AWT / SWT and the fly likes JTable ClassCastException... Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "JTable ClassCastException..." Watch "JTable ClassCastException..." New topic
Author

JTable ClassCastException...

Shannon Sims
Ranch Hand

Joined: Jul 03, 2003
Posts: 197
Hello. I'm constructing the JTable with two Vectors to build a table. It seems as though the rowData is causing the ClassCastException. The rowData contains only Strings. The second Vector works fine, if I set rowData as just an empty Vector.

//Vector rowData = new Vector(); this works fine
Vector rowData = aModel.getMatchingCriteria();
Iterator anIter = matches.iterator();
while( anIter.hasNext() )
{
System.out.println( ( (String) anIter.next() ) );
}
JTable table = new JTable( rowData, aModel.getColumnNames() );
System.out.println( "table is constructed" );
table.setPreferredScrollableViewportSize( new Dimension( 500, 100 ) );
TableColumn widestColumn = table.getColumnModel().getColumn(2);
widestColumn.setPreferredWidth( 150 );

I can iterate and print the contents of the Vector, however I never get to the "table is constructed" print statement. This is the exception I get if I use the rowData to construct the table:

java.lang.ClassCastException
at javax.swing.table.DefaultTableModel.justifyRows(DefaultTableModel.java:238)
at javax.swing.table.DefaultTableModel.setDataVector(DefaultTableModel.java:194)
at javax.swing.table.DefaultTableModel.<init>(DefaultTableModel.java:131)
at javax.swing.JTable.<init>(JTable.java:403)
at suncertify.client.SearchContractorWindow.buildContractorResultTable(SearchContractorWindow.java:153)
at suncertify.server.Controller$SearchButtonListener.actionPerformed(Controller.java:56)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1786)
at javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1839)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:420)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:258)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:245)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:231)
at java.awt.Component.processMouseEvent(Component.java:5100)
at java.awt.Component.processEvent(Component.java:4897)
at java.awt.Container.processEvent(Container.java:1569)
at java.awt.Component.dispatchEventImpl(Component.java:3615)
at java.awt.Container.dispatchEventImpl(Container.java:1627)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3198)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128)
at java.awt.Container.dispatchEventImpl(Container.java:1613)
at java.awt.Window.dispatchEventImpl(Window.java:1606)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)

Any help is greatly appreciated! Thank you all!
Jason Kingsley
Greenhorn

Joined: Feb 21, 2004
Posts: 18
JTables expect to see a data structure of rows and columns. When you use a vector in the JTable constructor, this is expected to be 2-dimensional. Specifically, a Vector of Vectors (as that is what the DefaultTableModel uses/expects as its underlying storage structure - but becareful with DefaultTableModel's, because of the Vector of Vectors, you pay a penalty of synchronized access).

The requirements are shown in the API help for JTable:


JTable

public JTable(Vector rowData,
Vector columnNames)

Constructs a JTable to display the values in the Vector of Vectors, rowData, with column names, columnNames. The Vectors contained in rowData should contain the values for that row. In other words, the value of the cell at row 1, column 5 can be obtained with the following code:

((Vector)rowData.elementAt(1)).elementAt(5);

Parameters:
rowData - the data for the new table
columnNames - names of each column



With your vector only containing strings the cast illustrated above will fail. If you only have one column, you need to have a Vector (rows) of Vectors(columns) where each row Vector is of length 1 containing your string.

You can trace it through by looking at the source for JTable and DefaultTableModel:


/**
* Constructs a <code>JTable</code> to display the values in the
* <code>Vector</code> of <code>Vectors</code>, <code>rowData</code>,
* with column names, <code>columnNames</code>. The
* <code>Vectors</code> contained in <code>rowData</code>
* should contain the values for that row. In other words,
* the value of the cell at row 1, column 5 can be obtained
* with the following code:
* <p>
* <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
* <p>
* @param rowData the data for the new table
* @param columnNames names of each column
*/
public JTable(Vector rowData, Vector columnNames) {
this(new DefaultTableModel(rowData, columnNames));
}


and


private void justifyRows(int from, int to) {
// Sometimes the DefaultTableModel is subclassed
// instead of the AbstractTableModel by mistake.
// Set the number of rows for the case when getRowCount
// is overridden.
dataVector.setSize(getRowCount());

for (int i = from; i < to; i++) {
if (dataVector.elementAt(i) == null) {
dataVector.setElementAt(new Vector(), i);
}
((Vector)dataVector.elementAt(i)).setSize(getColumnCount());
}
}


You can see the line that fails.
Shannon Sims
Ranch Hand

Joined: Jul 03, 2003
Posts: 197
Thanks Jason for the help and quick response. I thought I would be stuck on this problem for a while. So basically, the first Vector is a container of rows (each row is a Vector within the first Vector), correct?
Jason Kingsley
Greenhorn

Joined: Feb 21, 2004
Posts: 18
yes, that is what the particular constructor for JTable is expecting. It will take the Vector and construct a DefaultTableModel with it (as can be seen:



and if you follow the codepath in DefaultTableModel (the source is included usually with your JDK installation) you'll see that it uses a Vector of Vectors and will replace its internal vector with the one passed in.

You will need to construct a Vector of columns for each row, and add that to a Vector of rows and pass that to the constructor.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: JTable ClassCastException...