I'm building and app that creates a process, and streams its stdout into a javafx text area. Just like terminal emulators, I want the output to automatically scroll to the end of the console if the process shows too many lines.
The problem is the text area does not scroll to the end of the text, but rather stay at the top. Another weird behavior is when I try to scroll the text area using mouse wheel / keyboard / scroll bar, the text area scrolls to the very top.
I already tried the answers here, here, and here. It seems that I have something wrong somewhere else.
Here is the content of method void streamToTextArea(java.lang.Process process)
- The method that does the heavy lifting in executing the process and streaming it to the 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