tags:

views:

2569

answers:

3

I'm subclassing JTable and using a DefaultTableModel to model my table data. The following class sets up the JTable, and adds one row to the model.

import java.io.File;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.JTable;  
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

public class SelectedFileTable extends JTable {
Vector<File> SelectedFiles = new Vector<File>(); 
DefaultTableModel Model    = new DefaultTableModel();

TableColumn ColumnName     = new TableColumn();
TableColumn ColumnSize     = new TableColumn();
TableColumn ColumnRmIcon   = new TableColumn(); 

ImageFilenameFilter Filter = new ImageFilenameFilter();

public SelectedFileTable() {
 super();
 this.setModel(Model);

 ColumnName.setHeaderValue(new String("Name") );
   ColumnName.setMinWidth(200);
 ColumnSize.setHeaderValue(new String("Size") );
   ColumnSize.setMinWidth(50); 
   ColumnSize.setMaxWidth(100);
 ColumnRmIcon.setHeaderValue(new String("Remove?") );
   ColumnRmIcon.setMaxWidth(100);
   ColumnRmIcon.setResizable(false);

 this.addColumn(ColumnName);
 this.addColumn(ColumnSize);
 this.addColumn(ColumnRmIcon);

 this.setShowVerticalLines(false);
 this.setShowHorizontalLines(true);
this.setAutoCreateColumnsFromModel(true);

this.addFile( new File("C:/temp/cfk.jpg") );
}
public void addFile(File file) {
 System.out.println("FileTable adding: " + file.getName() );
 if ( file.isDirectory() ) { 
  for ( File f : file.listFiles(Filter) ) {
   this.addFile(f);
  }
 } else { 
  if ( Filter.accept(file) ) {
   System.out.println("Accepting file; " + file.getName() );
   SelectedFiles.add(file);
   {
    String name = file.getName();
    Long size = new Long( file.length() );
    String tempstr = new String("X");

    System.out.println("RowItems before: " + Integer.toString(Model.getRowCount()) );
    Model.addRow( new Object[] { name, size, tempstr } );
    Model.fireTableDataChanged(); 
    System.out.println("RowItems start : " + Integer.toString(Model.getRowCount()) );
   }
   System.out.println("Done Accepting file; " + file.getName() );
  }
 }
}
public Iterator<File> iterator() { 
 return SelectedFiles.iterator();
}

}

At display/visualization time, the following exception is thrown:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Vector.java:432)
at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:622)
at javax.swing.JTable.getValueAt(JTable.java:1903)
at javax.swing.JTable.prepareRenderer(JTable.java:3911)
at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2072)
at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1974)
at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1897)
at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
at javax.swing.JComponent.paintComponent(JComponent.java:743)
at javax.swing.JComponent.paint(JComponent.java:1006)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JViewport.paint(JViewport.java:728)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:559)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4979)
at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4925)
at javax.swing.JComponent.paint(JComponent.java:996)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1709)
at sun.awt.RepaintArea.paintComponent(RepaintArea.java:248)
at sun.awt.RepaintArea.paint(RepaintArea.java:224)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:254)
at java.awt.Component.dispatchEventImpl(Component.java:4060)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Window.dispatchEventImpl(Window.java:1791)
at java.awt.Component.dispatchEvent(Component.java:3819)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

I'm ripping my hair out - I haven't been able to find the root cause of this immensely simple use case.

+7  A: 

I think you need to add columns to your TableModel. Your code adds UI columns to the table but doesn't add them to the model

Dmitry
@Chris: More specifically, you should add columns to the TableModel **instead** of explicitly adding them to the JTable. It's also worth pointing out that you will get better performance from a List instead of a Vector, since you're not using the synchronization (and shouldn't have to pay for the overhead) that comes with a Vector.
rob
+1  A: 

From the JTable.setAutoCreateColumnsFromModel() API:

"This method calls createDefaultColumnsFromModel if autoCreateColumnsFromModel changes from false to true. "

Vector throws ArrayIndexOutOfBoundsException - if the index is out of range ( index < 0 || index >= size())

I guess the table model is missing the columns, as suggested by Dmitry

Thimmayya
+2  A: 

Dmitry is right. Replace

this.addColumn(ColumnName);
this.addColumn(ColumnSize);
this.addColumn(ColumnRmIcon);

with

Model.addColumn(ColumnName);
Model.addColumn(ColumnSize);
Model.addColumn(ColumnRmIcon);

and now the Model knows about the columsn and won't throw an Exception anymore when you try to add a row to a model which thinks it has 0 columns

jitter