4

我有一个“ConsoleFrame”,它应该将我的控制台输出实时显示到 JTextArea。

我重定向了输出流:

private void redirectSystemStreams() {
    OutputStream out = new OutputStream() {
        @Override
        public void write(int b) throws IOException {
            updateTextArea(String.valueOf((char) b));
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            updateTextArea(new String(b, off, len));
        }

        @Override
        public void write(byte[] b) throws IOException {
            write(b, 0, b.length);
        }
    };

    System.setOut(new PrintStream(out, true));
    System.setErr(new PrintStream(out, true));
}

并调用 SwingUtilities.invokeAndWait 方法来附加新文本,效果很好

private void updateTextArea(final String text) {
    try {
        SwingUtilities.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                txt_console.append(text);
            }
        });
    } catch (InterruptedException ex) {
    } catch (InvocationTargetException ex) {
    }
}

但它在我的新 ConsoleFrame 中向我显示了这个错误:java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread 我得到了因为 EDT - 但它为什么工作以及如何调整我的代码以使其工作适当地?

4

2 回答 2

2
  • invokeAndWait必须从 EDT 中调用,否则会导致异常,

  • 小心invokeAndWait,因为可以冻结整个 Swing GUI,被异常锁定RepaintManager(并非在所有情况下都只创建 GUI,重新布局,刷新一些方法),然后应用程序需要重新启动,

  • forinvokeAndWait需要测试if (EventQueue.isDispatchThread()) {/ if (SwingUtilities.isEventDispatchThread()) {on true 你可以到setText("")/ append("") 没有任何副作用,输出是在 EDT 上完成的,但是关于包装内部的良好实践invokeLater

  • 使用SwingWorker,有实现的方法process,和publish,所有提到的方法通知,setProcessdoneEDT by default

  • SwingWorker被指定为只运行一次,重复(在某个时期)使用ExecutorSwingWorker作为Runnable#Thread最简单、清晰且没有任何副作用、效果

于 2013-07-17T17:37:20.743 回答
0

您可以SwingUtilities.invokeLater()从任何线程中使用,对于错误流,即使您已经在 EDT 中,也可能最好使用它:

private void updateTextArea(final String text) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            txt_console.append(text);
        }
    });
}

您收到的特定错误来自 EDT 外部,然后invokeAndWait()可能会被调用,以便您将输出输出到控制台。

于 2013-07-17T17:27:13.997 回答