2011-01-25 34 views
0

所以我有一个使用受this tutorial(但稍作修改)启发的MVC模式设计的桌面应用程序。该应用程序需要做的是将文件列表从一个目录复制到另一个目录。我想要做的是基本上在每个文件被复制后更新我的GUI。当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()); 
     } 

    } 

正如你所能想象的什么?每次都打印,但直到循环结束才更新GUI。 这是当你使用SWING和EDT时的经典问题,我已经在oracle网站上读到了这个article/tutorial,但我不认为我需要使用SwingWorker。我只需要在GUI上更新单个组件。

+0

“但我不认为我需要使用SwingWorker,我只需要在GUI上更新单个组件。”那么你最好仔细阅读SwingWorkers和美国东部时间,了解为什么这是你的错误决定:你正在避免你需要的工具。 – 2011-01-26 03:30:07

回答

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();  
    } 
}); 
+0

等一下。你在那做什么?因为我需要的是加载一个文件,然后通知GUI:为每个加载的文件。你是否建议在GUI中执行加载文件操作?这是对MVC。 – dierre 2011-01-25 22:52:38

3

,但没有更新的GUI,直到循环已经完成的事情。

这表明您的所有代码都在EDT上运行,因此在整个循环完成之前GUI无法重新绘制自己。

但我不认为我需要使用SwingWorker。

为什么不,这可能是最简单的解决方案。您的主循环在单独的线程上运行,然后在处理每个文件时“发布”结果。

或者使用Gursel建议的方法。长时间运行的代码在单独的线程中执行,只有属性更改事件触发在EDT上,这意味着GUI可以在EDT上重新绘制自己。

相关问题