Neo
Neo

Reputation: 53

Manipulating the number of rows and columns in GridPane

I initialized rowSize (number of rows) and colSize (number of columns) inside the MapTest class. I created 3 methods: startStage1(), startStage2() and startStage3(); each is assigned to a button. Each method assigns the rowSize and colSize to a new integer.

I want to be able to the re-size of my GridPane whenever I click a button but it does not works that way. What could I have done differently?

import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MapTest extends Application implements EventHandler<KeyEvent> {

    static Stage theStage;
    static Scene scene1, scene2;

    // top box
    HBox topBox = new HBox();

    // bottom box
    HBox bottomBox = new HBox();

    // grid dimensions (I'm trying to manipulate these variables)
    int rowSize;
    int colSize;
    int tileSize;

    GridPane gridPane;
    GridMapT gridMap;

    @Override
    public void start(Stage firstStage) throws Exception {
        theStage = firstStage;

        // scene 2 //////////////
        Label label2 = new Label("scene 2: choose a stage");
        Button stage1_btn = new Button("Room 5x5");
        Button stage2_btn = new Button("Room 7x7");
        Button stage3_btn = new Button("Room 10x10");
        Button button5 = new Button("Exit");

        stage1_btn.setOnAction(e -> {
            startStage1();
        });
        stage2_btn.setOnAction(e -> {
            startStage2();
        });
        stage3_btn.setOnAction(e -> {
            startStage3();
        });
        button5.setOnAction(e -> System.exit(0));

        // Layout1
        VBox layout = new VBox(20);
        layout.setAlignment(Pos.CENTER);
        layout.getChildren().addAll(label2, stage1_btn, stage2_btn, stage3_btn, button5);
        scene1 = new Scene(layout, 800, 600);

        // Scene 3 ////////////////////
        // top box
        Label title = new Label("Map test");

        topBox.getChildren().add(title);

        // bottom box
        Label instruction = new Label("");

        bottomBox.getChildren().add(instruction);

        // scene 3
        BorderPane gameScreen = new BorderPane();

        scene2 = new Scene(gameScreen);

        // set up gridPane
        gridPane = new GridPane();
        gridMap = new GridMapT(rowSize, colSize);

        for (int x = 0; x < rowSize; x++) {
            for (int y = 0; y < colSize; y++) {

                String grid = gridMap.getMap()[x][y];

                // floor labels
                if (grid == "floor") {
                    Label table = new Label("F");
                    table.setMinWidth(tileSize);
                    table.setMinHeight(tileSize);
                    gridPane.add(table, x, y);
                }

                // wall labels
                if (grid == "wall") {
                    Label table = new Label("W");
                    table.setMinWidth(tileSize);
                    table.setMinHeight(tileSize);
                    gridPane.add(table, x, y);

                }

            }

        }

        ////// ////////////////////////////////////////////////////////////////////////
        // add a clickable reset and Debug Mode to bottom box

        Button resetBtn = new Button();
        resetBtn.setText("Quit game");

        bottomBox.getChildren().add(resetBtn);

        resetBtn.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<Event>() {
            @Override
            public void handle(Event event) {
                try {

                    restart(firstStage);
                } catch (Exception e) {

                    e.printStackTrace();
                }

            }
        });

        // keyboard input
        scene2.setOnKeyPressed(this);

        // setting up the whole borderPane
        gameScreen.setTop(topBox);
        gameScreen.setBottom(bottomBox);
        gameScreen.setCenter(gridPane);

        // set scene1 as start up screen
        firstStage.setScene(scene1);
        firstStage.show();

    }

    // restart method
    public void restart(Stage stage) throws Exception {

        topBox.getChildren().clear();
        bottomBox.getChildren().clear();
        gridPane.getChildren().clear();
        gridMap = new GridMapT(rowSize, colSize);

        start(stage);
    }

    ///////////////////////////////////////////////////////////////////////////////////////
    // stage setting methods
    public void startStage1() {
        rowSize = 21;
        colSize = 21;
        tileSize = 40;

        theStage.setScene(scene2);
    }

    public void startStage2() {
        rowSize = 29;
        colSize = 29;
        tileSize = 30;

        theStage.setScene(scene2);

    }

    public void startStage3() {
        rowSize = 41;
        colSize = 41;
        tileSize = 20;

        theStage.setScene(scene2);
    }

    @Override
    public void handle(KeyEvent event) {
        // TODO Auto-generated method stub

    }

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

    /////////////////////////////////////////////////////////////////////////////////////////////////
    // GridMap Class

    public class GridMapT {

        private String[][] map;

        public GridMapT(int rowSize, int colSize) {

            this.map = new String[rowSize][colSize];

            // set up wall and fog
            for (int i = 0; i < rowSize; i++) {
                for (int j = 0; j < colSize; j++) {

                    if (i % 4 == 0 || j % 4 == 0) {
                        map[i][j] = "wall";
                    } else {
                        map[i][j] = "floor";
                    }

                }
            }

        }

        public String[][] getMap() {
            return map;
        }

    }

}

Upvotes: 0

Views: 3357

Answers (1)

I made a couple of changes to your code and made it work.

Firstly Application#start method should not be called by anybody but system. It is your app's entry point and calling it manually breaks app's lifecycle.

Secondly there's no need to create GridMapT instance in start method just because you don't know by the time it runs how many columns and rows there should be. And that's why there's no need to put map into your GridPane here too.

Thirdly you need to create new GridMapT instance or change existing any time you need to update your map. So after you created new map or updated existing (added or removed items) you need to put it into your GridPane. Both pieces of code that creates map and updates grid seems to be ok, but they are called at the wrong time and in the wrong place.

