【问题标题】:"fireTableChanged" event on JTable model throws exception after filteringJTable模型上的“fireTableChanged”事件过滤后抛出异常
【发布时间】:2017-02-16 04:58:05
【问题描述】:

我在具有自定义模型的 JTable 上应用了两个操作。

首先是一个过滤操作:

// rf is a RowFilter object
((DefaultRowSorter) table.getRowSorter()).setRowFilter(rf);

此后,另一个线程更改表列名称并触发事件:

model.fireTableChanged(new TableModelEvent(model, TableModelEvent.HEADER_ROW));

但是,正在引发运行时异常。可能的原因是什么?

跟踪如下。谢谢。

线程“AWT-EventQueue-0”中的异常 java.lang.ArrayIndexOutOfBoundsException:-1 在 java.util.Vector.elementData(Vector.java:734) 在 java.util.Vector.elementAt(Vector.java:477) 在 javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294) 在 com.jtattoo.plaf.BaseTableHeaderUI.getHeaderRenderer(BaseTableHeaderUI.java:189) 在 com.jtattoo.plaf.BaseTableHeaderUI.paintCell(BaseTableHeaderUI.java:358) 在 com.jtattoo.plaf.BaseTableHeaderUI.paint(BaseTableHeaderUI.java:327) 在 javax.swing.plaf.ComponentUI.update(ComponentUI.java:161) 在 javax.swing.JComponent.paintComponent(JComponent.java:780) 在 javax.swing.JComponent.paint(JComponent.java:1056) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JViewport.paint(JViewport.java:728) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JLayeredPane.paint(JLayeredPane.java:586) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintChildren(JComponent.java:889) 在 javax.swing.JComponent.paint(JComponent.java:1065) 在 javax.swing.JComponent.paintToOffscreen(JComponent.java:5210) 在 javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579) 在 javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502) 在 javax.swing.RepaintManager.paint(RepaintManager.java:1272) 在 javax.swing.JComponent._paintImmediately(JComponent.java:5158) 在 javax.swing.JComponent.paintImmediately(JComponent.java:4969) 在 javax.swing.RepaintManager$4.run(RepaintManager.java:831) 在 javax.swing.RepaintManager$4.run(RepaintManager.java:814) 在 java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) 在 javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814) 在 javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789) 在 javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738) 在 javax.swing.RepaintManager.access$1200(RepaintManager.java:64) 在 javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732) 在 java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311) 在 java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756) 在 java.awt.EventQueue.access$500(EventQueue.java:97) 在 java.awt.EventQueue$3.run(EventQueue.java:709) 在 java.awt.EventQueue$3.run(EventQueue.java:703) 在 java.security.AccessController.doPrivileged(Native Method) 在 java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)

【问题讨论】:

  • 方法com.jtattoo.plaf.BaseTableHeaderUI.getHeaderRenderer 调用DefaultTableColumnModel.getColumn(-1) 是行不通的。您是否参与了您的任何课程的堆栈跟踪?
  • “使用排序器时,请始终记住转换单元格坐标。”—loc.cit..
  • @f1sh 不,我没有参与。但是,我在 EDT 中调用 fireTableChanged
  • @trashgod 我没有明确尝试在过滤后按索引获取任何行。接下来的唯一操作是重命名列标题并在模型上触发模型更改事件。

标签: java swing jtable thread-safety filtering


【解决方案1】:

查看您的堆栈跟踪,我猜 BaseTableHeaderUI 中存在错误

com.jtattoo.plaf.BaseTableHeaderUI.getHeaderRenderer(BaseTableHeaderUI.java:189)

因为上面是对 javax.swing.table.DefaultTableColumnModel 的调用:

/**
 * Returns the <code>TableColumn</code> object for the column
 * at <code>columnIndex</code>.
 *
 * @param   columnIndex     the index of the column desired
 * @return  the <code>TableColumn</code> object for the column
 *                          at <code>columnIndex</code>
 */
public TableColumn getColumn(int columnIndex) {
    return tableColumns.elementAt(columnIndex);
}

看起来 BaseTableHeaderUI 您的两个线程有​​问题。 所以也许你应该在同一个线程中处理所有事件?我的选择是 Event-Dipatch-Thread。

【讨论】:

  • 谢谢。我没有明白你所说的“两个线程”是什么意思。 fireModelChanged 模型调用在 SwingUtilities.invokeLater 内部调用。
  • 必须是 (AbstractTableModel) 的一部分,因为 fireModelChanged 可以将所有更改(JTable、与其模型的关系、ColumnModel、编辑器、渲染器等)重置为默认值(来自新模型定义),SelectionModel 可以忽略它
  • 我不再打电话给fireTableChanged。问题是,正如@trashgod 提醒的那样,表格行索引值在应用过滤操作后会发生变化。相反,我通过将索引值转换为视图来遍历列,然后设置标题值。但是,我不得不在表头上调用repaint 方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多