更新的JLabel我有一個創建許多基於名稱的用戶輸入列表面板,與用戶輸入的每一個名字面板的Swing應用程序。在應用程序的底部,我有一個JPanel,帶有一個關閉當前面板的按鈕和一個顯示當前打開面板數的JLabel。從JButton的ActionListener的
我初始化像這樣
String[] usernames = input("Usernames");
int totalTabs = usernames.length;
JLabel lblRemaining = new JLabel("Remaining: " + totalTabs);
標籤然後我加入了一個動作偵聽器的關閉按鈕,並嘗試使用的SwingWorker更新標籤,但它只是似乎沒有更新。
close.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
unlookup(username);
SwingWorker<String, String> updateLabel = new SwingWorker<String, String>(){
@Override
protected String doInBackground() throws Exception {
String tabTotal = Integer.toString(desktop.getTabCount());
return tabTotal;
}
@Override
protected void done(){
try {
lblRemaining.setText(get());
System.out.println(get());
} catch (Exception ignore) {
}
}
};
updateLabel.execute();
}
});
println的是顯示在控制檯中正確的數字,所以我知道它一定有什麼做的GUI沒有更新,但我似乎無法推測出來!
我是相當新的Java和搖擺,所以希望它的東西很明顯,我做錯了!
謝謝:)
使用SwingWorker有什麼意義?在除事件派發線程之外的任何線程中訪問任何Swing類(包括作爲JTabbedPane的「桌面」)都是非法的,因此在doInBackground中使用它會導致未定義的結果。您的ActionListener已經在EDT上運行。 「lblRemaining.setText(Integer.toString(desktop.getTabCount()));」是你在action中所需要的所有東西。 (除了「unlookup(用戶名)」,這是神祕的,可能與這個問題沒有關係)。 – laszlok
@laszlok,doInBackground()方法不訪問GUI。它返回一個字符串值,然後在done()方法中訪問,該方法在EDT上執行。所以SwingWorker代碼看起來是正確的。同意SwingWorder可能不是必要的,因爲它看起來並不像它正在執行任何長時間運行的任務,這會凍結GUI,因此所有代碼都可能在ActionListener本身中。 – camickr
@camickr,請閱讀https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html - desktop.getTabCount()方法是一種Swing組件方法,它不標記線程安全並因此調用它在EDT以外的線程上,如教程所述,「存在線程干擾或內存一致性錯誤的風險」。它不涉及繪畫(如果這就是你的意思是「不訪問GUI」)是不重要的。 – laszlok