在 JavaFX 中,如何将 ScrollPane 的内容保留在视口边框内?

Mic*_*ims 5 javafx scrollpane

我意识到我不可能是第一个希望将 ScrollPane 的内容保留在 ScrollPanes 视口边界内的人,但经过几个小时的搜索,我找不到问题的答案。

我用各种搜索词搜索了 Google、you.com 和 duckduckgo,例如

  • JavaFX ScrollPane 视口将内容限制在内部边框内
  • JavaFX ScrollPane 视口将内容保留在视口边框内

以及其他措辞的变化,我还没有找到答案。

我创建了基本的可重现代码,可以准确地对我在实际程序中呈现的数据进行建模。其实很简单:

  • 我有多个 VBox,每个 VBox 都有三个标签和一个分隔符。
  • 每个 VBox 都会添加到父 VBox。
  • 该父 VBox 被添加到 ScrollPane 中。
  • ScrollPane 删除了滚动条,并添加了一些浅色样式。

问题:滚动时,ScrollPane 的内容与 ScrollPane 视口的边框重叠,并且我无法弄清楚如何告诉 ScrollPane 将视口的内容保留在其边框内。

如果有另一种方法可以使可滚动内容保留在视口的边界内,我不知道这一点,并且希望为此提供任何指导。

我的假设是,视口的实际边框显然可以根据其宽度和颜色等进行定义,但它恰好是在与视口的实际内容相同的空间内“绘制”的。因此,不应假设边界是任何类型的预期边界,内容将通过该边界进行绑定......如果这是真的,我当然接受这一点,但这并不能帮助我实现该行为我追求的是,​​这是为了确保内容不会显示在视口边框上。

在这里,你可以看到我在说什么

在此输入图像描述

下面是显示该行为的代码:

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Separator;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.util.Random;

public class Main extends Application {

    @Override public void start(Stage stage) throws Exception {
        random = new Random(System.currentTimeMillis());
        makeScrollPane();
        Scene scene = new Scene(scrollPane);
        stage.initStyle(StageStyle.TRANSPARENT);
        stage.setScene(scene);
        stage.centerOnScreen();
        stage.setWidth(width);
        stage.setHeight(height);
        stage.show();

    }
    private       Random     random;
    private final double     width       = 300;
    private final double     height      = 500;
    private       ScrollPane scrollPane;
    private final String     scrollStyle = Main.class.getResource("scrollpane.css").toExternalForm();
    private final String     labelStyle  = Main.class.getResource("label.css").toExternalForm();

    private void makeScrollPane() {
        VBox[] contentArray = new VBox[15];
        for (int x = 0; x < 15; x++) {
            String boxIndex = String.valueOf(random());
            String boxNum = String.valueOf(random());
            String lbl1   = "Title " + boxIndex;
            String lbl2   = "Item " + boxIndex;
            contentArray[x] = getVBox(lbl1, lbl2, boxNum);
        }
        VBox vBoxContent = new VBox(contentArray);
        scrollPane = new ScrollPane(vBoxContent);
        scrollPane.fitToWidthProperty().set(true);
        scrollPane.fitToHeightProperty().set(true);
        scrollPane.getStylesheets().add(scrollStyle);
        scrollPane.hbarPolicyProperty().set(ScrollPane.ScrollBarPolicy.NEVER);
        scrollPane.vbarPolicyProperty().set(ScrollPane.ScrollBarPolicy.NEVER);
    }

    private VBox getVBox(String label1, String label2, String label3) {
        Label lbl1 = newLabel(label1);
        Label lbl2 = newLabel(label2);
        Label lbl3 = newLabel(label3);
        lbl3.setId("big");
        Separator separator = new Separator();
        separator.setMaxWidth(250);
        separator.setHalignment(HPos.CENTER);
        separator.setPadding(new Insets(0, 0, 25, 0));
        VBox vBox = new VBox(20, lbl1, lbl2, lbl3, separator);
        vBox.setPrefWidth(width * .9);
        vBox.setPrefHeight(100);
        vBox.setAlignment(Pos.CENTER);
        return vBox;
    }

    private int random() {
        return random.nextInt(1000, 9999);
    }

    private Label newLabel(String content) {
        Label label = new Label(content);
        label.getStylesheets().add(labelStyle);
        label.setPrefWidth(width * .9);
        label.setPrefHeight(25);
        label.setAlignment(Pos.CENTER);
        return label;
    }
};
Run Code Online (Sandbox Code Playgroud)

以及与之配套的两个样式表:

标签.css

.label {
    -fx-font-size: 13pt;
    -fx-background-color: transparent;
    -fx-font-family: "Arial";
    -fx-text-fill: ghostwhite;
}

#big {
    -fx-font-size: 40;
    -fx-text-fill: yellow;
}
Run Code Online (Sandbox Code Playgroud)

滚动窗格.css

.scroll-pane .viewport {
    -fx-background-color: black;
    -fx-border-color: darkorange;
    -fx-border-width: .7em;
}

.root {
    -fx-background-color: black;
}
Run Code Online (Sandbox Code Playgroud)

我很感谢任何指导我找到实现我在这里追求的目标的方法。

谢谢

Mic*_*ims 3

这种情况下的解决方案(我想这在技术上是一种解决方法)是仅使用边框设置 ScrollPane 本身的样式,并按照 James_D 的建议将视口保留为黑色背景。

只需更改scrollpane.css即可解决问题:

.scroll-pane {
    -fx-background-color: black;
    -fx-border-color: darkorange;
    -fx-border-width: .7em;
}

.scroll-pane .viewport {
    -fx-background-color: black;
}

.root {
    -fx-background-color: black;
}
Run Code Online (Sandbox Code Playgroud)