【问题标题】:Manipulating the number of rows and columns in GridPane操作 GridPane 中的行数和列数
【发布时间】:2018-02-08 22:04:17
【问题描述】:

我在 MapTest 类中初始化了 rowSize(行数)和 colSize(列数)。我创建了 3 个方法:startStage1()、startStage2() 和 startStage3();每个都分配给一个按钮。每个方法都将 rowSize 和 colSize 分配给一个新整数。

我希望能够在单击按钮时重新调整 GridPane 的大小,但它不能以这种方式工作。 我可以做些什么不同的事情?

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

    }

}

【问题讨论】:

    标签: java javafx scene stage gridpane


    【解决方案1】:

    我对您的代码进行了一些更改并使其正常工作。

    首先Application#start 方法不应被系统以外的任何人调用。它是您应用的入口点,手动调用它会破坏应用的生命周期。

    其次,不需要在start 方法中创建GridMapT 实例,因为您不知道它运行时应该有多少列和行。这就是为什么这里也不需要将地图放入您的GridPane 的原因。

    第三,您需要创建新的GridMapT 实例或在需要更新地图时随时更改现有实例。因此,在您创建新地图或更新现有(添加或删除项目)后,您需要将其放入您的 GridPane。创建地图和更新网格的两段代码似乎都可以,但是它们在错误的时间和错误的位置被调用。

    最后int 类型是Java 中的原语。更改任何 int 值只会影响它,您仍然需要手动重新创建和/或更新任何依赖它的东西。这意味着每次更改时都需要使用新的 colSizerowSize 值手动创建/更新映射。如果您创建新地图,您需要手动将其传递给您的 GridPane 实例。

    一般而言,您的应用程序逻辑应如下所示:

    1. 创建舞台、场景、组件。
    2. 显示第一个场景
    3. 等待用户输入(点击、大小等)
    4. 更新第二个场景
    5. 显示第二个场景
    6. 等待用户输入(点击Quit
    7. 关闭第二个场景
    8. 根据用户的操作重复3-7

    这里还有一些事情可以做得更好,我希望你能找到并改进它们:)

    改进的代码:

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

    【讨论】:

    • 我现在明白了!您不知道我多么感谢您的完整回答和建议。谢谢!
    • @Neo 很高兴我的回答对您有所帮助!请考虑根据StackOverflow rules投票接受 :)
    猜你喜欢
    • 2015-06-19
    • 1970-01-01
    • 2014-01-13
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多