Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JTable-UI在多次插入时冻结_Java_Swing_Concurrency_Jtable_Event Dispatch Thread - Fatal编程技术网

Java JTable-UI在多次插入时冻结

Java JTable-UI在多次插入时冻结,java,swing,concurrency,jtable,event-dispatch-thread,Java,Swing,Concurrency,Jtable,Event Dispatch Thread,我有一个GUI应用程序,它有两个选项卡,每个选项卡上都有一个JTable。我的UI class i在以下代码段中处理来自控制器的事件,该代码段在EDT上运行: private void processAnalysisResult(AnalysisResult generatedValue) { LimitType limit = generatedValue.getMetric().getLimit(); String limitName = limit.getName();

我有一个GUI应用程序,它有两个选项卡,每个选项卡上都有一个
JTable
。我的UI class i在以下代码段中处理来自控制器的事件,该代码段在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);
    }
}
每秒有几千个新生成的结果,atm I将其降低到大约10k。即使使用相对较低的值,该应用程序也会在处理来自Jtable的UI更新时冻结约10-20秒。
addRow
方法在插入每一行时调用
fireTableRowsInserted
mewthod,但这会有这么慢吗

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

controller.addAnalysisGenerationListener(新生成的ValueListener()){
@凌驾
生成的公共作废值(最终生成的值事件){
processEDT(新的可运行的(){
@凌驾
公开募捐{
processAnalysisResult(event.getGeneratedValue());
}
});
}
});
私有void processEDT(可运行可运行){
if(EventQueue.isDispatchThread()){
runnable.run();
}否则{
SwingUtilities.invokeLater(可运行);
}
}

是的,它可能很慢。10公里不是一个低数字。正如您已经注意到的那样,
addRow()
调用
fireTableRowsInserted()
,这反过来会通知视图发生了更改并刷新视图(但在这种情况下,用户看不到它,因为EDT正忙于处理下一个结果)。 解决方案之一是在后台线程上执行
processAnalysisResult()
,并通过将最后一行(
model.addRow(generatedValue);
)传递到
SwingUtilities.invokeLater()
来更新EDT上的模型。也许它不会快很多,但至少GUI不会冻结20秒。 当然,您也可以使用专门用于此类任务的
SwingWorker

此外,您可以尝试批量更新模型(例如,在EDT上一次向模型添加每100个结果),这将最大限度地减少屏幕闪烁。

猜测AnalysisResultableModel是DefaultTableModel的实例

尝试添加batch 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());
}
public void insertRows(int行、Vector行数据){
对于(){
insertElementAt(rowData,row);
证明行(行,行+1);
}
fireTableRowsInserted(行,行+行数据.size());
}

抱歉,忘了提一下,启动整个分析的代码,即调用上述方法的代码,已经在后台线程的背面运行。如果GUI冻结,则意味着在EDT上的单个事件处理循环中调用
processAnalysisResult()
。应更改调用代码,以便在发送到EDT的单独事件上,每个
generatedValue
调用一次
processAnalysisResult()。这样,EDT将有机会处理其他挂起的GUI事件(即刷新视图)。另一个好主意是通过
addRows()
方法扩展模型,该方法调用
fireTableRowsInserted()
一次,正如@StanislavL所提到的。现在发生的事情正是您所描述的——后台线程正在生成一个事件,随后在EDT上一次处理一个事件。但是GUI仍然挂起…您能否显示将事件传递给EDT并调用
processAnalysisResult()
的代码?
public void insertRows(int row, Vector<Vector> rowsData) {
    for () {
        dataVector.insertElementAt(rowData, row);
        justifyRows(row, row+1);
    }

    fireTableRowsInserted(row, row+rowsData.size());
}