java - 如何优化 Java Swing 中的事件处理?
问题描述
我的程序使用像 JTable 这样的具有数千行的电子表格。如果用户更改了一个单元格值,事件侦听器会执行一些昂贵的侦听器函数。每次执行只需不到一秒钟。
但是像在列中“全部替换”这样的操作会导致很长的延迟,因为事件侦听器会为每个更改的行执行一次。
如何优化侦听器的执行?
(我认为,在“全部替换”等操作期间,所有表侦听器事件都应该以某种方式停用,并且应该在最后执行一次。理想情况下,我不想单独调整每个侦听器。)
以下代码显示了该问题。使用“填充表格”按钮,一个函数会用数字填充除最后一个单元格之外的每个单元格。表侦听器对每个单元格更改执行求和操作。因为这个计算很快,我插入了一个 Thread.sleep 函数来模拟一个昂贵的操作。按“填充表”后,程序会挂起几秒钟。
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
public class TableListenerExample {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new TableListenerExample().startGUI();
}
});
}
public void startGUI() {
JFrame tableFrame = new JFrame();
tableFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tableFrame.setTitle("Table Example");
tableFrame.setSize(700, 860);
tableFrame.setLocationRelativeTo(null);
Object[][] data = new Object[100][1];
String[] columnNames = {"Column 1"};
JTable exampleJTable = new JTable(data, columnNames);
JScrollPane sp = new JScrollPane(exampleJTable);
TableModel tabModel = exampleJTable.getModel();
// the example uses only one table model listener event
tabModel.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (e.getFirstRow() == e.getLastRow() && e.getLastRow() == tabModel.getRowCount() - 1) {
// ignore changes in the sum cell
return;
}
TableModel tabModel = exampleJTable.getModel();
Object cellValue;
Integer cellValueI;
Integer total = 0;
// calculate a sum of all cells
for (int i = 0; i < tabModel.getRowCount() - 1; i++) {
cellValue = tabModel.getValueAt(i, 0);
cellValueI = 0;
try {
cellValueI = Integer.parseInt((String) cellValue);
} catch (NumberFormatException ex) {
//ignore
}
total += cellValueI;
}
try {
// simulate the time delay for a bigger calculation
Thread.sleep(100);
} catch (InterruptedException ex) {
// ignore
}
// write the sum in the last cell
tabModel.setValueAt("Sum: " + total, tabModel.getRowCount() - 1, 0);
}
});
tableFrame.add(sp, BorderLayout.CENTER);
JButton fillButton = new JButton("Fill Table");
tableFrame.add(fillButton, BorderLayout.SOUTH);
fillButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
TableModel tabModel = exampleJTable.getModel();
for (int i = 0; i < tabModel.getRowCount() - 1; i++) {
tabModel.setValueAt(Integer.toString(i + 1), i, 0);
}
}
});
tableFrame.setVisible(true);
}
}
解决方案
推荐阅读
- javascript - 如何仅使用没有 jQuery 的 javascript 删除除最后一个具有相同 document.querySelectorAll(".someClass") 的所有元素
- javascript - 迭代角度模板中的非空数组时出现空白结果
- javascript - Javascript中的哈希刷新
- android - 如何在android studio中将居中按钮放在2个线性布局下方
- substrate - 构建墨水时出错!脚蹼合同
- ruby-on-rails - 使用 alpinejs 渲染模板时遇到语法错误
- iis - 获取被 CORS 策略阻止
- python - 如何在 Tkinter/Python 中使用 .pack 控制垂直空间?
- internet-explorer - Microsoft 删除 Internet Explorer 后,Internet Explorer 自动化代码是否会继续工作?
- c++ - 当一个右值引用被副本捕获时会发生什么?