提问者:小点点

javaFX在按钮坐标上显示正确的值


我已经把问题简化为问题,所以我正在为扫雷游戏做一个UI,在下面的控制器中,在StartGame方法中,事情很好(根据我使用调试的检查),直到

game.open(x, y)

,这意味着我设法创建板并将按钮(将充当插槽)添加到GridPane,但我的问题是我似乎无法打开并在插槽上显示正确的值。(Mines类的逻辑工作正常-没有javaFX部分的逻辑)。

package MS;

import java.io.IOException;
import java.util.Random;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBase;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class NewGameCONTROLLER {
    Mines game;
    int rows, columns, mines;
    Button b;

    @FXML
    private TextField NumRows;

    @FXML
    private TextField NumCols;

    @FXML
    private TextField NumM;

    @FXML
    private Button StartGame;

    @FXML
    private Button BackMainMenu;

    @FXML
    private Button RandomGame;

    @FXML
    void BackMainMenu(ActionEvent event) throws IOException {
        FXMLLoader loader = new FXMLLoader(); // Create loading object
        loader.setLocation(getClass().getResource("MainMenuFXML.fxml")); // fxml location
        VBox root = loader.load(); // Load layout
        root.setStyle("-fx-background-image: url(\"file:///C:/EclipseProjects/MineSweeper/src/MS/menu.jpg\")");
        Scene scene = new Scene(root); // Create scene with chosen layout
        Stage primaryStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        primaryStage.setTitle("..."); // Set stage's title
        primaryStage.setMinWidth(400); // Won't be allowed to make width/height smaller
        primaryStage.setMinHeight(350);
        primaryStage.setMaxWidth(600);
        primaryStage.setMaxHeight(450);
        primaryStage.setScene(scene); // Set scene to stage
        primaryStage.show(); // Show stage
    }

    @FXML
    void RandomGame(ActionEvent event) {
        Random rand = new Random();
        int low = 3, high = 15;
        int minesLow = 1, minesHigh;
        rows = rand.nextInt(high - low) + low;
        columns = rand.nextInt(high - low) + low;
        minesHigh = rows * columns - 1;
        mines = rand.nextInt(minesHigh - minesLow) + minesLow;
        game = new Mines(rows, columns, mines);
    }

    @FXML
    void StartGame(ActionEvent event) throws IOException {
        rows = Integer.parseInt(NumRows.getText());
        columns = Integer.parseInt(NumCols.getText());
        mines = Integer.parseInt(NumM.getText());
        game = new Mines(rows, columns, mines);

        FXMLLoader loader = new FXMLLoader(); // Create loading object
        loader.setLocation(getClass().getResource("BoardFXML.fxml")); // fxml location

        AnchorPane root = loader.load(); // Load layout
        root.setStyle("-fx-background-image: url(\"file:///C:/EclipseProjects/MineSweeper/src/MS/Pic.jpg\")");
        Scene scene = new Scene(root); // Create scene with chosen layout
        Stage gameStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        gameStage.setTitle("..."); // Set stage's title
        gameStage.setMinWidth(1000); // Won't be allowed to make width/height smaller
        gameStage.setMinHeight(500);
        gameStage.setMaxWidth(1200);
        gameStage.setMaxHeight(800);
        gameStage.setScene(scene); // Set scene to stage

        BoardCONTROLLER bCont = loader.getController(); // Prepare board in BoardCONTROLLER
        for (int i = 0; i < columns; i++)
            for (int j = 0; j < rows; j++) {
                b = new Button(" ");
                b.setMinSize(40, 40);
                b.setMaxSize(40, 40);
                bCont.TheBoard.add(b, i, j);
            }
        for (int i = 0; i < bCont.TheBoard.getChildren().size(); i++) {
            ((ButtonBase) bCont.TheBoard.getChildren().get(i)).setOnAction(new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent event) {
                    int x, y;
                    event.getSource();
                    x = (int) ((Button) event.getSource()).getProperties().get("gridpane-column");
                    y = (int) ((Button) event.getSource()).getProperties().get("gridpane-row");
                    game.open(x, y);
                    for (int i=0;i<game.getCol();i++)
                        for (int j=0;i<game.getRow();j++) {
                            if (game.board[i][j].charAt(1)=='T')
                                ((Button) bCont.TheBoard.getChildren().get(i)).setText(game.get(x, y));
                        }
                /*  while ()
                    for (int i = 0; i < bCont.TheBoard.getChildren().size(); i++) {
                        if (game.board[x][y].charAt(2) == 'B') {
                            ((Button) bCont.TheBoard.getChildren().get(i)).setText(game.get(x, y));
                        }
                    }*/
                }
            });
        }
        gameStage.show(); // Show stage
    }

}

谢谢你。


共1个答案

匿名用户

当我看到这个循环时。

for (int i=0;i<game.getCol();i++)
    for (int j=0;i<game.getRow();j++) {
        if (game.board[i][j].charAt(1)=='T')
            ((Button) bCont.TheBoard.getChildren().get(i)).setText(game.get(x, y));
    }    
}

变量i不对应行坐标,它对应于板中的第n个子节点。所以实际上,您只是循环遍历第一行(或第一列)中的所有子节点。

在路上我可以看到修复;

for( Node child: bCont.TheBoard.getChildren() ){
    int i = (int) ((Button) child).getProperties().get("gridpane-column");
    int j = (int) ((Button) child).getProperties().get("gridpane-row");
    if (game.board[i][j].charAt(1)=='T'){
        ((Button) child).setText(game.get(x, y));
    }
}

这样你就可以检查所有的孩子,并在黑板上检查他们的状态。

我不知道GridPane中子节点的顺序是否与布局顺序相对应,布局顺序是将2D数组打包为1D数组的常见技术,

bCont.TheBoard.getChildren().get(i + j*game.getCol());

请记住,您有x行总按钮。