2011-02-07 179 views
8

在Swing上執行一些操作後更新UI的正確方法是什麼?Swing,如何正確更新UI

例如,點擊一個按鈕後,調用的方法可能幾乎是即時的或需要幾秒鐘的時間。實際上,所有應用程序邏輯都是通過Web服務遠程完成的,所以等待應用程序響應是正常的。

我的一個按鈕的事件處理程序可能看起來像這些:

myButton.addActionListener(new java.awt.event.ActionListener() { 
    public void actionPerformed(java.awt.event.ActionEvent evt) { 
     //callWebService(); 
     //do stuff 
     //updateUI(); // <----- repaint? revalidate? what? 
    } 
}); 

我目前的實現調用updateUI方法,內部調用的validate()和重繪()爲保存UI父組件。這有效,但有時我可以看到屏幕閃爍。我做錯了嗎?有沒有更好的方法來做到這一點?

+0

http://en.wikipedia.org/wiki/SwingWorker – qwerty 2011-02-07 11:58:43

+0

據我瞭解,這個問題是關於做一些更新後的UI,不是在另一個線程做的東西,以保持UI響應。不過,我不完全明白爲什麼在問題中提到方法的執行時間。 – 2011-02-07 12:15:20

+0

我提到了執行時間,因爲它看起來像Swing在嘗試加載組件時的行爲有點不同,並且加載時間過長,因此可能需要重新繪製屏幕。 – Hectoret 2011-02-07 12:25:29

回答

0

您通常不應做任何事情:如果你使用Swing組件的方法,或他們的模型的方法,必要的事件被解僱和GUI應自動更新。

這會不會是這樣,如果你定義自己的模型(而忘記火必要的事件,但當時它在你的模型中的錯誤,並應固定在那裏。

1

採取長期運行將事件發送回AWT事件調度線程(EDT)以更新GUI,使用java.awt.EventQueue.invokeLater

5

正確的方法是使用SwingWorker,但如果要手動執行,您將擁有實施以下模式:

@Override public void actionPerformed(java.awt.event.ActionEvent evt) { 
    new Thread() { 
    @Override public void run() { 
     //callWebService(); 
     //do stuff 
     SwingUtilities.invokeLater(new Runnable(){ 
     @Override public void run() { 
      //updateUI(); // <----- repaint? revalidate? what? 
     } 
     }); 
    } 
    }.start(); 
} 

對於重繪/重新驗證問題,通常請撥revalidate(),然後repaint()。這當然只適用於手動繪製的組件。對於您重複使用的組件,只需調用其值更改方法即可。

4

我個人使用的SwingWorker爲此,儘管有一些其他的意見/回答:

  • 儘管保持UI響應不是原來的問題的一部分,這是很好的做法,這樣做反正(我想不出一個很好的理由,鎖定了EDT冗長的處理。)
  • 它提供了一個done()方法可以實現,這將在美國東部時間默認情況下,當任務完成後執行,節省需要手動包裝的東西在invokeLater()
  • 這是更ex這種框架可以提供一個框架,以允許稍後添加進度等信息,只要它是如此需要的話。

最近我見過很多SwingWorker討厭,我不明白爲什麼。這是一個設計良好,可擴展的類,專門用於諸如此類的用途。是的,你可以用線程包裝並啓動它們,讓它們將其他方法包裝在invokeLater()中,但爲什麼在有更好的免費版本時重新發明輪子?