0

初步问题

如何构建 JTable 以便在触发 Google Guava 事件时更新它(并保证它是线程安全的)?

简单的方法是做model.setValueAt(aValue, row, column);

两个问题:

  • 使用JTableModel的标准数据结构,不知道自己在哪一行。
  • 使用 JTableModel 的标准数据结构,我不能将此数据用于其他组件
  • 这不是线程安全的(我认为)

我曾想过将 JTableModel 更改为使用 ConcurrentHashMap ,但似乎这不是扩展它的预期目的。我觉得这是一条通往奇怪错误的途径。

我在这一切中感到非常迷茫,如果你能提供一个我应该首先探索的指南,那将有很大帮助。

一个更明智的问题

事件不在 EVT 中。为了确保我跑了SwingUtilities.isEventDispatchThread(),结果是假的。

我现在认为我应该做的:

@Subscribe
public void handleMessage(DataStructure newInformation) {
  // handle the information

  SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        tableModel.setValueAt(...); // update table1
        tableModel2.setValueAt(...); // update table2
    }
  });
}

如果我得到完全独立于表格的信息。我需要一种方法来了解信息与哪一行相关。
我总是可以循环浏览模型中的整个向量,但我正在寻找一个可以使用地图或数组的解决方案。

4

2 回答 2

3

对 Swing 组件的每次更改都必须在事件分派线程中完成。您可以通过调用来测试您是否在事件调度线程中SwingUtilities.isEventDispatchThread()。如果返回 true,则可以直接修改模型。如果它返回 false,则必须在 EDT 中完成更新,方法是将其包装在使用SwingUtilities.invokeLater()(or SwingUtilities.invokeAndWait()) 执行的 Runnable 中:

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        tableModel.setValueAt(...);
    }
});

你没有说这个事件是什么,你的表模型是什么,但是由于表模型,你当然需要能够找到与你得到的事件对应的行和列. 通常使用 AbstractTableModel 包装一个List<SomeBean>. 使用列表的方法,您应该能够找到SomeBean要更新的实例的索引。

编辑:

正如我所说,定义表模型的典型方法是扩展 AbstractTableModel,并基于包装的 List 实现方法。但是,只要实现了表模型契约,没有什么能阻止您使用 Map 代替或添加 List,并向模型添加其他方法。List 将用于实现方法getValueAt(),getRowCount()等,例如,映射将允许快速找到列表中对象的索引。当然,将所有内容封装到自定义表模型中并保持两个集合同步是您的工作。

也就是说,我会采用一个简单的解决方案,即在列表上进行迭代以找到合适的行,并且仅在您确实遇到性能问题时才尝试优化(这可能只发生在一个巨大的表中)。维护这两个集合可能比简单地在列表上循环具有更大的开销。不要过早优化:这是万恶之源。

于 2012-11-02T15:46:22.367 回答
1

我的一般建议是使用一个AsyncEventBus通过调用Executor实现的。这将导致该事件总线的所有事件处理程序仅在 EDT 上被调用。execute(Runnable)SwingUtilities.invokeLater(Runnable)

如果您有很多不想在 EDT 上处理的事件您可以使用两个事件总线,只有一个调用 EDT 上的事件处理程序(UI 事件总线)。然后您的 UI 组件订阅 UI 事件总线。然后,您可以让您的主事件总线使用向主事件总线注册的中间对象将某些类型的事件转发到 UI,该对象仅将其接收到的事件发布到 UI 事件总线。

于 2012-11-02T18:06:55.680 回答