DJa*_*mes 2 java concurrency user-interface swing jtextarea
我正在用一个按钮编写一个GUI.当用户单击该按钮时,我希望立即在JTextArea中显示"Beginning work ..."消息,并显示"已完成".工作完成时显示的消息.GUI包含表单的一些代码
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
myJTextArea.append("Beginning work...\n");
<more lines of code>
myJTextArea.append("Finished.\n");
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,直到最后都没有消息.有没有办法将消息刷新到JTextArea?在另一个论坛上,我看到有人提到为JTextArea输出运行一个单独的线程.基于此的一些解决方案是否可行?
谢谢
不幸的是,直到最后都没有消息.有没有办法将消息刷新到JTextArea?在另一个论坛上,我看到提到为JTextArea输出运行一个单独的线程.基于此的一些解决方案是否可行?
这与"刷新"JTextArea无关,而是与确保您的代码遵循Swing线程规则有关.输出到JTextArea的长时间运行的代码应该在后台线程中调用,例如使用SwingWorker.然后它将间歇性地将其结果输出到JTextArea,但确保在Swing事件线程上小心地这样做.如果您使用SwingWorker,可以使用发布/处理方法对完成.
看看:教程:Swing中的并发.
例如:
import java.util.List;
import javax.swing.*;
public class SwingThreadingEg extends JPanel implements MyAppendable {
private JTextArea area = new JTextArea(30, 50);
public SwingThreadingEg() {
JScrollPane scrollPane = new JScrollPane(area);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scrollPane);
}
@Override
public void append(String text) {
area.append(text);
}
private static void createAndShowGui() {
SwingThreadingEg mainPanel = new SwingThreadingEg();
MyWorker myWorker = new MyWorker(mainPanel);
// add a Prop Change listener here to listen for
// DONE state then call get() on myWorker
myWorker.execute();
JFrame frame = new JFrame("SwingThreadingEg");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyWorker extends SwingWorker<Void, String> {
private static final long SLEEP_TIME = 500;
private MyAppendable myAppendable;
public MyWorker(MyAppendable myAppendable) {
this.myAppendable = myAppendable;
}
@Override
protected Void doInBackground() throws Exception {
publish("Beginning Work");
// simulate some long-running task:
for (int i = 0; i < 20; i++) {
publish("From SwingWorker: " + i);
Thread.sleep(SLEEP_TIME);
}
publish("Finished!");
return null;
}
@Override
protected void process(List<String> chunks) {
for (String text : chunks) {
myAppendable.append(text + "\n");
}
}
}
interface MyAppendable {
public void append(String text);
}
Run Code Online (Sandbox Code Playgroud)
代码改编自我的代码,回答了以前的类似问题.
注意,如果您要使用标准的Runnable和没有SwingWorker的后台线程,正如Lars所建议的那样,您首先要实现Runnable而不是扩展Thread,并且您必须注意大多数Swing调用排队到事件线程,因此类似于:
@Override
public void actionPerformed(ActionEvent e) {
textarea.append("Start...");
new Thread(new Runnable(){
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
textarea.append("End");
}
});
}
}).start();
}
Run Code Online (Sandbox Code Playgroud)
对于所有嵌套的匿名内部类,这看起来有点复杂,事实上这是SwingWorker在这种情况下可以更好地工作的主要原因之一,因为使用的代码更简单,减少了创建看不见的错误的机会.
| 归档时间: |
|
| 查看次数: |
1136 次 |
| 最近记录: |