How to control the JavaFX TextArea auto scroll?

2019-09-15 16:05发布

In my application I am appending the text to TextArea every 2 minutes. When ever I append new line to TextArea the auto scroll automatically going to down. But I want to stay the scroll where i am keep the scroll button. How to do it in JavaFX.

logTextArea.appendText("Here i am appending text to text area"+"\n");
logTextArea.setScrollTop(Double.MIN_VALUE);

I tried this but scroll automatically going to down , but I need to keep my scroll chosen position I don't want to go automatically down.

How can I do this?

3条回答
Root(大扎)
2楼-- · 2019-09-15 16:25

The most straightforward way is to remember the position of the caret and restore it after it gets moved by appendText or setText.

Here's how you can do it:

int caretPosition = area.caretPositionProperty().get();
area.appendText("Here i am appending text to text area"+"\n");
area.positionCaret(caretPosition);
查看更多
地球回转人心会变
3楼-- · 2019-09-15 16:29

Maybe you could just add a changeListener to the TextArea which does nothing, or it just scrolls to the top of the TextArea everytime the text inside it is changed.

logTextArea.textProperty().addListener(new ChangeListener<Object>() {
  @Override
  public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) {
      logTextArea.setScrollTop(Double.MIN_VALUE); //this will scroll to the top
  }
});

Now when you logTextArea.appendText("Here i am appending text to text area"+"\n"); to the TextArea, it should stay at the top.

The idea is taken from: JavaFX TextArea and autoscroll

查看更多
一纸荒年 Trace。
4楼-- · 2019-09-15 16:38

You can write your own function to append text. In this method you can use setText, rather than appendText as appendText automatically scrolls to the end of the content (setText scrolls to the beginning but this can be supressed by setting back the scrollTopProperty to its previous value).

Example

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);

            TextArea ta = new TextArea();
            root.setCenter(ta);
            Button button = new Button("Append");
            button.setOnAction(e -> {
                appendTextToTextArea(ta, "BlaBlaBla\n");
            });
            root.setBottom(button);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }


    /**
     * Appends text to the end of the specified TextArea without moving the scrollbar.
     * @param ta TextArea to be used for operation.
     * @param text Text to append.
     */
    public static void appendTextToTextArea(TextArea ta, String text) {
        double scrollTop = ta.getScrollTop();
        ta.setText(ta.getText() + text);
        ta.setScrollTop(scrollTop);
    }
}

Note:

Alternatively you can also extend TextArea and overload appendText to be able to specify whether you want to move the scrollbar:

public class AppendableTextArea extends TextArea {

    public void appendText(String text, Boolean moveScrollBar) {
        if (moveScrollBar)
            this.appendText(text);
        else {
            double scrollTop = getScrollTop();
            setText(getText() + text);
            setScrollTop(scrollTop);
        }
    }
}

and the usage:

AppendableTextArea ta = new AppendableTextArea();
ta.appendText("BlaBlaBla\n", false);
查看更多
登录 后发表回答