【问题标题】:Java: BufferedStreams and event handlersJava:BufferedStreams 和事件处理程序
【发布时间】:2012-02-13 20:38:57
【问题描述】:

我正在使用 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”方法。

在事件处理程序中,直到事件完成运行,文本才会写入文本区域。我想要的是在命令运行时将文本写入控制台(这对于耗时的命令尤其需要)。换句话说,当用户按下回车键时(例如),在将数据打印到 JTextArea 时会运行一个很长的进程,但直到整个进程运行完 后才会显示文本。

有人对我如何解决这个问题有任何想法吗?

【问题讨论】:

    标签: swing events event-handling buffer


    【解决方案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 上执行 - 否则,所有事件活动都将等待。您可以使用threadsexecutors(另见:http://www.baptiste-wicht.com/2010/09/java-concurrency-part-7-executors-and-thread-pools/)来实现这一点。这在很大程度上取决于您要解决的问题。

    应始终在 EDT thread 上调用 Swing GUI 类的方法 - 参见例如如果您有兴趣,这些用于深入解释:

    风格上的一件事——你把你的班级命名为textareaStream。 Java 类应以大写字母开头是事实上的标准。

    【讨论】:

    • 谢谢! executors and thread pools 文章正是我想要的。它就像一个魅力。我非常感谢您在答案中的详细程度,甚至是样式说明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多