【问题标题】:Maintain Gridpane the same height and width (Aspect ratio)保持 Gridpane 相同的高度和宽度(纵横比)
【发布时间】:2021-06-23 22:14:28
【问题描述】:

我有一个 javafx GridPane,当我调整舞台大小时,它会调整自身大小以适应舞台的尺寸。我希望网格窗格的高度与网格窗格的宽度相匹配,从而将大小调整为保持此约束的最大可能大小。

我不得不在 GridPane 的父级中添加更多元素。我发现添加的元素根本没有正常行为,并且相互重叠。

当然,当我删除覆盖方法时,它们不再重叠,但是当我重新调整舞台大小时,网格窗格不会保持完美的正方形。

我想尝试在后台使用图像/图像视图并为其应用setPreserveRatio(true)。然后将此图像的 heightProperty 绑定到 gridPane 的 prefHeightProperty,但由于某种原因,这也没有给我任何结果。

这是第二种方法的 MCVE,它不起作用,但如果我能以某种方式使其工作,那就太好了。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        StackPane stackPane = new StackPane();

        Image image = new Image("Square Image.png", 300, 300, true, true);
        ImageView imageView = new ImageView(image);
        // This makes the image resize while maintaining its square shape...
        imageView.fitHeightProperty().bind(stackPane.heightProperty());
        imageView.fitWidthProperty().bind(stackPane.widthProperty());
        imageView.setPreserveRatio(true);

        GridPane gridPane = new GridPane();
        for(int i=0; i<5; i++) {
            for (int j = 0; j < 5; j++) {
                Pane pane = new Pane();
                pane.setPrefSize(100, 100);
                gridPane.add(pane, i, j);
            }
        }
        // Does not work as intended... :(
        gridPane.prefWidthProperty().bind(imageView.fitWidthProperty());
        gridPane.prefHeightProperty().bind(imageView.fitHeightProperty());
        
        /*
        Tried this as well, also does not work.. :(
        gridPane.prefWidthProperty().bind(image.widthProperty());
        gridPane.prefHeightProperty().bind(image.heightProperty());
        */


        gridPane.setGridLinesVisible(true);

        stackPane.getChildren().addAll(imageView, gridPane);
        primaryStage.setScene(new Scene(stackPane));
        primaryStage.show();
    }
  
    public static void main(String[] args) {
        launch(args);
    }
}

当然,所有这些方法都是试图完成这项工作的廉价的 hacky 方法。如果有一种我不知道的标准方法,那么我想知道。

【问题讨论】:

  • 所以您想让您的GridPane 始终保持完美的 1:1 方形?如果我理解正确,只需将其宽度绑定到其高度:gridPane.prefWidthProperty().bind(gridPane.prefHeightProperty());
  • @zephyr 您没有像 GridPane 中的 widthProperty() 这样的只读方式可用的 bind() 方法。 bind() 只能应用于 prefWidthProperty()。并且做 prefWidthProperty().bind(prefHeightProperty()) 也不起作用,刚刚检查过。
  • 是的,我更新了我的评论。这将处理GridPane,但如果您希望每个方块也保持它们的比率,则需要计算出类似的东西。
  • 我尝试做gridPane.prefWidthProperty().bind(gridPane.prefHeightProperty());,但它不起作用。我认为因为它只是设置 prefWidth 而不是实际宽度,javafx 只是忽略了这个声明,因为它不可能满足这样的需求
  • 我想我不确定你当时想要完成什么。您想要一个完全可扩展的盒子网格,既能保持比例,又能随着舞台不断扩大或缩小?

标签: java javafx aspect-ratio


【解决方案1】:

GridPane 封装在StackPane 中,并使用绑定动态更改GridPane 孩子的首选大小,同时保持纵横比:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.*;
import javafx.stage.Stage;

    public class Main extends Application {

        private final int SIZE = 5;

        @Override
        public void start(Stage primaryStage) {

            GridPane gridPane = new GridPane();
            gridPane.setAlignment(Pos.CENTER);

            StackPane centerPane = new StackPane(gridPane);
            centerPane.setStyle("-fx-background-color:cyan");
            centerPane.setPrefSize(SIZE*50, SIZE*50);

            for(int i=0; i<SIZE; i++) {
                for (int j = 0; j < SIZE; j++) {
                    Pane pane = new Pane();
                    pane.setStyle("-fx-background-color:red");
                    gridPane.add(pane, i, j);
                    pane.prefWidthProperty().bind(Bindings.min(centerPane.widthProperty().divide(SIZE),
                                                                centerPane.heightProperty().divide(SIZE)));
                    pane.prefHeightProperty().bind(Bindings.min(centerPane.widthProperty().divide(SIZE),
                                                                centerPane.heightProperty().divide(SIZE)));
                }
            }
            gridPane.setGridLinesVisible(true);

            primaryStage.setScene(new Scene(centerPane));
            primaryStage.show();
        }

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

【讨论】:

  • 问题是这迫使GridPane 的单元格保持1:1 的比例,因此GridPane 似乎也保持相同的比例。但实际上,GridPane 仍在扩展舞台的全尺寸,而将其单元格留在后面。如果您为网格窗格设置背景,则很容易注意到这一点
  • 有什么要求?保留GripPane 正方形或其内容?您可以将绑定应用于Gridpane 而不是其内容。这将使内容保持其首选大小。
猜你喜欢
  • 2014-07-01
  • 2018-04-29
  • 1970-01-01
  • 2011-04-14
  • 2015-01-21
  • 2021-02-09
  • 2018-06-21
  • 2014-04-17
  • 2012-06-02
相关资源
最近更新 更多