1

I have a scroll pane inside it an anchor pane. and inside this anchor pane i have a label. I need this label to always be visible when i scroll. I need to move so that the user always see it as if it didn't change. Can anyone help?

@FXML
 private ScrollPane s;


public void initialize(URL location, ResourceBundle resources) {                           
                AnchorPane p = new AnchorPane();
                VBox v = new VBox();
                p.getChildren().add(v);
                s.setContent(p);}
  • You should show some code, it will help to get some answers – Yanga Dec 03 '16 at 08:48
  • For that the position of the node (Label) will have to be dynamic also ! – Bo Halim Dec 03 '16 at 09:12
  • @BoHalim how do i fix that – user6601127 Dec 03 '16 at 09:51
  • Possible duplicate of [How to scroll to make a Node within the content of a ScrollPane visible?](http://stackoverflow.com/questions/12837592/how-to-scroll-to-make-a-node-within-the-content-of-a-scrollpane-visible) – Bo Halim Dec 03 '16 at 09:54
  • 1
    @BoHalim Nope, that one is about scrolling to make a certain node visible, this one is about keeping a node visible independent of the scroll position however. – fabian Dec 03 '16 at 10:01

1 Answers1

2

The easiest way to accomplish this would be not placing the Label inside the content, but in a StackPane that contains both the ScrollPane and the Label:

@Override
public void start(Stage primaryStage) {
    Region content = new Region();
    content.setPrefSize(2000, 2000);
    content.setBackground(new Background(new BackgroundFill(
            new LinearGradient(0, 0, 1, 1, true, CycleMethod.NO_CYCLE, new Stop(0, Color.RED), new Stop(1, Color.BLUE)),
            CornerRadii.EMPTY,
            Insets.EMPTY)));

    Label label = new Label("Hello World!");
    label.setTextFill(Color.WHITE);
    StackPane.setAlignment(label, Pos.TOP_LEFT);
    StackPane.setMargin(label, new Insets(10));

    ScrollPane scrollPane = new ScrollPane(content);

    StackPane root = new StackPane();
    root.getChildren().addAll(scrollPane, label);

    Scene scene = new Scene(root, 200, 200);

    primaryStage.setScene(scene);
    primaryStage.show();
}

Or you could alternatively adjust the position using the translate properties:

@Override
public void start(Stage primaryStage) {
    Label label = new Label("Hello World!");
    label.setTextFill(Color.WHITE);

    Pane content = new Pane(label);
    content.setPrefSize(2000, 2000);
    content.setBackground(new Background(new BackgroundFill(
            new LinearGradient(0, 0, 1, 1, true, CycleMethod.NO_CYCLE, new Stop(0, Color.RED), new Stop(1, Color.BLUE)),
            CornerRadii.EMPTY,
            Insets.EMPTY)));

    ScrollPane scrollPane = new ScrollPane(content);

    double targetX = 10;
    double targetY = 10;

    InvalidationListener listener = o -> {
        Bounds viewportBounds = scrollPane.getViewportBounds();
        Bounds contentBounds = content.getBoundsInLocal();
        Bounds labelBounds = label.getBoundsInLocal();

        double factorX = Math.max(contentBounds.getWidth() - viewportBounds.getWidth(), 0);
        double factorY = Math.max(contentBounds.getHeight() - viewportBounds.getHeight(), 0);

        label.setTranslateX(targetX + scrollPane.getHvalue() * factorX - labelBounds.getMinX());
        label.setTranslateY(targetY + scrollPane.getVvalue() * factorY - labelBounds.getMinY());
    };

    scrollPane.viewportBoundsProperty().addListener(listener);
    scrollPane.hvalueProperty().addListener(listener);
    scrollPane.vvalueProperty().addListener(listener);
    label.boundsInLocalProperty().addListener(listener);

    Scene scene = new Scene(scrollPane, 200, 200);

    primaryStage.setScene(scene);
    primaryStage.show();

    listener.invalidated(null);
}
fabian
  • 80,457
  • 12
  • 86
  • 114