保持Gridpane的高度和宽度相同(保持纵横比)

4

我有一个JavaFX的GridPane,它会根据舞台的尺寸自动调整大小。我想让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
@zephyr,你在GridPane的只读属性widthProperty()上没有可用的bind()方法。bind()只能应用于prefWidthProperty()。而且,执行prefWidthProperty().bind(prefHeightProperty())也不起作用,我刚刚检查过了。 - user15491771
是的,我更新了我的评论。这将处理GridPane,但如果您希望每个正方形保持其比例,您需要想出类似的解决方案。 - Zephyr
是的,正是我想要的,并且它们应该保持1:1的比例。 - user15491771
一旦您将GridPane锁定到随着Stage调整大小的AnchorPane中,现在您需要处理舞台本身不按1:1比例调整大小的情况。这个问题/答案可以帮助解决这个问题。 - Zephyr
显示剩余3条评论
1个回答

3

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);
        }
    }

enter image description here


问题在于这会强制GridPane的单元格保持1:1的比例,因此看起来GridPane也在保持相同的比例。但实际上,GridPane仍然扩展到舞台的全尺寸,而其单元格则被留在后面。如果为网格面板设置背景,则可以轻松地注意到这一点。 - user15491771
什么是要求?保持GripPane正方形还是其内容?您可以将绑定应用于Gridpane而不是其内容。这将导致内容保持其首选大小。 - c0der

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