java有什么区别吗?SwingWorker#发布vs SwingUtilities#调用器
比方说,我们有一个长/重的任务,必须在后台运行,并将其进度或任何内容发布到GUI。我知道这种发布必须在事件调度线程上进行。这就是为什么我们在任务中使用SwingWorker
所以,我们所做的是这样的:
public class WorkerTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
JLabel label = new JLabel();
frame.add(label);
startWorker(label);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
private static void startWorker(JLabel label) {
new SwingWorker<Integer, Integer>() {
@Override
protected Integer doInBackground() throws Exception {
for (int i = 0; i < 500; i++) {
publish(i);
Thread.sleep(500); //Simulate long task
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
Integer integer = chunks.get(0);
label.setText(String.valueOf(integer));
}
}.execute();
}
}
我的问题是,上述内容与此有何不同:
private static void startWorker(JLabel label) {
new SwingWorker<Integer, Integer>() {
@Override
protected Integer doInBackground() throws Exception {
for (int i = 0; i < 500; i++) {
int i2 = i;
SwingUtilities.invokeLater(() -> {
label.setText(String.valueOf(i2));
});
Thread.sleep(500); //Simulate long task
}
return null;
}
}.execute();
}
在这两种情况下,GUI的更新label.setText()
运行到事件调度线程。它们有什么不同
当然,问题也存在,为什么我应该对worker实现done()
方法,而不是在doInBackground
方法的末尾调用SwingUtilities.invokeLater
?除了处理doInBackground
方法中可能引发的异常之外
# 1 楼答案
查看类
SwingWorker
中的方法publish()
的javadoc根据问题中的代码,直接从方法
doInBackground()
调用SwingUtilities.invokeLater()
不会执行合并。也许你能想出一个理由,为什么合并是必要的?另请参阅Tasks that Have Interim Results关于
SwingWorker
类中的done()
方法,您也曾询问过,我再次向您推荐javadoc所以你不必重写方法
done()
。就我个人而言,我通常会在SwingWorker
对象中添加一个属性侦听器,用于处理[SwingWorker
]任务完成后需要执行的任务。当然,YMMV