2011-08-29 22 views
6

我有一個主程序,其中GUI基於swing,並且取決於四種狀態之一GUI元素具有不同的參數。由java中的另一個線程刷新GUI(swing)

public class Frame extends JFrame implements Runnable { 
Status status = 1; 
... 
@Override 
public void run() { 
    switch (status) { 
     case 1: 
     ... 
     case 2: 
     ... 
} 

public void updateGUI(Status status) { 
    this.status = status; 
    SwingUtilities.invokeLater(this); 
} 

如果我想刷新GUI只調用具有適當參數的updateGUI,一切都很好。但該程序還創建了一個額外的線程,在處理完相關數據後,應該更改GUI主程序。不幸的是我不能在這個線程中調用updateGUI(..)方法。

我知道我可以使用invokeLater或SwingWorker來刷新,但有超過10個元素,所以我寧願使用方法udpateGUI()。

我將不勝感激任何提示。

+0

請看看在這個問題上關於事件和事件總線的答案: http://stackoverflow.com/questions/7131484/how-to-pass-the-message-from-working-thread-to -gui-in-java/7131574#7131574 –

+0

爲什麼你不能從另一個線程調用updateGUI?除了對狀態變量的非同步訪問,我不明白爲什麼你不能從另一個線程使用這個方法。 –

+0

如果我調用Frame f = new Frame(); f.udpateGUI(..);那麼當然沒有事情發生。我還能如何調用這種方法? – galica

回答

7

如果使status場線程安全的,那麼你可以直接從後臺線程中調用setStatus。要使狀態成爲線程安全的,請將更改置於同步塊中,並使該變量易變,以便其他線程上的更新可見。

例如

public class Frame extends JFrame implements Runnable { 
private volatile Status status = 1; 
... 
@Override 
public void run() { 
    switch (status) { 
     case 1: 
     ... 
     case 2: 
     ... 
} 

public void updateGUI(Status status) { 
    setStatus(status); 
    SwingUtilities.invokeLater(this); 
} 

private synchronized void setStatus(Status status) { 
    this.status = status; 
} 

隨着這些變化的地方,這是確定調用setStatus從任何線程。

16

下面是一個小小的片段,您可以將其添加到方法中以確保它在GUI線程中執行。它依賴於isEventDispatchThread()

public void updateGUI(final Status status) { 
    if (!SwingUtilities.isEventDispatchThread()) { 
    SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
      updateGUI(status); 
     } 
    }); 
    return; 
    } 
    //Now edit your gui objects 
    ... 
} 
+0

謝謝,這也有幫助。 – galica