单击按钮时不执行的方法[JavaFX]

时间:2017-02-03 12:15:20

标签: java user-interface button methods javafx

我正在开发我的第一个JavaFX应用程序,这是一个Tic Tac Toe游戏。除按钮外,我已经完成了所有工作。单击时按钮应调用 checkTurn() 方法和 checkState() 方法。 checkTurn() 方法会显示 X O ,具体取决于 X 转向与否。 checkState() 方法,检查是否有任何玩家获胜或是否为平局,此时会显示新的舞台。

但是, checkState() 方法无法正常工作。我想知道它是否无法实例化新阶段,因此,出于调试目的,我用print语句替换了实例化,这也没有用。我得出的结论是,该方法甚至不被调用。

寻找修复我偶然发现了其他一些Tic Tac Toe程序,却发现我的方法在任何方面都没有错。我似乎无法弄清楚为什么 checkState() 方法没有被调用。

这是我的代码(按类名排列):

注意:除了Main.java之外的所有类都在一个名为" model"的文件夹中,我已经放了一个大评论,显示" checkState() "方法是,在Tiles.java中。

Main.java:

package com.frixoe;

import com.frixoe.model.Window;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

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

    @Override
    public void start(Stage window) throws Exception {
        Window gameScreen = new Window();

        window.setScene(new Scene(gameScreen));
        window.setTitle("Tic Tac Toe");
        window.setResizable(false);
        window.show();
    }
}

Window.java:

package com.frixoe.model;

import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;

public class Window extends GridPane {
    private final int HEIGHT = 600;
    private final int WIDTH = 600;
    private Tiles tiles;

    public Window() {
        setPrefSize(WIDTH, HEIGHT);
        setAlignment(Pos.CENTER);

        this.tiles = new Tiles();

        placeTiles();
    }

    private void placeTiles() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                Button tile = this.tiles.getTiles()[i][j];
                setConstraints(tile, j, i);
                getChildren().add(tile);
            }
        }
    }
}

Tiles.java:

package com.frixoe.model;

import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;

public class Tiles extends StackPane {
    private boolean isTurnX = true;
    private Button[][] tiles = new Button[3][3];
    private Font helvetica = new Font("Helvetica", 70);

    public Button[][] getTiles() {
        generateTiles();
        return this.tiles;
    }

    private void generateTiles() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                Button newBtn = new Button("");
                newBtn.setFont(helvetica);
                newBtn.setPrefSize(600 / 3, 600 / 3);
                newBtn.setOnAction(event -> {
                    checkTurn(newBtn);
                    checkState(); // <================================THIS METHOD
                });
                this.tiles[i][j] = newBtn;
            }
        }
    }

    private void checkState() {
        if (hasWon("X")) {
            new AlertBox("Yay! Player X has Won!", "X Won!");
        } else if (hasWon("O")) {
            new AlertBox("Yay! Player O has Won!", "O Won!");
        } else if (isFull()) {
            new AlertBox("It's a draw!", "Draw!");
        }
    }

    private boolean isFull() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (this.tiles[i][j].getText().equalsIgnoreCase("")) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean hasWon(String player) {
        for (int i = 0; i < 3; i++) {
            if (tiles[i][0].getText().equalsIgnoreCase(player)
                    && tiles[i][1].getText().equalsIgnoreCase(player)
                    && tiles[i][2].getText().equalsIgnoreCase(player)) {
                return true;
            }
        }

        for (int i = 0; i < 3; i++) {
            if (tiles[0][i].getText().equalsIgnoreCase(player)
                    && tiles[1][i].getText().equalsIgnoreCase(player)
                    && tiles[2][i].getText().equalsIgnoreCase(player)) {
                return true;
            }
        }

        return tiles[0][0].getText().equalsIgnoreCase(player)
                && tiles[1][1].getText().equalsIgnoreCase(player)
                && tiles[2][2].getText().equalsIgnoreCase(player);
    }

    private void checkTurn(Button btn) {
        if (isTurnX) {
            drawO(btn);

            isTurnX = false;
        } else {
            drawX(btn);

            isTurnX = true;
        }
    }

    private void drawX(Button btn) {
        btn.setText("X");
    }

    private void drawO(Button btn) {
        btn.setText("O");
    }
}

另一个注意事项:AlertBox类是玩家获胜或抽签时显示的另一个阶段。

感谢您的帮助!

JDK:jdk1.8.0_121

系统:Windows 10 32位。

IDE:IntelliJ IDEA 2016.3.3

1 个答案:

答案 0 :(得分:3)

请注意,每次调用getTiles时都会重新生成磁贴,因此每个按钮有9个副本。这意味着虽然每个按钮都可以设置它自己的文本,但它们都“仅”看到最后一组九个按钮(由最后一次调用getTiles创建)。

确保您只创建一次瓷砖 - 通过在Tiles的构造函数中生成它们,或者在调用generateTiles中的getTiles之前检查它们是否已经初始化。