两个同步的 ScrollPanes 未对齐
Misalignment of two synced ScrollPanes
我尝试通过
对齐两个javafx.scene.control.ScrollPane的垂直滚动位置
sp1.vvalueProperty().bindBidirectional(sp2.vvalueProperty());
问题是其中一个 ScrollPanes 可能有水平滚动条。所以我越向下滚动 ScrollPanes,它们就越不对齐(见屏幕截图)。我该如何处理?
不可能用 2 ScrollPane
s 和等高的内容来做到这一点,除非你在两个 ScrollPane
s 中显示滚动条:
考虑内容完全符合左侧 ScrollPane
的 viewport
的情况。右边ScrollPane
的viewPort
可以滚动ScrollBar
高度。修改左边ScrollPane
是不行的
由于预期结果似乎是某种比例,您可以简单地使用 Pane
和应用 transformY
的 child 和剪辑。计算置顶像素的公式,使用
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();
}
我尝试通过
对齐两个javafx.scene.control.ScrollPane的垂直滚动位置sp1.vvalueProperty().bindBidirectional(sp2.vvalueProperty());
问题是其中一个 ScrollPanes 可能有水平滚动条。所以我越向下滚动 ScrollPanes,它们就越不对齐(见屏幕截图)。我该如何处理?
不可能用 2 ScrollPane
s 和等高的内容来做到这一点,除非你在两个 ScrollPane
s 中显示滚动条:
考虑内容完全符合左侧 ScrollPane
的 viewport
的情况。右边ScrollPane
的viewPort
可以滚动ScrollBar
高度。修改左边ScrollPane
是不行的
由于预期结果似乎是某种比例,您可以简单地使用 Pane
和应用 transformY
的 child 和剪辑。计算置顶像素的公式,使用
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();
}