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

折月煮酒 提交于 2019-12-11 22:27:38

问题


I'm trying to make a java Sudoku Game. I cannot align my Sudoku input rectangles. They are being shifted away because of the buttons at the bottom of the input board. How can I align the rectangles like my expected.jpg in my Main.java. I want to make my Buttons and Input Rectangles through the Main.java file only. If it is not possible to make the alignment though Main.java, please let me know. Thanks

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

回答1:


A common strategy to gain better control over layout, is to sub-divide it into smaller, simpler to manage containers, each having its own layout manager.
In this case, start by separating the game and it's controls into two containers as proposed by Jai :

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




回答2:


There are several problems (major and minor ones) here.

Firstly, screen_buttons is declared as StackPane[10][10], which can potentially give you problem later.

Secondly, I have no idea why you created two root nodes and two scenes. It would work, but totally unnecessary.

Thirdly, your GridPane is used as the common root for the display grid and the control buttons. All the buttons below is affecting the column widths at the grid on top. You need to separate these two. You could use a BorderPane containing two GridPane child nodes - one for the display and another for control.

Lastly, doing Label label = new Label(Integer.toString(this.original_map[y][x])) is going to make your grid display static values. While this looks great for grids pre-generated with values, this can be a problem when the player places a number on the grid. Of course, you could manually set the text of the corresponding grid when the user does an action, but this would make it redundant to keep 2 arrays here.



来源:https://stackoverflow.com/questions/52845315/how-to-align-my-rectangles-in-java-fx-gridpane-from-my-main-java-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!