Search code examples
javajavafxfxml

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


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:

enter image description here

what_i_get.jpg:

enter image description here

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

Solution

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

    enter image description here