所以我有一个使用受this tutorial启发的MVC模式设计的桌面应用程序(但略有修改)。此应用程序需要做的是将文件列表从目录复制到另一个目录。我想做的是基本上在复制每个文件后更新我的GUI。
首先让我告诉你代码。 在我的模型中,我有这种虚拟方法(不是真正的方法,但背后的逻辑是相同的):
public void dummyMethod(Integer k) throws InterruptedException{
for(int i=0;i<10;i++){
System.out.println(i);
Thread.sleep(1000);
this.firePropertyChange(DefaultController.BACKUP_DUMMY, i-1, i);
}
}
在我看来,我有这个:
@Override
public void modelPropertyChange(PropertyChangeEvent evt) {
// .......
else if( evt.getPropertyName().equals( DefaultController.BACKUP_DUMMY ) ){
System.out.println("WHAT?");
this.dummy.setText(evt.getNewValue().toString());
}
}
你可以想象每次打印 WHAT?但是在循环结束之前GUI不会更新。 这是你使用SWING及其EDT时的经典问题,我在oracle网站上阅读了article/tutorial,但我认为我不需要使用SwingWorker。我只需更新GUI上的单个组件。
答案 0 :(得分:3)
但是在循环结束之前GUI不会更新。
这表示您的所有代码都在EDT上运行,因此GUI在整个循环结束之前无法重新绘制。
但我认为我不需要使用SwingWorker。
为什么不,这可能是最简单的解决方案。您可以在单独的线程上运行主循环,然后在处理每个文件时“发布”结果。
或者使用Gursel建议的方法。长时间运行的代码在一个单独的线程中执行,只有属性更改事件的触发在EDT上,这意味着GUI可以在EDT上重新绘制自己。
答案 1 :(得分:1)
不要将事件调度线程用于长时间运行的操作。您应该为长时间运行的操作启动另一个线程,例如文件复制。如果需要从工作线程更新gui,则应使用SwingUtilities.invokeLater或SwingUtilities.invokeAndWait方法..
作为例子;
final JLabel label = new JLabel();
JButton button = new JButton();
button.addActionListener(new ActionListener() {
public void actioPerformed(ActionEvent ev) {
Thread workerThread = new Thread() {
public void run() {
//do long running job then update ui
SwingUtilities.invokeLater(new Runnable() {
public void run(){
label.setText("Operation has finished");
}
});
}
}.start();
}
});