我有一个“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 而明白这一点的——但是为什么它可以工作,我该如何调整我的代码以使其正常工作?

最佳答案

  • invokeAndWait 必须在EDT外调用,否则引起a.m.异常,
  • invokeAndWait 小心,因为可以卡住整个 Swing GUI,被 RepaintManager 的异常锁定(并非在所有情况下都只创建 GUI,重新布局,刷新一些方法),然后应用程序需要重新启动,
  • for invokeAndWait 需要在 true 上测试 if (EventQueue.isDispatchThread()) {/if (SwingUtilities.isEventDispatchThread()) { ,你可以到 setText("")/append("" ) 没有任何副作用,输出是在 EDT 上完成的,但关于在 invokeLater
  • 中包装的良好实践
  • 使用 SwingWorker ,有实现方法 process , publish , setProcessdone ,所有提到的方法都通知 EDT by default ,
  • SwingWorker 被指定只运行一次,重复(在某个时期)使用 Executor 作为 SwingWorkerRunnable#Thread 作为最简单、清晰且没有任何副作用,影响
  • 关于java - 其他 JFrame 中的 JTextArea 显示实时控制台输出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17706140/

    10-08 22:34
    查看更多