[英]Java Swing Concurrency display 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");
}
});
}
所以现在,整个执行完成后,“Test”和“Test1”会显示在JTextArea上。 如何首先显示“测试”,然后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和朋友的原因)。
更不为人知的是,痛苦代码也在事件处理线程中执行。 当您对Thread.sleep的调用正在执行时,它不仅会阻塞事件线程,还会阻止任何组件绘制。 这就是全面更新似乎一次性发生的原因 - JTextArea已更新,但在run方法返回之前无法重新绘制。
这里提供了大量信息: http : //java.sun.com/products/jfc/tsc/articles/threads/threads1.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.