滚动面板未按需显示,流式面板内容。

7
我在JavaFX 8中使用ScrollPane时遇到了一些困难,即无法按需显示滚动条。我目前所做的是创建一个包含x个元素的FlowPane,并将其设置为ScrollPane的内容。
问题出现在与FlowPane方向垂直的方向上缩小时。当元素开始换行并超出边界时,滚动条不会出现。但是在与方向平行的情况下缩小时,这种情况不会发生。我有一个小的Java程序来说明这个问题。 起始 平行缩小 垂直缩小 垂直缩小夸张版 平行缩小夸张版
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

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

       @Override
       public void start(Stage primaryStage) throws Exception {
             FlowPane flow = new FlowPane();
             flow.setStyle("-fx-border-color: red");
             addPanes(flow, 16);

             ScrollPane scroll = new ScrollPane(flow);
             scroll.setStyle("-fx-border-color: green");
             scroll.setFitToHeight(true);
             scroll.setFitToWidth(true);

             Scene scene = new Scene(scroll, 450, 450);
             primaryStage.setScene(scene);
             primaryStage.show();
       }

       public void addPanes(FlowPane root, int panes) {
             for(int i = 0; i < panes; i++) {
                    StackPane filler = new StackPane();
                    filler.setStyle("-fx-border-color: black");
                    filler.setPrefSize(100, 100);
                    root.getChildren().add(filler);
             }
       }
}

有趣的是,当Stage的宽度小于FlowPane的初始宽度时,它可以正确地工作。在Scene的宽度上使用400。 - SedJ601
1
这确实是一些奇怪的行为。不幸的是,即使您将其初始化为400x400,如果您将其扩展到约450x450并垂直缩小,它仍然会出现问题。 - Mekiah
3个回答

2

请看下面的代码,告诉我这是否是您想要实现的内容。我仍然不确定问题的原因,我将查看ScrollPane的文档以找出答案。我的猜测在于setFitToWidthsetFitToHeight方法。尽管我仍然认为这不是一个错误。

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        FlowPane flow = new FlowPane();
        flow.setStyle("-fx-border-color: red");

        addPanes(flow, 16);

        ScrollPane scroll = new ScrollPane(flow);
        scroll.setStyle("-fx-border-color: green");

        // Apparently this cause the issue here.
        // scroll.setFitToHeight(true);
        // scroll.setFitToWidth(true);


        // Instead just make the flow pane take the dimensions of the ScrollPane
        // the -5 is to not show the Bars when both of panes have the same dimensions  
        flow.prefWidthProperty().bind(Bindings.add(-5, scroll.widthProperty()));
        flow.prefHeightProperty().bind(Bindings.add(-5, scroll.heightProperty()));

        Scene scene = new Scene(scroll, 450, 450);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public void addPanes(FlowPane root, int panes) {
        for (int i = 0; i < panes; i++) {
            HBox filler = new HBox();
            filler.setStyle("-fx-border-color: black");
            filler.setPrefSize(100, 100);
            root.getChildren().add(filler);
        }
    }
}

浏览ScrollPane的文档,特别是setFitToHeight属性,您会发现:
属性描述: 如果为true,并且包含的节点可调整大小,则节点将保持调整大小以匹配ScrollPane视口的高度。如果包含的节点不可调整大小,则忽略此值。
因为ScrollPane内部的节点将保持调整大小以匹配ScrollPane视口的宽度和高度,所以垂直滚动条永远不会出现。

问题是我不想为面板设置最大尺寸。我希望用户能够调整窗口大小,流式面板将自由地根据需要移动元素到任何大小,但当缩小得太小时,我希望出现滚动条,但在这种特定情况下并没有发生。 - Mekiah
当缩小至太小时,我希望出现滚动条。您能更具体一些吗?指多小?在这种情况下,只需设置setMinWidth()即可。例如,如果要在用户将窗格缩小超过250时显示水平条,则设置flow.setMinWidth(250);即可。这不会影响最大尺寸,但会防止用户尝试将窗格宽度缩小超过250。 - JKostikiadis
关于您的初始解决方案,它强制窗格始终为4列宽。第二个解决方案仍然存在原来的问题。如果可以帮助您理解,我可以附上截图夸大了初始截图所要呈现的内容。这些已经编辑到问题中。如您所见,当您向缩小屏幕截图的方向缩小时,垂直滚动条不会显示。该应用程序具有创建1x16或16x1盒子的窗口的功能,如果按此方式展开,则希望保留该功能,而不是采取其他解决方法否则会删除该功能。 - Mekiah
我认为新的解决方案是最好的权宜之计。但你必须承认滚动条外观行为的方式是不正确的,对吧?当内容的宽度/高度大于ScrollPane时,滚动条应该显示。我在内存中检查了两个对象,在两种调整大小的情况下都成立。明显是个bug,但感谢提供的解决方法。这个特定的解决方法唯一的问题是你会在内容窗格上得到填充,但这不应影响我的计划。谢谢。 - Mekiah
@Mekiah 不是错的。实际上这就是ScrollBar表现出你所看到的方式的原因。通过设置setFitToWidth(true)(或高度),节点将被保持调整大小以匹配ScrollPane视口的宽度,这就是为什么滚动条永远不会出现的原因。 - JKostikiadis
显示剩余2条评论

2
您可以添加以下代码来始终显示您的垂直滚动条。
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);

1
我很感谢你的努力,但如果我找不到真正的解决方案,或者它被证明是JavaFX的一个错误,我已经有这个想法了。 - Mekiah
1
我猜这是一个 bug。 - SedJ601

0

当计算ScrollPane中FlowPane所需的高度时,传递了-1的宽度值。当所有内容都适合单行时,流面板将报告所需的高度。

作为解决方法,在这种情况下,您可以从上次布局计算中传递宽度。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

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

       @Override
       public void start(Stage primaryStage) throws Exception {
             FlowPane flow = new FlowPane() {
                @Override protected double computeMinHeight(double width) {
                    double minHeight = super.computeMinHeight(width != -1 ? width : 
                        /* When no width is specified, use the current contol size*/ 
                        getWidth());
                    return minHeight;
                }
             };
             flow.setStyle("-fx-border-color: red");
             addPanes(flow, 16);

             ScrollPane scroll = new ScrollPane(flow);
             flow.maxWidthProperty().bind(scroll.widthProperty());
             scroll.widthProperty().addListener((observable, oldValue, newValue)->{
                 /* clearSizeCache */
                 flow.requestLayout();
             });

             scroll.setStyle("-fx-border-color: green");
             scroll.setFitToHeight(true);
             scroll.setFitToWidth(true);

             Scene scene = new Scene(scroll, 450, 450);
             primaryStage.setScene(scene);
             primaryStage.show();
       }

       public void addPanes(FlowPane root, int panes) {
             for(int i = 0; i < panes; i++) {
                    StackPane filler = new StackPane();
                    filler.setStyle("-fx-border-color: black");
                    filler.setPrefSize(100, 100);
                    root.getChildren().add(filler);
             }
       }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接