2011-08-25 25 views
51

我的問題是關於SwingUtilities.invokeLater。我應該什麼時候使用它?每次需要更新GUI組件時,我都必須使用它嗎?它究竟做了什麼?有沒有其他的選擇,因爲它聽起來不直觀,並增加了看似不必要的代碼?SwingUtilities.invokeLater

+2

它等價於Control.BeginInvoke。 – SLaks

+0

@SLaks這是否意味着如果我有一個線程,我不必使用它? – FadelMS

+4

@FadelMS,由於Swing框架產生了自己的一個線程(EDT),所以您將始終擁有該線程。 (*你*沒有「消息檢查」 - 處理用戶點擊等操作,對嗎?那麼各種'actionPerformed'方法如何被調用?由EDT!)所以當你說你有*一個*線程,我不得不解釋爲只有*有EDT(即,您拋出一個GUI並從主方法的邊緣掉下來)。在那種情況下,不,你*不需要使用'invokeLater'。但是,您將無法執行任何「背景」處理。如果你這樣做,你會完全鎖定GUI ... – aioobe

回答

52

每次我需要更新GUI組件嗎?

不,如果你已經將事件調度線程(EDT)響應用戶發起的事件,如點擊和選擇時總是這樣的。 (該actionPerformed方法等,總是被稱爲美國東部時間)。

如果你然而EDT是和想要做的GUI更新(如果要更新一些計時器線程的GUI,或一些網絡線程等),你必須時間表由EDT執行的更新。這就是這個方法的用途。

Swing基本上是線程不安全的。即,與該API的所有交互都需要在單個線程(EDT)上執行。如果您需要從另一個線程(計時器線程,網絡線程......)執行GUI更新,則需要使用諸如所提到的方法(SwingUtilities.invokeLater,SwingUtilities.invokeAndWait,...)。

+0

@ Jens:這意味着如果我在同一個線程(Swing)中或者在運行時做某事,我可以不用它。 – FadelMS

+1

那麼,「或者在運行時做事」並不是很精確。如果你在運行時做了一些事情,例如在一個計時器線程中,那麼不行,你不能沒有這些類型的方法。 – aioobe

+0

感謝aioobe,明白了。 – FadelMS

7

每一個Swing應用程序至少有2個線程:

  1. 運行應用
  2. 的EDT(事件指派線程)的主要思路是更新UI線程(所以UI不會凍結)。

如果您想更新UI,您應該在EDT內執行代碼。 像SwingUtilities.invokeLater,SwingUtilities.invokeAndWait,EventQueue.invokeLater,EventQueue.invokeAndWait等方法允許您通過EDT執行代碼。

+0

簡單易懂,謝謝 – Yahya

3

大多數用戶發起的事件(點擊,鍵盤)已經在EDT上,因此您不必爲此使用SwingUtilities。這涵蓋了很多情況,除了更新EDT的main()線程和工作線程外。

+0

不是大部分,_all_ – kleopatra

+0

好吧,用戶可以更新正在更新GUI的線程正在監視的文件。 –

+1

嗯...這不會被視爲用戶發起的事件(直接的,這就是規則存在的地方):用戶更新文件(在EDT內部擺動)並保存(通過點擊EDT上的按鈕),這會觸發OS文件更新事件(外部擺動,關閉EDT)通知,該通知到達監視器(關閉EDT),該監視器負責更新EDT上的GUI – kleopatra

7

我這個問題與SwingUtilities.invokeLater有關:我什麼時候應該使用它?

要理解的是,Java有一個單獨的線程(EDT)處理Swing相關的事件。

您應該使用invokeLater()來顯示桌面應用程序的主要JFrame(例如),而不是嘗試在當前線程中執行此操作。它也將創建用於稍後優雅地關閉應用程序的上下文。

對於大多數應用程序來說就是這樣。

每次我需要更新GUI組件時,我必須使用嗎?它究竟做了什麼?

No.如果您修改GUI組件,它將觸發一個事件,該事件將在稍後由Swing調度時進行註冊。如果有這個事件的監聽者,EDT線程會在路上的某個地方調用它。您不需要使用invokeLater(),只需將聽衆設置在正確的組件上即可。

請記住,此線程是相同的線程繪製幀等...在您的屏幕上。因此,聽衆不應執行復雜/長時間/ CPU密集型任務,否則您的屏幕將凍結。

是否有替代方案,因爲它不直觀,並增加了看似不必要的代碼?

您不需要編寫更多的代碼,而只需使用您對組件感興趣的invokeLater() +監聽器來編寫代碼。其餘的由Swing處理。

12
Swing is single threaded and all changes to the GUI must be done on EDT 

基本用法爲invokeLater()

  1. 主要方法應當始終包裹在invokeLater()

  2. 延遲(但異步地)的動作/事件的EventQueue結束時,

  3. 如果EDT不存在,則必須使用創建新的EDT 10。你可以用if (SwingUtilities.isEventDispatchThread()) {...

  4. 存在着invokeAndWait()測試,但直到今天我(只是我的看法)無法找到使用invokeAndWait(),而不是invokeLater()有原因的,除了硬變成GUI(JTree的& JTable的),只是與Substance L&F(優秀的EDT事件的測試一致性)

  5. 基本的東西:Concurrency in Swing

  6. 所有的後臺任務的輸出必須被包裹在invokeLater()

相關問題