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

发布于 2024-12-11 14:22:10 字数 7229 浏览 0 评论 0原文

我已经阅读了所有看起来好像可以解决我的问题的线程,我也阅读了这里的所有答案,但我仍然束手无策。我不确定为什么会抛出异常,尽管我有一种感觉这可能与线程有关。如果是这样,请告诉我在哪里包含 new Runnable() 以及是 invokeLater() 还是 invokeAndWait(),正如我所言已经尝试过了,但没有效果。

请耐心等待,我将向您提供导致异常的代码+堆栈跟踪(如下)。

编辑:在调用tableChanged之前,我在AnnoTable部分中包含了许多syso,但它们不不会出现在控制台中,因此我认为问题必须在应用程序到达该点之前发生,即从 AAView 调用它时或实例化数据和表模型时...

< strong>编辑二:问题是覆盖 tableChanged 方法。这显然会引发异常。我也删除了 tableChanged() 调用(这不会产生任何影响)。现在我遇到了另一个问题:了解基础数据 (AnnoData) 的更改如何自动更新表。虽然这可能是另一个查询(在扩展的谷歌搜索之后),但请随时在此线程中发布有用的评论,因为我将继续阅读它......非常感谢所有有用的评论和提示!

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

编辑 IV: 好吧,所以 fireTableDataChanged() (如编辑 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 包含三个 Vector和一个用于列标题的 String[]),请告诉我。

这是堆栈跟踪。

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 时,最初我不仅有 AnnoTable 构建表,而且还构建了表。还将其包装在滚动窗格中并将其添加到但是因为我想从一个只知道 AAView 的类中fireTableDataChanged(它还具有 setAnnoTable()< /code> 方法)我想以正确的方式做到这一点,而之前它工作得很好?

I have read through all the threads out there that looked as if they could solve my problem and I've also read all the answers on here, but I'm still at my wit's end. I'm not sure why the exception is thrown, although I have a feeling this might be to do with threading. If it does, please let me know where to include the new Runnable()and whether to invokeLater() or invokeAndWait(), as I have tried it to no avail.

Please bear with me while I give you the code that leads to the exception + the stacktrace (below).

EDIT: I had included a number of sysos in the AnnoTable section just before tableChanged is called and they don't show up in the console, hence I think the problem must occur even before the application gets to that point, i.e. either when it's called from AAView or when data and table model are instantiated...

EDIT II: The problem was the overwritten tableChanged method. That would obviously fire an Exception. I've removed the tableChanged() call (which wouldn't make a difference) as well. Now I've got another problem: understanding how a change in the underlying data (AnnoData) can automatically update the table. Although this is perhaps for another query (after an extended Google search), please feel free to post helpful comments in this thread, as I'll continue reading it... THANKS A LOT for all the helpful comments and tips!

EDIT III:* I've solved the problem. I needed to instantiate another object from AnnoData, pass that to a new instance of AnnoTableModel, set this instance to my table and THEN fireTableDataChanged().

EDIT IV: Okay, so fireTableDataChanged() (as used in EDIT III) is unnecessary after all. I still would want to use it rather than creating new objects all the time. I guess I should ask a new question... Thanks!

This method in AAView should create an object extending a JTable, put it into a JScrollPane, etc. (the latter does work).

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

Here is the class AnnoTable (aameth is an instance object containing business logic to access a data model, works fine).

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!
  }
}

If you need the source code for AnnoTableModel() (which is a fairly generic extension of AbstractTableModel) or AnnoData (which constructs a Vector containing three Vector<Object> and a String[] for column titles), please let me know.

Here's the stacktrace.

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)

I can see the EDT in there so from what I've learned this might really be a problem of threading. However, I don't know how to find out where I should start a new Thread (or invoke a new Runnable().

On a side note, the Exception only started appearing when I changed AnnoTable to extend JTable rather than JPanel. Originally I had AnnoTable not only construct the table but also wrap it in a scroll pane and add this to a new JPanel. But because I wanted to fireTableDataChanged from a Class that only knew of AAView (which also features a setAnnoTable() method) I wanted to do it the correct way, whereas before it worked just fine. Murphy's law?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ㄟ。诗瑗 2024-12-18 14:22:11

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

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

A rowIndex of -1 (==TableModelEvent.HEADER_ROW) indicates that the model's structure has changed completely. Such an event is fired internally by the JTable on setModel. Read the api doc of TableModelEvent to fully understand which types/values to expect in the listener's tableChanged.

BTW, @AKJ is right - no need to fire any TableModelEvents in your table code. Make the model fire the events as appropriate

清秋悲枫 2024-12-18 14:22:11

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

This means that you are passing -1 as row or column. This is not permitted - make sure you pass a correct value.

落日海湾 2024-12-18 14:22:11

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

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。它具有用于指定这些行/列值的选项。

I have a feeling that your problem is here:

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

Because you haven't specified a row or column value, the getColumn() and getRow() calls will return -1, which you are then passing to getValueAt().

Try looking at the constructor for TableModelEvent. It has options for specifying those row/column values.

多像笑话 2024-12-18 14:22:11
TableModelEvent tme = new TableModelEvent(tableModel);
this.tableChanged(tme);

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

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

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

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

I don't see any need of this call. As pointed by other posters this is the cause of your problem.

If you are implementing the table model correctly, whenever you update the table model the jtable will automatically get notifications and you don't need to write the tableChanged() method as well. So I am lost why you need to call tableChanged() explicitly.

Whenever you want to update the table just update the model. Also at first glance there does not seem to be any threading issue involved.

慵挽 2024-12-18 14:22:11

您的 AnnoTable 构造函数正在泄漏对不完整构造的“this”对象的引用。此外,从构造函数注册监听器也不安全。 在此处输入链接描述

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

Your AnnoTable constructor is leaking references to the incompletely constructed "this" object. Also, registering Listeners from the constructor is not safe. enter link description here

Build your objects doing the least amount of work possible in the constructor and then operate on the fully built objects. Add listeners, adjust the models, fireEvents etc...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文