2010-12-15 82 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); 
       } 
      }); 
     } 
}