【问题标题】:javaFX show correct value on button coordinatesjavaFX在按钮坐标上显示正确的值
【发布时间】:2020-09-16 15:48:19
【问题描述】:

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

game.open(x,y)

,这意味着我设法创建板并将按钮(将充当插槽)添加到 GridPane,但我的问题是我似乎无法打开并在插槽上显示正确的值。 (地雷类的逻辑工作正常 - 没有 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
    }

}

谢谢。

【问题讨论】:

  • @matt 完成,希望现在更容易理解
  • 酷,好多了。所以听起来你点击了一个按钮,你需要检查那个按钮是否有炸弹,如果没有,就“打开”它。是否返回了正确的 x 和 y 值?
  • @matt 是的,x 和 y 值正确返回(确保并在调试器中检查),“game”变量(一个 Mines 对象)打开正确的插槽(在“game. open(x,y)"),“open”方法基本上会添加一个“T”字符,因此代码会打开该插槽(“T”是要打开的插槽的指示器)。现在对于这个问题,我似乎找不到打开它的方法,我尝试了循环中所示的方法,但这是错误的,因为该插槽已经包含“T”,所以它会打开许多​​其他插槽(不应该被打开),我只需要打开正确的插槽(包含“T”)。
  • 你为什么要遍历所有的插槽?您不是已经有了要更改的插槽吗? (Button)evt.getSource() 是您要更改的按钮吗?
  • 请使用java命名约定

标签: javafx fxml actionevent


【解决方案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中子节点的顺序是否对应​​布局顺序,常用的把二维数组打包成一维数组的技巧,

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

记住你有第 x 列的总按钮。

【讨论】:

  • 我只是将 if 行更改为 game.get(i,j) 而不是 (x,y) 并且效果很好(我认为这是因为如果插槽只有一个“T”,它应该被打开)!谢谢!还有你的最后一条注释,我确实知道这一点,但从未尝试过以这种方式实现它,非常有用,谢谢!
猜你喜欢
  • 2015-08-02
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 2018-10-11
相关资源
最近更新 更多