java.lang.ArrayIndexOutOfBoundsException: 0 >= 0 尝试填充JTable时出错

13

我正在子类化JTable并使用DefaultTableModel来对表格数据进行建模。以下类设置了JTable,并向模型添加了一行。

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();
}

}

在显示/可视化时,会抛出以下异常:

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)

我简直要抓狂了 - 我一直找不到这个极其简单的用例的根本原因。


1
直到今天我从未见过这个越界异常消息。感谢您帮助我调试应用程序! - Feanor
请学习Java命名规范并遵循它们。 - kleopatra
你们所有人。你具体的问题是什么? - Chris K
@ChrisKaminski 我猜例如实例变量在 Java 中应该以小写字母开头。 - Steffen T
10个回答

19

1
+1 虽然被采纳的答案在这种情况下是正确的,但这非常重要,对我造成了问题。 - BeRecursive

18

我认为你需要向你的TableModel中添加列。你的代码向表格添加了UI列,但没有将它们添加到模型中。


1
@Chris:更具体地说,您应该将列添加到TableModel中,而不是将它们直接添加到JTable中。值得指出的是,如果您使用List而不是Vector,您将获得更好的性能,因为您没有使用同步(也不应该为了Vector带来的开销而付出代价)。 - rob

5

德米特里是正确的。替换

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

使用

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

现在这个模型知道了它的列数,当你试图向一个认为自己没有列的模型中添加一行时,它不会再抛出异常了。


1

使用以下代码替换您的代码 在这里,您需要仅删除第一行,该行应迭代所有行

private void refreshTable() {

   int rowCount= model.getRowCount();

  // System.out.println(rowCount);

   for(int i=0;i<rowCount;i++ ){
        model.removeRow(0);
        //System.out.println(i);
   }

}

1

另一个问题可能与使用 RowSorter 有关。当您编辑模型时,RowSorter 会尝试重新对旧模型进行排序。RowSorter 应该在表格模型每次更改时自动重新创建和重新运行。

您可以通过以下方法解决它:

tableModel = new DefaultTableModel(data, columnNames);
jTableSentence.setModel(tableModel);
jTableSentence.setRowSorter(new TableRowSorter(tableModel));
jTableSentence.setAutoCreateRowSorter(true);

-Hayri


在设置模型并手动安装新的行排序器之后设置autoCreate属性就没有意义了。相反,在设置tableModel之前将该属性设置为true,然后完成即可。 - kleopatra
从API中我们可以知道,如果autoCreateColumnsFromModel从false变为true,该方法会调用createDefaultColumnsFromModel。因此它可以在之后添加。 - WesternGun

1
我遇到了这个问题,因为我向JTable添加的是列和行,而不是模型。
最好的方法是这样的。
Object[][]rows = new Object[ ][ ] { {"a","b"} , {"c","d"} };
Object[]columns = new Object[] {"column1","column2"};
JTable table = new JTable();
table.setModel(new DefaultTableModel(rows,columns));

1

替换

tabWindow.addTab(...);

使用

SwingUtilities.invokeLater(new Runnable() {
    @Override public void run() {
        tabWindow.addTab(...);
    }
});

当您在操作监听器中更改选项卡窗格时,可能会出现这种情况。


虽然在某些情况下可能是正确的,但它与问题完全无关。 - kleopatra

1

来自JTable.setAutoCreateColumnsFromModel() API:

“如果autoCreateColumnsFromModel从false更改为true,则此方法调用createDefaultColumnsFromModel。”

如果索引超出范围(index <0 || index > = size()),则Vector会抛出ArrayIndexOutOfBoundsException。

我猜表格模型缺少列,正如Dmitry所建议的那样。


0

在您的表格模型类中,需要添加一个 isCellEditable 方法,并返回 false。

@Override
  public boolean isCellEditable(int row, int column)
  {
    return false;
  }

0

Dmitry说得没错,但是你只需要更新你的模型。 要做到这一点,请在你的代码中添加以下内容:

DefaultTableModel dtm = (DefaultTableModel) table.getModel();
for (int c = 0; c < table.getColumnCount(); c++) {
dtm.addColumn(table.getColumnName(c));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接