ArrayIndexOutOfBoundsException:在JTable创建/表更改时为-1



我已经通读了所有看起来可以解决我问题的线程,我也读了这里的所有答案,但我仍然束手无策。我不知道为什么会抛出异常,尽管我有一种感觉,这可能与threading有关。如果是,请让我知道在哪里包括new Runnable(),以及是invokeLater()还是invokeAndWait(),因为我已经尝试过了,但没有成功。

请耐心等待,我会给你导致异常+堆栈争用的代码(如下(。

EDIT:就在调用tableChanged之前,我在AnnoTable部分中包含了许多syso,但它们不会显示在控制台中,因此我认为问题一定会在应用程序到达该点之前发生,即从AAView调用它时,或者当数据和表模型实例化时。。。

EDIT II:问题在于被覆盖的tableChanged方法。这显然会引发一个例外。我也删除了tableChanged()调用(这不会有什么不同(。现在我遇到了另一个问题:理解底层数据(AnnoData(的更改如何自动更新表。虽然这可能是另一个查询(在谷歌搜索后(,但请随时在这个帖子中发布有用的评论,因为我会继续阅读…非常感谢所有有用的评论和提示!

第三版:*我已经解决了这个问题。我需要从AnnoData实例化另一个对象,将其传递给AnnoTableModel的一个新实例,将该实例设置到我的表中,然后再设置为fireTableDataChanged()

EDIT IV:好的,所以fireTableDataChanged()(在EDIT III中使用(毕竟是不必要的。我仍然想使用它,而不是一直创建新的对象。我想我应该问一个新问题。。。谢谢

AAView中的这个方法应该创建一个扩展JTable的对象,将其放入JScrollPane中,等等(后者确实有效(。

private JPanel createAnnoTablePanel() {
    annoTablePanel = new JPanel();
    annoTable = new AnnoTable(aameth);
    setAnnoTable(annoTable);
    JScrollPane scrollPane = new JScrollPane(getAnnoTable());
    annoTablePanel.add(scrollPane);
    return annoTablePanel;
}

这里是类AnnoTable(aameth是一个实例对象,包含访问数据模型的业务逻辑,工作正常(。

public class AnnoTable extends JTable implements TableModelListener
{
  public AnnoTable(AAMethods aameth)
  {
     int tokenCount = aameth.getTokenCount();
     AnnoData annoData = new AnnoData(aameth); // cf. below, AnnoData is a Vector(Vector<Object>,String[])
     TableModel tableModel = new AnnoTableModel(annoData.getAnnoData(),
     // AnnoTableModel extends AbstractTableModel(Vector, String[])
     annoData.getColTitles());
     setModel(tableModel);
     getModel().addTableModelListener(this);
     TableModelEvent tme = new TableModelEvent(tableModel);
     this.tableChanged(tme);
     setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
     setCellSelectionEnabled(true);
     getColumnModel().getSelectionModel().addListSelectionListener(new AnnoTableSelectionListener(this));
     setPreferredScrollableViewportSize(this.getPreferredSize());
  }
  public void tableChanged(TableModelEvent e) {
  int row = e.getFirstRow();
     int column = e.getColumn();
     AbstractTableModel model = (AbstractTableModel)e.getSource();
     String columnName = model.getColumnName(column);
     Object data = model.getValueAt(row, column); // This is where the exception is thrown!
  }
}

如果您需要AnnoTableModel()(它是AbstractTableModel的一个相当通用的扩展(或AnnoData(它构造了一个包含三个Vector<Object>和一个用于列标题的String[]Vector(的源代码,请告诉我。

这是堆叠比赛。

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.table.DefaultTableModel.getValueAt(Unknown Source)
at package.AnnoTable.tableChanged(AnnoTable.java:52)
at javax.swing.JTable.setModel(Unknown Source)
at javax.swing.JTable.<init>(Unknown Source)
at javax.swing.JTable.<init>(Unknown Source)
at package.AnnoTable.<init>(AnnoTable.java:25)
at package.AAView.createAnnoTablePanel(AAView.java:464)
at package.AAView.createNorthPanel(AAView.java:455)
at package.AAView.displayAndAnnotate(AAView.java:444)
at package.AAView.loadProject(AAView.java:333)
at package.AAView.actionPerformed(AAView.java:286)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Actions.actionPerformed(Unknown Source)
at javax.swing.SwingUtilities.notifyAction(Unknown Source)
at javax.swing.JComponent.processKeyBinding(Unknown Source)
at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source)
at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source)
at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source)
at javax.swing.JMenuBar.processKeyBinding(Unknown Source)
at javax.swing.KeyboardManager.fireBinding(Unknown Source)
at javax.swing.KeyboardManager.fireKeyboardAction(Unknown Source)
at javax.swing.JComponent.processKeyBindingsForAllComponents(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$000(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.awt.EventQueue$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.awt.EventQueue$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$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)

我可以在那里看到EDT,所以根据我所学到的,这可能真的是一个线程问题。然而,我不知道如何找到应该在哪里启动新的Thread(或调用new Runnable().

附带说明一下,当我将AnnoTable更改为扩展JTable而不是JPanel时,Exception才开始出现。最初,我让AnnoTable不仅构建表,而且将其包装在滚动窗格中,并将其添加到新的JPanel中。但因为我想从一个只知道AAView的类中fireTableDataChanged(它还具有setAnnoTable()方法(,所以我想用正确的方式来做,而以前它工作得很好。墨菲定律?

rowIndex为-1(==TableModelEvent.HEADER_ROW(表示模型的结构已完全更改。这样的事件是由setModel上的JTable在内部触发的。阅读TableModelEvent的api文档,以完全了解侦听器的tableChanged中需要哪些类型/值。

顺便说一句,@AKJ是对的-不需要在表代码中激发任何TableModelEvents。使模型适当地触发事件

这意味着您将-1作为行或列传递。这是不允许的-请确保您传递了正确的值。

我感觉你的问题就在这里:

TableModelEvent tme = new TableModelEvent(tableModel);      
this.tableChanged(tme); 
->
  int column = e.getColumn();     
  AbstractTableModel model = (AbstractTableModel)e.getSource();     
  String columnName = model.getColumnName(column); 

因为您没有指定rowcolumn值,所以getColumn()getRow()调用将返回-1,然后将其传递给getValueAt()

请尝试查看TableModelEvent的构造函数。它具有用于指定这些行/列值的选项。

TableModelEvent tme = new TableModelEvent(tableModel);
this.tableChanged(tme);

我认为没有必要打这个电话。正如其他海报所指出的,这就是你问题的原因。

如果您正确地实现了表模型,那么每当您更新表模型时,jtable都会自动获得通知,并且您也不需要编写tableChanged((方法。所以我不明白为什么需要显式调用tableChanged((。

只要您想更新表,只需更新模型即可。而且乍一看,似乎没有涉及任何线程问题。

您的AnnoTable构造函数正在泄漏对未完全构造的"this"对象的引用。此外,从构造函数注册Listener是不安全的。在此处输入链接描述

在构造函数中尽可能少地构建对象,然后对完全构建的对象进行操作。添加监听器、调整模型、fireEvents等…

最新更新