2009-10-15 47 views
0

我使用NetBeans在Swing中創建應用程序。我希望能夠在窗口變得可見之後操作一些組件(僅一次),例如更新進度條。爲此,我有應用程序的主類,稱爲主窗口:在程序啓動時操作Swing組件的正確方法是什麼?

public class MainWindow extends JFrame 
{ 

public MainWindow() 
{ 
    initComponents(); // NetBeans GUI builder-generated function for setting 
         // up the window components 

} 

public void Init() 
{ 
    loadLabel.setText("Loading...."); 
    loadProgressBar.setValue(20); 
    doSomething(); 
    loadProgressBar.setValue(40); 
    doSomething(); 
    loadProgressBar.setValue(80); 
    doSomething(); 
    loadProgressBar.setValue(100); 

    loadLabel.setVisible(false); 
    loadProgressBar.setVisible(false); 
} 

/* .... */ 

public static void main(String args[]) 
{ 
    java.awt.EventQueue.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
      mainHandle = new MainWindow(); 
      mainHandle.setVisible(true); 
      mainHandle.Init(); 
     } 
    }); 
} 

} 

的問題是,對於初始化內更新進度條(或操縱任何其它GUI部件)的發言()功能的影響可以不會被觀察到。如果Init()函數在main()中被調用,如上所示,窗口出現,但是爲空,Init()函數執行並返回,只有在窗口繪製它的內容後,Init()所做的任何更改都不會不可見,因爲窗戶一直是空的和不活動的。我也嘗試從windowOpened()AWT事件中調用init,該事件在窗口完全繪製後執行,但令人驚訝的是,任何用於操作組件的語句似乎沒有任何作用,或者更確切地說它們被放入隊列中,並在可以觀察到一些點,所以只有最後一個(隱藏元素)的效果。我設法讓它工作的唯一方法是刪除整個invokeLater(new Runnable()...)口頭禪,並將新的MainWindow(),setVisible(),Init()序列直接放在main()中,我猜是非常醜陋的,並打破了gui以線程方式運行的概念。什麼是正確的方法來做到這一點?當gui準備好被操作時,我會在哪裏放置代碼以執行第一件事,執行一次語句並將控制權返回給主事件循環?我認爲目前這是以這樣的方式工作,即當Init()函數正在運行時,gui組件上的任何操作都被掛起(繪圖線程不分離並且等待Init()以在執行操作之前完成)。也許我應該讓Init()成爲一個新的線程......只有如何和怎樣?

謝謝。

回答

1

您可以將EventQueue.invokeLater()更改爲invokeAndWait(),並將該調用移至init()調出至第二個EventQueue.invokeLater()調用。

如果(看起來是這種情況)doSomething()需要一個明顯的時間,更好的辦法是將Init代碼移動到SwingWorker的主體中。這可以在MainWindow()構造函數中執行,也可以在main()中調用setVisible()之後執行,並且是具有響應式GUI的慣用方法(以防用戶厭倦等待並想要退出)並顯示一些可見的進度跡象。

有關如何更新doSomething()調用之間的進度欄的詳細信息,請參閱processpublish方法。

你可能也想看看ProgressMonitors爲另一個替代方案,將爲您處理對話框等。

1

有幾件事情可以做:

  1. 的Windows(如JFrameJDialog)可以附加的WindowListener,做你的操作中的windowOpened方法。
  2. 重寫addNotify方法並在那裏進行控制操作。
  3. 附加HierarchyListener並且只要組件的可顯示性發生變化就可以進行操作。

請務必確保您在EDT上執行了組件操作。對於簡單的UI更新使用SwingUtilities.invokeLater或對於長時間運行的任務使用SwingWorker

+0

廣告1:我可能沒有得到某些東西,但在我看來,我說過嘗試這種方法並沒有奏效。 – neuviemeporte 2009-10-15 16:54:39

+0

您可以嘗試我提供的3種不同方法中的任意一種。我會在你的案例中使用#2,只需從addNotify調用init(不要忘記調用super.addNotify) – 2009-10-15 19:56:03

相關問題