如何从 Main.java 文件中对齐 Java FX GridPane 中的矩形?

How to align my rectangles in Java FX GridPane from my Main.java file?

我正在尝试制作 java 数独游戏。我无法对齐我的数独输入矩形。由于输入板底部的按钮,它们被移开了。如何在我的 Main.java 中对齐像我的 expected.jpg 这样的矩形。我只想通过 Main.java 文件制作我的 ButtonsInput Rectangles。如果无法通过 Main.java 进行对齐,请告诉我。谢谢

expected.jpg:

what_i_get.jpg:

Main.java:

package application;

import java.util.*;
import javafx.scene.shape.Rectangle;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;

public class Main extends Application {
    int[][] original_map;
    StackPane[][] screen_buttons = new StackPane[10][10];

    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,600,700);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }

        GridPane root = new GridPane();
        root.setPadding(new Insets(10));
        root.setHgap(10);
        root.setVgap(10);
        Scene scene = new Scene(root, 700, 700);
        primaryStage.setScene(scene);

    // USING SUDOKU.java to build the Sudoku Game
        Sudoku map = new Sudoku();
    // STORING the sudoku game in the 2x2 array
        this.original_map = map.make_game();

        for (int y=0;y<9;y++) {
            for (int x=0;x<9;x++) {
                screen_buttons[y][x] = new StackPane();
                Rectangle rec = new Rectangle(30,30);
                rec.setFill(javafx.scene.paint.Color.WHITE);
                rec.setStyle("-fx-arc-height: 10; -fx-arc-width: 10;");
                Label label = new Label(Integer.toString(this.original_map[y][x]));
                screen_buttons[y][x].getChildren().addAll(rec, label);
                root.add(screen_buttons[y][x], x, y);
            }
        }

        Button[] function_buttons = new Button[4];
        String[] function_id = {"Hint", "Clear", "Pause", "Check"};
        int pos = 0;
        for (Button b : function_buttons) {
            if (function_id[pos] == "Hint") {
                b = new Button(function_id[pos]);
                root.add(b, 1, pos+10);
            } else if (function_id[pos] == "Clear"){
                b = new Button(function_id[pos]);
                root.add(b, 1, pos+10);
            } else if (function_id[pos] == "Pause"){
                b = new Button(function_id[pos]);
                root.add(b, 1, pos+10);
            } else {
                b = new Button(function_id[pos]);
                root.add(b, 6, 11);
            }
            b.setStyle("-fx-pref-width: 100px; -fx-pref-height: 50px;");
            pos++;
        }

        Button[] click_buttons = new Button[9];
        pos = 1;
        for (int y=10;y<=12;y++) {
            for (int x=2;x<=4;x++) {
                click_buttons[pos-1] = new Button(Integer.toString(pos));
                root.add(click_buttons[pos-1], x, y);
                click_buttons[pos-1].setStyle("-fx-pref-width: 50px; -fx-pref-height: 50px;");
                pos++;
            }
        }
    }

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

这里有几个问题(主要问题和次要问题)。

首先,screen_buttons 声明为 StackPane[10][10],稍后可能会给您带来问题。

其次,我不知道你为什么要创建两个根节点和两个场景。它会起作用,但完全没有必要。

第三,您的 GridPane 用作显示网格和控制按钮的公共根。下面的所有按钮都会影响顶部网格的列宽。您需要将这两者分开。您可以使用包含两个 GridPane 子节点的 BorderPane - 一个用于显示,另一个用于控制。

最后,执行 Label label = new Label(Integer.toString(this.original_map[y][x])) 将使您的网格显示 static 值。虽然这对于使用值预先生成的网格来说看起来不错,但当玩家在网格上放置数字时,这可能会成为一个问题。当然,您可以手动设置用户执行操作时相应网格的文本,但这会使此处保留2个数组变得多余。

更好地控制布局的一种常见策略是将其细分为更小、更易于管理的容器,每个容器都有自己的布局管理器。
在这种情况下,首先按照 :

的建议将游戏及其控件分成两个容器
public class Main extends Application {

    StackPane[][] screen_buttons = new StackPane[9][9];

    @Override
    public void start(Stage primaryStage) {

       //container for game
       BorderPane root = new BorderPane();

        GridPane grid = new GridPane();
        grid.setPadding(new Insets(10));
        grid.setHgap(10);
        grid.setVgap(10);

        for (int y=0;y<screen_buttons.length;y++) {
            for (int x=0;x<screen_buttons[y].length;x++) {
                screen_buttons[y][x] = new StackPane();
                Rectangle rec = new Rectangle(30,30);
                rec.setFill(javafx.scene.paint.Color.WHITE);
                rec.setStyle("-fx-arc-height: 10; -fx-arc-width: 10;");
                Label label = new Label("0");
                screen_buttons[y][x].getChildren().addAll(rec, label);
                grid.add(screen_buttons[y][x], x, y);
            }
        }

        //container for controls
        GridPane controls = new GridPane();

        Button[] function_buttons = new Button[4];
        String[] function_id = {"Hint", "Clear", "Pause", "Check"};
        int pos = 0;
        for (Button b : function_buttons) {
            if (function_id[pos] == "Hint") {
                b = new Button(function_id[pos]);
                controls.add(b, 1, pos+10);
            } else if (function_id[pos] == "Clear"){
                b = new Button(function_id[pos]);
                controls.add(b, 1, pos+10);
            } else if (function_id[pos] == "Pause"){
                b = new Button(function_id[pos]);
                controls.add(b, 1, pos+10);
            } else {
                b = new Button(function_id[pos]);
                controls.add(b, 6, 11);
            }
            b.setStyle("-fx-pref-width: 100px; -fx-pref-height: 50px;");
            pos++;
        }

        Button[] click_buttons = new Button[9];
        pos = 1;
        for (int y=10;y<=12;y++) {
            for (int x=2;x<=4;x++) {
                click_buttons[pos-1] = new Button(Integer.toString(pos));
                controls.add(click_buttons[pos-1], x, y);
                click_buttons[pos-1].setStyle("-fx-pref-width: 50px; -fx-pref-height: 50px;");
                pos++;
            }
        }

        root.setCenter(grid);
        root.setBottom(controls);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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