swing 将system.out输出的信息重定向到JTEXTAREA

来源:互联网 发布:laravel mac 环境 编辑:程序博客网 时间:2024/05/11 19:20

一、处理系统输出的系统重新连接填充到一个inputstream,以供第二部的JtextArea组建读取数据并显示;

具体思路:new一个新的线程处理SYSTEM.OUT的数据。通过管道输出流与输入流连接,将数据传输到一个PipedInputStream。

 LoopedStreams.java

package ywcai.ls.data;
import java.io.*;
public class LoopedStreams {


private PipedOutputStream pipedOS = 
new PipedOutputStream();
private boolean keepRunning = true;
private ByteArrayOutputStream byteArrayOS =
new ByteArrayOutputStream(1024) {
public void close() {
keepRunning = false;
try {
super.close();
pipedOS.close();
}
catch(IOException e) {
System.exit(1);
}
}
};


private PipedInputStream pipedIS = new PipedInputStream() {
public void close() {
keepRunning = false;
try    {
super.close();
}
catch(IOException e) {
System.exit(1);
}
}
};


public LoopedStreams() throws IOException {
pipedIS.connect(pipedOS);
startByteArrayReaderThread();

public InputStream getInputStream() {
return pipedIS;

public OutputStream getOutputStream() {
return byteArrayOS;

private void startByteArrayReaderThread() {
new Thread(new Runnable() {
public void run() {


while(keepRunning) {
if(byteArrayOS.size() > 0) {
byte[] buffer = null;
synchronized(byteArrayOS) {
buffer = byteArrayOS.toByteArray();
byteArrayOS.reset(); // 清除缓冲区
}
try {
pipedOS.write(buffer, 0, buffer.length);
}
catch(IOException e) {
System.exit(1);
}


}
else
{

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


}
}
}).start();


二、继承一个JTextArea类,重定向system.out数据,并读取。

package ywcai.ls.data;

import java.io.*;
import javax.swing.*;

public class ConsoleText extends JTextArea
{
private static final long serialVersionUID = 1L;
/**

*/
public ConsoleText() {
LoopedStreams ls = null;
try {
ls = new LoopedStreams();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PrintStream ps = new PrintStream(ls.getOutputStream(),true);
System.setOut(ps);
System.setErr(ps);
startConsoleReaderThread(ls.getInputStream());


private void startConsoleReaderThread(InputStream inStream) 
{
final BufferedReader br =new BufferedReader(new InputStreamReader(inStream));
new Thread(new Runnable() {
public void run() {
StringBuffer sb = new StringBuffer();
try {
String s;
while( (s=br.readLine()) != null) {
sb.setLength(0);
append(sb.append(s).append("\n").toString());
setCaretPosition(getText().length());
}
}
catch(Exception e) {
e.printStackTrace();



}
}).start();
}
}


三、在主程序创建consoleTextArea实例

代码省略;


四、问题:

处理按纽点击事件,所有的信息均需要等待按纽时间处理完成后,consoleTextArea才能显示控制台信息,而且是一次性显示;

开始一直以为是LoopedStreams 处理的方式有问题。

最后发现原因:swing在处理事件时,由于UI更新与按纽点击等事件都属于EDT类事件处理线程,需按队列进行处理,因此当时间进行耗时较长操作时就会感觉客户端无响应。

五、解决办法:

在编写点击事件处理实务代码时,新开辟一个工作线程进行处理,这样UI更新无需等待时间处理完毕,即可达到同步输出控制台信息的需求。

button_sub.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {

            new Thread(new Runnable() {//开辟一个工作线程   
                   @Override  
                   public void run() {
            updateAll();//需处理的实务
                   }   
               }).start();   
}
});



0 0
原创粉丝点击