2010-09-29 77 views
0

在下一個代碼中應該有一個錯誤/遺漏,但我看不到主要是因爲我從來沒有使用過線程。有人可以找到我失蹤的東西嗎?這裏有什麼遺漏/錯誤?

import java.awt.BorderLayout; 
import java.awt.Button; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Timer; 
import java.util.TimerTask; 

import javax.swing.JDialog; 
import javax.swing.JLabel; 

public class JavaSwingTest extends JDialog { 
    private JLabel m_countLabel; 

    private Timer m_timer = new Timer(); 

    private class IncrementCountTask extends TimerTask { 
     @Override 
     public void run() { 
      m_countLabel.setText(Long.toString(System.currentTimeMillis() 
/1000)); 
     } 
    } 

    private JavaSwingTest() { 
     createUI(); 

     m_timer.schedule(new IncrementCountTask(), 1000, 1000); 
    } 

    private void createUI() { 
     Button button1 = new Button("Action1"); 
     button1.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       doLongOperation(); 
      } 

     }); 
     add(button1, BorderLayout.NORTH); 

     m_countLabel = new JLabel(Long.toString(System.currentTimeMillis() 
/1000)); 
     add(m_countLabel, BorderLayout.CENTER); 
    } 

    /** 
    * Simulates an operation that takes time to complete. 
    */ 
    private void doLongOperation() { 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException e) { 
      // ignored for this test 
     } 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     new JavaSwingTest().setVisible(true); 
    } 
} 
+1

這個省略/錯誤是你省略了你問題的一部分,你告訴我們你想要解決的錯誤是什麼。 – 2010-09-29 19:29:40

+0

嗯。您正在設置線程(不是主線程(定時器))的Swing組件的值。 – Dirk 2010-09-29 19:33:52

+1

@Dirk:'setText'是線程安全的極少數Swing方法之一。 – 2010-09-29 19:38:09

回答

1

Swing與大多數UI工具包一樣,不是線程安全的。您的setText()調用應該被轉發到事件線程。

要從計時器線程啓動GUI工作,請使用SwingUtilities .invokeLater()或invokeAndWait()。

+0

很好的答案,謝謝。 – 2010-09-29 21:58:29

1

正如其他人所說,setText()應該從Swing Event Dispatch Thread調用,因爲它不是線程安全的。解決這個問題的最簡單方法是使用javax.swing.Timer(這稱爲EDT上已有的操作),而不是java.util.Timer

1

使用SwingWorker將允許您的doLongOperation()在不阻止EDT的情況下執行,同時還提供定期更新GUI的便捷方式。 Theres一個完整的例子here