使用自动滚动将流程输出流输出到Java FX文本区域

时间:2017-03-17 03:57:37

标签: java javafx process javafx-8 daemon

我正在构建和创建流程的应用,并将其标准输出流式传输到文本区域。就像终端仿真器一样,如果进程显示太多行,我希望输出自动滚动到控制台的末尾。

问题是文本区域不会滚动到文本的末尾,而是保持在顶部。另一个奇怪的行为是当我尝试使用鼠标滚轮/键盘/滚动条滚动文本区域时,文本区域滚动到最顶层。

我已经尝试了答案hereherehere。似乎我在其他地方出了问题。

以下是方法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

1 个答案:

答案 0 :(得分:1)

首先,Task.call()方法在JavaFX应用程序线程中执行而不是,因此更改此方法中当前视图的任何状态都是不合适的。您正在错误的帖子中将""添加到consoleTextArea。你应该这样做:

Platform.runLater(() -> {
    consoleTextArea.appendText("");
});

第二个问题是调用consoleTextArea.appendText("");不会触发你的ChangeListener(事实上,它什么都不做),因为你将consoleTextArea文本属性绑定到Task消息属性{{1} }。在这种情况下,文本区域将仅监听textProperty.bind(bgTask.messageProperty());消息属性中的文本更改。将您的侦听器添加到消息属性:

Task