我正在使用JTextArea处理“控制台”,一切都很好,除了输出不能像我想要的那样工作。
我正在使用Stackoverflow上找到的类的修改版本。
import java.io.*;
import javax.swing.*;
public class textareaStream extends OutputStream {
//*************************
//* Parameters
//*************************
private JTextArea textArea; // target text area
private byte[] aByte; // array for write(int val);
//*************************
//* Constructor
//*************************
public textareaStream(JTextArea ta) {
textArea=ta;
aByte=new byte[1];
}
//*************************
//* Writing methods
//*************************
public void write(int val) {
aByte[0]=(byte)val;
write(aByte,0,1);
}
public void write(byte[] ba) {
write(ba,0,ba.length);
}
public synchronized void write(byte[] ba,int str,int len) {
try {
for(int xa=0; xa<10; xa++) {
try {
textArea.append(new String(ba,str,len));
break;
} catch(Throwable thr) {
if (xa==9) {
thr.printStackTrace();
} else {
Thread.sleep(200);
}
}
}
} catch(Throwable thr) {
CharArrayWriter caw=new CharArrayWriter();
thr.printStackTrace(new PrintWriter(caw,true));
textArea.append(System.getProperty("line.separator","\n"));
textArea.append(caw.toString());
}
}
}
这很有效,除非从事件处理程序调用“write”方法。
在事件处理程序中,在事件完成运行之前,文本不会写入textarea。我想要的是在命令运行时将文本写入控制台(这对于耗时的命令尤其需要)。换句话说,当用户点击回车键(例如)时,在将数据打印到JTextArea时会运行一个长进程,但是在之后整个进程运行之前,文本才会显示。
有没有人对如何解决这个问题有任何想法?
答案 0 :(得分:1)
如果我理解正确,您可以在某个事件处理程序中使用您的类,并在那里调用write
方法。如果是这种情况,您可以使用SwingUtilities.invokeLater方法。请参阅此示例:
http://www.javamex.com/tutorials/threads/invokelater.shtml
基本上,你可以在这些方面创建一个辅助方法:
private void writeOnEDT(final byte[] ba, final int str, final int len) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
instance.write(ba, str, len);
}
});
}
其中instance
是您的textareaStream
类的实例。如果您决定将其放在同一个班级中,只需删除instance.
并使用writeOnEDT
代替write
,它就可以正常运行。
请注意,无论您在长时间运行的作业必须不在EDT上执行 - 否则,所有活动活动都将等待。您可以使用threads或executors(另请参阅:http://www.baptiste-wicht.com/2010/09/java-concurrency-part-7-executors-and-thread-pools/)来实现这一目标。这在很大程度上取决于您试图解决的问题。
应始终在EDT thread上调用Swing方法 - 请参阅例如如果您有兴趣,请进行深入解释:
一种风格的东西 - 你为你的班级textareaStream
命名。事实上,Java类应该以大写字母开头。