Смещение двух синхронизированных панелей прокрутки - PullRequest
0 голосов
/ 02 сентября 2018

Я пытаюсь выровнять положение вертикальной прокрутки двух javafx.scene.control.ScrollPane s с помощью

sp1.vvalueProperty().bindBidirectional(sp2.vvalueProperty());

Проблема в том, что одна из этих панелей прокрутки может иметь горизонтальную полосу прокрутки. Поэтому, чем больше я прокручиваю ScrollPanes, тем больше они смещаются (см. Скриншот). Как я могу справиться с этим?

javafx scollpane misaligned

1 Ответ

0 голосов
/ 03 сентября 2018

Невозможно сделать это с 2 ScrollPane с и содержимым одинаковой высоты, если вы не отобразите полосу прокрутки в обоих ScrollPane с:

Рассмотрим случай, когда содержимое точно соответствует viewport слева ScrollPane. viewPort справа ScrollPane можно прокрутить по высоте ScrollBar. Изменение левого ScrollPane невозможно.

Поскольку ожидаемый результат представляет собой некую шкалу, вы можете просто использовать Pane с ребенком, к которому вы применяете transformY, и клипом. Формула для расчета пикселя для размещения сверху, используйте

top = vvalue * (contentHeight - viewportHeight)

Пример

private static Label createLabel(int num, boolean mark) {
    Label label = new Label(Integer.toString(num));
    label.setPrefSize(50, 50);
    label.setMaxSize(Double.MAX_VALUE, Region.USE_PREF_SIZE);
    label.setStyle(mark ? "-fx-background-color: #FFFFFF" : "-fx-background-color: #BBBBBB;");
    return label;
}

@Override
public void start(Stage primaryStage) throws Exception {
    VBox scale = new VBox();
    scale.setMinHeight(Region.USE_PREF_SIZE);
    GridPane content = new GridPane();

    for (int i = 0; i < 40; i++) {
        boolean b = ((i % 2) == 0);
        scale.getChildren().add(createLabel(i, !b));

        for (int j = 0; j < 10; j++) {
            content.add(createLabel(i * 10 + j, b), j, i);
        }
    }

    AnchorPane scaleContainer = new AnchorPane(scale);
    scaleContainer.setMinWidth(30);
    scaleContainer.setMinHeight(0);
    AnchorPane.setLeftAnchor(scale, 0d);
    AnchorPane.setRightAnchor(scale, 0d);

    Rectangle clip = new Rectangle();
    scaleContainer.setClip(clip);
    clip.widthProperty().bind(scaleContainer.widthProperty());
    clip.heightProperty().bind(scaleContainer.heightProperty());

    ScrollPane scroll = new ScrollPane(content);

    scale.translateYProperty().bind(Bindings.createDoubleBinding(() -> {
        double contentHeight = content.getHeight();
        double viewportHeight = scroll.getViewportBounds().getHeight();
        if (contentHeight <= viewportHeight) {
            return 0d;
        } else {
            return -scroll.getVvalue() * (contentHeight - viewportHeight);
        }
    }, scroll.viewportBoundsProperty(), scroll.vvalueProperty(), content.heightProperty()));

    HBox root = new HBox(scaleContainer, scroll);
    root.setPadding(new Insets(10));

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

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