Lastly int type is a primitive in Java. Changing any int value affects only it and you still need to recreate and/or update anything that depends on it manually. This means that you need manually create/update map with new colSize and rowSize values each time you change them. If you create new map you need manually pass it to your GridPane instance.

In general your app's logic should look like that:

  1. Create stage, scenes, components.
  2. Show first scene
  3. Wait for user's input (click, size, etc.)
  4. Update second scene
  5. Show second scene
  6. Wait for user's input (click Quit)
  7. Close second scene
  8. Repeat 3-7 according to user's actions

There are still a couple of things that can be done better here and I wish you luck to find and improve them :)

Improved code:

public class Test extends Application implements EventHandler<KeyEvent>{
    static Stage theStage;
    static Scene scene1, scene2;

    // top box
    HBox topBox = new HBox();

    // bottom box
    HBox bottomBox = new HBox();

    // grid dimensions (I'm trying to manipulate these variables)
    int rowSize;
    int colSize;
    int tileSize;

    GridPane gridPane;
    GridMapT gridMap;

    @Override
    public void start(Stage firstStage) throws Exception{
        theStage = firstStage;

        // scene 2 //////////////
        Label label2 = new Label("scene 2: choose a stage");
        Button stage1_btn = new Button("Room 5x5");
        Button stage2_btn = new Button("Room 7x7");
        Button stage3_btn = new Button("Room 10x10");
        Button button5 = new Button("Exit");

        stage1_btn.setOnAction(e -> {
            startStage1();
        });
        stage2_btn.setOnAction(e -> {
            startStage2();
        });
        stage3_btn.setOnAction(e -> {
            startStage3();
        });
        button5.setOnAction(e -> System.exit(0));

        // Layout1
        VBox layout = new VBox(20);
        layout.setAlignment(Pos.CENTER);
        layout.getChildren().addAll(label2, stage1_btn, stage2_btn, stage3_btn, button5);
        scene1 = new Scene(layout, 800, 600);

        // Scene 3 ////////////////////
        // top box
        Label title = new Label("Map test");

        topBox.getChildren().add(title);

        // bottom box
        Label instruction = new Label("");

        bottomBox.getChildren().add(instruction);

        // scene 3
        BorderPane gameScreen = new BorderPane();

        scene2 = new Scene(gameScreen);

        // set up gridPane
        gridPane = new GridPane();

        ////// ////////////////////////////////////////////////////////////////////////
        // add a clickable reset and Debug Mode to bottom box

        Button resetBtn = new Button();
        resetBtn.setText("Quit game");

        bottomBox.getChildren().add(resetBtn);

        resetBtn.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<Event>(){
            @Override
            public void handle(Event event){
                try {
                    //There's no need to call start method anymore.
                    //Think of the stage like it's your app's window
                    //and of a scene like it is window's content.
                    //restart(firstStage);
                    firstStage.setScene(scene1);
                } catch (Exception e) {

                    e.printStackTrace();
                }

            }
        });

        // keyboard input
        scene2.setOnKeyPressed(this);

        // setting up the whole borderPane
        gameScreen.setTop(topBox);
        gameScreen.setBottom(bottomBox);
        gameScreen.setCenter(gridPane);

        // set scene1 as start up screen
        firstStage.setScene(scene1);
        firstStage.show();

    }

    //TODO pass rowSize and colSize here
    private void createMap(){
        gridMap = new GridMapT(rowSize, colSize);
    }

    //TODO pass gridMap
    private void redrawMap(){
        gridPane.getChildren().clear();

        for (int x = 0; x < rowSize; x++) {
            for (int y = 0; y < colSize; y++) {
                String grid = gridMap.getMap()[x][y];

                // floor labels
                if (grid == "floor") {
                    Label table = new Label("F");
                    table.setMinWidth(tileSize);
                    table.setMinHeight(tileSize);
                    gridPane.add(table, x, y);
                }

                // wall labels
                if (grid == "wall") {
                    Label table = new Label("W");
                    table.setMinWidth(tileSize);
                    table.setMinHeight(tileSize);
                    gridPane.add(table, x, y);
                }
            }
        }
    }

    // restart method
    public void restart(Stage stage) throws Exception{

        topBox.getChildren().clear();
        bottomBox.getChildren().clear();
        gridPane.getChildren().clear();
        gridMap = new GridMapT(rowSize, colSize);

        start(stage);
    }

    ///////////////////////////////////////////////////////////////////////////////////////
    // stage setting methods
    public void startStage1(){
        rowSize = 21;
        colSize = 21;
        tileSize = 40;

        createMap();
        redrawMap();
        theStage.setScene(scene2);
    }

    public void startStage2(){
        rowSize = 29;
        colSize = 29;
        tileSize = 30;

        createMap();
        redrawMap();
        theStage.setScene(scene2);
    }

    public void startStage3(){
        rowSize = 41;
        colSize = 41;
        tileSize = 20;

        createMap();
        redrawMap();
        theStage.setScene(scene2);
    }

    @Override
    public void handle(KeyEvent event){
        // TODO Auto-generated method stub

    }

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

    /////////////////////////////////////////////////////////////////////////////////////////////////
    // GridMap Class

    public class GridMapT{

        private String[][] map;

        public GridMapT(int rowSize, int colSize){

            this.map = new String[rowSize][colSize];

            // set up wall and fog
            for (int i = 0; i < rowSize; i++) {
                for (int j = 0; j < colSize; j++) {

                    if (i % 4 == 0 || j % 4 == 0) {
                        map[i][j] = "wall";
                    } else {
                        map[i][j] = "floor";
                    }

                }
            }

        }

        public String[][] getMap(){
            return map;
        }

    }
}

Upvotes: 1

Related Questions