我正在尝试实现 StackOverflow 上许多人尝试过的盛宴:在基于 JavaFX 构建的 TextArea 中显示 Java 应用程序的控制台输出。
我已经设法在上述 TextArea 中显示我的输出,但与其他许多人一样,我的 UI 卡住了,因为该线程正在大量加载用于显示 UI 本身的线程。
所以我开始阅读有关 Platform.runLater()
的内容,但它并没有解决我的问题,主要是因为我输出了大量文本,这会减慢所述函数的速度。环顾四周,我进入了this question ,其中提出了一个基于 Task
的很好的解决方案。尽管如此,当我开始在 TextArea 中显示控制台日志时,我的 UI 就一直卡住。我将向您展示我的代码片段,以便您能够告诉我我遗漏了什么和/或做错了什么。
这是我的 JavaFX Controller 的片段:
public class MainViewController extends AbstractController implements Initializable {
@FXML private TextArea textAreaLog;
@Override
public void initialize(URL location, ResourceBundle resources) {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
boolean fxApplicationThread = Platform.isFxApplicationThread();
System.out.println("Is call on FXApplicationThread: " + fxApplicationThread);
Console console = new Console(textAreaLog);
PrintStream ps = new PrintStream(console, true);
System.setOut(ps);
System.setErr(ps);
return null;
}
@Override
protected void succeeded() {
boolean fxApplicationThread = Platform.isFxApplicationThread();
System.out.println("Is call on FXApplicationThread: " + fxApplicationThread);
super.succeeded();
textAreaLog.textProperty().unbind();
}
};
textAreaLog.textProperty().bind(task.messageProperty());
new Thread(task).start();
}
// Console Class
public static class Console extends OutputStream {
private TextArea output;
Console(TextArea ta) {
this.output = ta;
}
@Override
public void write(int i) throws IOException {
output.appendText(String.valueOf((char) i));
}
}
}
我已经编辑了从我之前链接的问题的答案中获取的代码,留下所有调试消息只是为了帮助我。
仅此而已。我的 UI 只是卡住,即使我显然是在后台运行重负载任务,而不是直接在 UI 线程中执行该操作。
最佳答案
我认为问题的根源在于以下之一;
System.out.println("text")
是一个同步方法。- 在 Ui 线程之外访问 ui 组件
当您从 ui 线程调用 System.out.println("text")
时,System.out 上的同步将导致 UI 在同步期间卡住。
您可以检查这是否是原因,如下所示;(您必须像下面这样包装所有 System.out 调用,只是为了测试上述理论是否正确)
这将导致 println
方法在不同线程中同步。(公共(public)池线程)
CompletableFuture.runAsync(()->System.out.println("text"));
您还应该更新 ui 线程中的输出组件。(在这种情况下问题已解决)
// or create new runnable if you are not using java8
Platform.runLater(()->output.appendText(String.valueOf((char) i)));
关于JavaFX:控制台登录 TextArea + 多线程和任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48889125/