2017-03-17 24 views
1

我正在構建和創建流程的應用程序,並將其輸出流傳輸到文本區域。就像終端仿真器一樣,如果進程顯示的行太多,我希望輸出自動滾動到控制檯的末尾。使用自動滾動將流處理輸出到Java FX文本區

問題是文本區域不滾動到文本的末尾,而是停留在頂部。另一個奇怪的行爲是,當我嘗試使用鼠標滾輪/鍵盤/滾動條滾動文本區域時,文本區域滾動到最頂端。

我已經試過答案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 
+0

考慮發佈[MCVE] – c0der

回答

1
所有

Task.call()方法首先是在JavaFX的應用程序線程執行,因此更改在該方法中當前視圖的任何狀態是不合適的。您在錯誤的線程中將""添加到consoleTextArea。你應該做的是這樣的:

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

第二個問題是調用consoleTextArea.appendText("");不會觸發ChangeListener(事實上,它不會做任何事情),因爲你consoleTextArea text屬性綁定到Task消息財產textProperty.bind(bgTask.messageProperty());。在這種情況下,文本區域將僅收聽Task消息屬性中的文本更改。將您的聽衆添加到消息屬性中:

bgTask.messageProperty().addListener((observable, oldValue, newValue) -> { 
    // currently: 
    consoleTextArea.selectPositionCaret(consoleTextArea.getLength()); 
    consoleTextArea.deselect(); 

    // also tried: 
    // consoleTextArea.setScrollTop(Double.MAX); 
});