[英]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.