My project involves a JTable with a custom TableModel. Since I want the user to be able to modify each cell in the table, I choose to have my custom TableModel (CSVModel) extend DefaultTableModel. However, for some reason CSVModel throws an exception when I try to edit a cell in my table. The only hint I have is from the last line of the stack trace:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3 >= 0 at
3 is the row number of the cell I was trying to modify. So maybe a problem with my data going out of scope? Here is the code:
class CSVModel extends DefaultTableModel {
private String[] columnNames;
private ArrayList<String[]> Data = new ArrayList<String[]>();
public void AddCSVData(ArrayList<String[]> DataIn) {
this.columnNames = DataIn.get(0);
DataIn.remove(0);
this.Data=DataIn;
this.fireTableStructureChanged();
}
@Override
public int getColumnCount() {
if (columnNames != null)
return columnNames.length;//length;
else
return 0;
}
@Override
public int getRowCount() {
if (Data != null)
return Data.size();
else
return 0;
}
public void setRowCount() {
Data=null;
columnNames=null;
this.fireTableStructureChanged();
}
@Override
public String getColumnName(int col) {
System.out.println("getcol");
return columnNames[col];
}
@Override
public Object getValueAt(int row, int col)
{
return Data.get(row)[col];
}
public ArrayList<String[]> ReadCSVFile(File dataFile) {
// When user presses load, read in the selected CSV file
CSVFile temp = new CSVFile();
return temp.ReadCSVfile(dataFile);
}
Before editing I load a CSV file into the table using this class:
public class CSVFile {
private ArrayList<String[]> Rs = new ArrayList<>();
private String[] OneRow;
// Method for reading CSV file
public ArrayList<String[]> ReadCSVfile (File DataFile) {
try {
BufferedReader brd = new BufferedReader (new FileReader(DataFile));
String st = brd.readLine();
while (st != null) {
OneRow = st.split(",");
Rs.add(OneRow);
st = brd.readLine();
} // end of while
brd.close();
} // end of try
catch (Exception e) {
String errmsg = e.getMessage();
System.out.println ("File not found:" +errmsg);
} // end of Catch
return Rs;
}// end of ReadFile method
}// end of CSVFile class
The full stack trace:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3 >= 0 at java.util.Vector.elementAt(Unknown Source) at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source) at javax.swing.JTable.setValueAt(Unknown Source) at javax.swing.JTable.editingStopped(Unknown Source) at javax.swing.AbstractCellEditor.fireEditingStopped(Unknown Source) at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(Unknown Source) at javax.swing.DefaultCellEditor.stopCellEditing(Unknown Source) at javax.swing.JTable$GenericEditor.stopCellEditing(Unknown Source) at javax.swing.DefaultCellEditor$EditorDelegate.actionPerformed(Unknown Source) at javax.swing.JTextField.fireActionPerformed(Unknown Source) at javax.swing.JTextField.postActionEvent(Unknown Source) at javax.swing.JTextField$NotifyAction.actionPerformed(Unknown Source) at javax.swing.SwingUtilities.notifyAction(Unknown Source) at javax.swing.JComponent.processKeyBinding(Unknown Source) at javax.swing.JComponent.processKeyBindings(Unknown Source) at javax.swing.JComponent.processKeyEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source) at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source) at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source) at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$200(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)
Thanks for the help!
The solution was to extend AbstractTableModel instead of DefaultTableModel. I also had to include appropriately overloaded versions of two methods of AbstractTableModel: