JavaFX ScrollPane 在 VBox 中时不会改变宽度

JavaFX ScrollPane won't change width when in VBox

我的应用程序的主场景使用 VBox 布局并包含一个滚动窗格。尽管使用 setPrefViewportWidth 方法更改了值,但 VBox 布局中的滚动窗格不会在视觉上更改宽度:

VBox mainLayout = new VBox(50);
ScrollPane activityPane = new ScrollPane(new Label("TEST"));
activityPane.setPrefViewportWidth(100); //Width stays the same visually
activityPane.setPrefViewportHeight(50); //Height changes fine

如您所见,滚动窗格的宽度与 window 的宽度相当,比应有的宽度大得多。我该怎么做才能强制滚动窗格采用特定宽度?

默认情况下,大多数 JavaFX 元素都可以调整大小。

如果您不希望滚动窗格超出其首选大小,请告诉它不要那样做。

scrollPane.setMaxWidth(ScrollPane.USE_PREF_SIZE);

进一步解释,如果需要

请注意,这是对整个滚动窗格控件(包括边框和滚动条等装饰)的最大宽度设置约束,而不仅仅是滚动窗格内的视口。

JavaFX 布局实现将根据您设置的滚动窗格视口的首选大小计算并使用整个滚动窗格的首选大小。在计算首选尺寸时,ScrollPane 的默认布局还将包括额外的 space 用于渲染装饰。

通过将最大大小限制为首选大小,滚动窗格可以根据需要缩小,但绝不会超出首选大小。如果你想阻止它缩小,那么你也可以设置最小尺寸来使用首选尺寸。你也可以对高度做同样的事情,以防你把它放在 VBox 以外的布局窗格中。

默认情况下,VBox 仅在您告诉它可以这样做时才垂直调整子项的大小,例如by setting Vgrow priority: VBox.setVgrow(scrollPane, Priority.ALWAYS);(尝试未注释此行的示例以查看它所产生的差异)。但它总是会尝试水平调整元素大小以填充可用 space。这就是为什么在您的示例中您看到滚动窗格水平调整大小,而不是垂直调整大小。

如果您想要一个不会调整大小的精确宽度(例如,无论如何它始终是 200 像素宽),那么您可以执行以下操作:

scrollPane.setPrefWidth(200);
scrollPane.setMaxWidth(ScrollPane.USE_PREF_SIZE);
scrollPane.setMinWidth(ScrollPane.USE_PREF_SIZE);

身高也一样。

有关调整大小的信息适用于大多数 JavaFX 控件(按钮略有不同,因为默认情况下它们不会调整到超出首选大小的大小,除非您将最大宽度和高度设置为 Double.MAX_VALUE 之类的值);

可执行示例

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class RestrictedWidthScrollPaneDemo extends Application {
    @Override
    public void start(Stage stage) {
        ScrollPane scrollPane = new ScrollPane(new Label("TEST"));
        scrollPane.setPrefViewportWidth(100);
        scrollPane.setPrefViewportHeight(50);
        scrollPane.setMaxWidth(ScrollPane.USE_PREF_SIZE);

        VBox layout = new VBox(scrollPane);
//        VBox.setVgrow(scrollPane, Priority.ALWAYS);
        stage.setScene(new Scene(layout, 200, 100));
        stage.show();
    }

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