2010-12-15 65 views
2

我需要執行/顯示從Arraylist到JTextArea的一系列事件,但是,每個事件都會在不同的時間執行。以下是我的目標,一個簡單的例子:Java Swing併發顯示JTextArea

public void start(ActionEvent e) 
{ 
    SwingUtilities.invokeLater(new Runnable() 
    { 
    public void run() 

    { 
    jTextArea.append("Test" + "\n"); 
    try 
    { 
    Thread.sleep(3000); 
    } catch (InterruptedException e1) 
    { 
    e1.printStackTrace(); 
    } 
    jTextArea.append("Test1" + "\n"); 
    } 
    }); 
} 

所以現在,「測試」和整個執行完畢後的JTextArea「測試1」顯示。 如何使「測試」顯示,再3秒後,顯示「Test1的」

感謝ü所有提前

回答

5

invokeLater調度可運行對事件調度線程中運行。你不應該睡在裏面,否則你會餓死派遣線程。嘗試使用單獨的工作線程代替:

Thread worker = new Thread(new Runnable(){ 
    public void run(){ 
     jTextArea.append("Test" + "\n"); 
     try { 
      Thread.sleep(3000); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     jTextArea.append("Test1" + "\n"); 

    } 
}); 
worker.start(); 
+0

感謝這麼多。有效! – Jack 2010-12-15 18:35:31

+0

根據我的經驗,即使JTextArea#append被列爲「線程安全」,因此可以從EDT調用,但實際上在很多情況下並非如此,並且此方法也應該在EDT上調用。 – 2010-12-15 18:49:06

2

正如指出的那樣,這是一個壞主意,因爲您將阻止事件線程。

但是,瞭解其原因也很重要。如你所知,影響Swing組件狀態的所有代碼都需要在事件處理線程中發生(這就是爲什麼總是使用invokeLater和朋友的原因)。

有一點不太好的知道是痛苦的代碼也在事件處理線程中執行。當你對Thread.sleep的調用正在執行時,它不僅阻塞了事件線程,而且還阻塞了任何組件的繪製。這就是爲什麼完整更新似乎一次性發生 - JTextArea已更新,但在您的運行方法返回之前無法重新繪製。

很多可以在這裏找到信息的:http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

3

如果你的任務是時間/ CPU密集型,那麼,肯定使用一個後臺線程來做到這一點,如SwingWorker的對象或主題中的Runnable運行。但是,如果您需要做的是錯開顯示內容並且您正在尋找的是Thread.sleep(3000)的Swing等價物,那麼最好的選擇是使用Swing Timer。有關於如何使用這些,你可以在這裏找到一個很好的教程:http://download.oracle.com/javase/tutorial/uiswing/misc/timer.html

例如:

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

public class Fu extends JPanel { 
     private static final int TIMER_DELAY = 600; 
     protected static final int MAX_COUNT = 20; 
     private JTextArea jTextArea = new JTextArea(10, 10); 
     private JButton startBtn = new JButton("Start"); 
     private Timer timer; 

     public Fu() { 
      startBtn.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent e) { 
        startAction(e); 
       } 
      }); 

      add(new JScrollPane(jTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)); 
      add(startBtn); 
     } 

     private void startAction(ActionEvent e) { 
      if (timer != null && timer.isRunning()) { 
       // prevent multiple instances of timer from running at same time 
       return; 
      } 
      timer = new Timer(TIMER_DELAY, new ActionListener() { 
       private int count = 0; 
       public void actionPerformed(ActionEvent e) { 
        if (count < MAX_COUNT) { 
          count++; 
          jTextArea.append("Test " + count + "\n"); 
        } else { 
          jTextArea.append("Done! \n"); 
          timer.stop(); 
          timer = null; 
        } 
       } 
      }); 
      timer.setInitialDelay(0); 
      timer.start(); 
     } 

     public static void main(String[] args) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        JFrame frame = new JFrame("Foo"); 
        frame.getContentPane().add(new Fu()); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } 
      }); 
     } 
}