2016-03-29 90 views
1

假设我有一个监听器连接到一个按钮。当我按下这个按钮时,actionPerformed被调用,并且我将标签设置为可见。然后运行calculate()方法(其中有一些非常长的计算,它需要时间)。然后我想用show()方法打印结果。在执行操作时执行多个任务代码java

的是,我知道一个事实,即标签将里面actionPerformed被设置为可见后,所有的代码就会被执行。

所以我的问题是:我应该如何设置calculate方法在后台运行?主题? SwingTimer? SwingWorker的?我还没有找到理想的方式。

class ButtonListener implements ActionListener{ 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     calculateLbl.setVisible(true); 
     calculate();   
     show(); 
    } 
} 

回答

3

你的问题是摆并发之一:当计算()被调用Swing事件线程上,长期运行的代码,妨碍了事件线程,防止它从绘画到JLabel的。解决方案是在后台线程中运行计算,然后在完成后通知。发生通知时,请致电show()。一个SwingWorker可以很好地工作,因为它带有自己的通知机制。

例如,

@Override 
public void actionPerformed(ActionEvent e) { 
    calculateLbl.setVisible(true); 
    new SwingWorker<Void, Void>() { 
     public Void doInBackground() throws Exception{ 
      calculate(); // this is run in a background thread 
         // take care that calculate makes no Swing calls 
      return null; 
     } 

     protected void done() { 
      show(); // this is run on the Swing event thread 
     } 
    }.execute(); 
} 

警告:代码未测试/编译/也不运行。

上述代码的一个问题是,它不处理可能在calculate方法中引发的任何异常,更清晰的更好的方法是创建SwingWorker变量,将PropertyChangeListener附加到它,以及何时它的SwingWorker.StateValue是SwingWorker.StateValue.DONE,在SwingWorker上调用get()并处理那里的任何可能的异常。

+0

感谢您的帮助,示例代码帮助我了解如何开始,现在我可以更多地编辑它并继续。 – breathtaker

+0

你可以告诉我一个方法,我可以调用'show()'在calculate()运行时在框架中打印结果吗?例如,它可以在“calculate”循环中每100次运行一次。 – breathtaker

+0

@breathtaker:看看在你的SwingWorker中使用发布/过程,包括看[SwingWorker教程](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html)作为搜索这个网站。例如,看看[我的相关答案](http://stackoverflow.com/search?tab=votes&q=user%3a522444%20swingworker%20publish%20process),可以很容易找到。 –