Java Swing Concurrency显示JTextArea

我需要执行/显示从Arraylist到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上会显示“Test”和“Test1”。 如何先进行“测试”显示,然后在3秒后显示“Test1”

提前谢谢你们

invokeLater计划runnable在Event Dispatch Thread上运行。 你不应该睡在它里面,否则你会使调度线程饿死。 请尝试使用单独的工作线程:

 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(); 

如果您的任务是时间/ CPU密集型,那么肯定是使用后台线程来执行此操作,例如SwingWorker对象或线程中的Runnable运行。 但是,如果您需要做的是错开某些东西的显示,而您正在寻找的是Swing等效的Thread.sleep(3000),那么您最好的选择是使用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); } }); } } 

正如所指出的,这是一个坏主意,因为您将阻止事件线程。

但是,了解其原因也很重要。 您似乎知道,所有影响Swing组件状态的代码都需要在事件处理线程中发生(这就是为什么应该始终使用invokeLater和friends的原因)。

更不为人知的是,痛苦代码也在事件处理线程中执行。 当您对Thread.sleep的调用正在执行时,它不仅会阻塞事件线程,还会阻止任何组件绘制。 这就是全面更新似乎一次性发生的原因 – JTextArea已更新,但在运行方法返回之前无法重新绘制。

这里提供了大量信息: http : //java.sun.com/products/jfc/tsc/articles/threads/threads1.html