我正在构建和创建流程的应用,并将其标准输出流式传输到javafx文本区域。就像终端仿真器一样,如果进程显示太多行,我希望输出自动滚动到控制台的末尾。
问题是文本区域不会滚动到文本的末尾,而是保持在顶部。另一个奇怪的行为是当我尝试使用鼠标滚轮/键盘/滚动条滚动文本区域时,文本区域滚动到最顶层。
我已经尝试了答案here,here和here。似乎我在其他地方出了问题。
以下是方法void streamToTextArea(java.lang.Process process)
的内容 - 执行流程并将其流式传输到consoleTextArea
的繁重方法。
Task bgTask = new Task<Void>() {
@Override
protected void call() throws Exception {
InputStream inputStream = process.getInputStream();
StringBuilder consoleContent = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while((line = reader.readLine()) != null) {
consoleContent
.append(line)
.append("\n");
updateMessage(consoleContent.toString());
consoleTextArea.appendText(""); // trigger ChangeListener
}
} catch (IOException e) { doSomething(e); }
return null;
}
};
StringProperty textProperty = consoleTextArea.textProperty();
textProperty.addListener((observable, oldValue, newValue) -> {
// currently:
consoleTextArea.selectPositionCaret(consoleTextArea.getLength());
consoleTextArea.deselect();
// also tried:
// consoleTextArea.setScrollTop(Double.MAX);
});
textProperty.bind(bgTask.messageProperty());
// start bgTask as daemon thread
// add event handling when bgTask ended
答案 0 :(得分:1)
首先,Task.call()
方法在JavaFX应用程序线程中执行而不是,因此更改此方法中当前视图的任何状态都是不合适的。您正在错误的帖子中将""
添加到consoleTextArea
。你应该这样做:
Platform.runLater(() -> {
consoleTextArea.appendText("");
});
第二个问题是调用consoleTextArea.appendText("");
不会触发你的ChangeListener
(事实上,它什么都不做),因为你将consoleTextArea文本属性绑定到Task
消息属性{{1} }。在这种情况下,文本区域将仅监听textProperty.bind(bgTask.messageProperty());
消息属性中的文本更改。将您的侦听器添加到消息属性:
Task