0

我有一个 GUI 应用程序,它有几个选项卡,每个选项卡都承载一个JTable. 我的 UI 类在 EDT 上运行的以下代码中处理来自控制器的事件:

private void processAnalysisResult(AnalysisResult generatedValue) {
    LimitType limit = generatedValue.getMetric().getLimit();
    String limitName = limit.getName();
    int index = tabs.indexOfTab(limitName);
    Component component = tabs.getComponentAt(index);
    JScrollPane scrollPane = (JScrollPane) component;
    JTable table = (JTable) scrollPane.getViewport().getView();
    AnalysisResultTableModel model = (AnalysisResultTableModel) table.getModel();
    model.addRow(generatedValue);
    }
}

每秒有几千个新生成的结果,我将其降低到大约 10k。即使具有相对较低的值,应用程序也会冻结大约 10-20 秒来处理来自 Jtable 的 UI 更新。该addRow方法在插入每一行时调用fireTableRowsInsertedmewthod,但这会那么慢吗?

编辑:这是处理事件的代码(从后台处理线程异步调用):

  controller.addAnalysisGenerationListener(new GeneratedValueListener<AnalysisResult>() {
        @Override
        public void valueGenerated(final GeneratedValueEvent<AnalysisResult> event) {
            processEDT(new Runnable() {
                @Override
                public void run() {
                    processAnalysisResult(event.getGeneratedValue());
                }
            });
        }
    });


private void processEDT(Runnable runnable) {
    if (EventQueue.isDispatchThread()) {
        runnable.run();
    } else {
        SwingUtilities.invokeLater(runnable);
    }
}
4

2 回答 2

6

是的,它可以那么慢。10k不是一个低数字。正如您已经注意到的那样,addRow()调用fireTableRowsInserted()反过来通知视图发生了更改并刷新视图(但在这种情况下,用户看不到它,因为 EDT 正忙于处理下一个结果)。一种解决方案是processAnalysisResult()在后台线程上执行并通过将最后一行 ( model.addRow(generatedValue);)传递给 EDT 来更新模型SwingUtilities.invokeLater()。也许它不会更快,但至少 GUI 不会冻结 20 秒。当然,您也可以使用SwingWorker专用于此类任务的。此外,您可以尝试批量更新模型(例如,一次将每 100 个结果添加到 EDT 上的模型中),这样可以最大限度地减少屏幕闪烁。

于 2013-01-09T10:27:13.617 回答
4

猜猜 AnalysisResultTableModel 是 DefaultTableModel 的实例?

尝试添加批量 addRows() 方法,而不是一个一个添加。addRow() 调用方法

public void insertRow(int row, Vector rowData) {
    dataVector.insertElementAt(rowData, row);
    justifyRows(row, row+1);
    fireTableRowsInserted(row, row);
}

尝试实现这样的事情

public void insertRows(int row, Vector<Vector> rowsData) {
    for () {
        dataVector.insertElementAt(rowData, row);
        justifyRows(row, row+1);
    }

    fireTableRowsInserted(row, row+rowsData.size());
}
于 2013-01-09T10:32:41.090 回答