2016-03-29 125 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),可以很容易找到。 –