【问题标题】:Add menu to javafx game将菜单添加到 javafx 游戏
【发布时间】:2016-05-06 05:05:05
【问题描述】:

我对 java 和 javafx 还是很陌生,我已经创建了一个扫雷游戏。我想添加一个小菜单栏,用户可以在其中选择游戏难度(瓷砖数量)。我已经创建了一个菜单方法,但我不确定将它添加到场景的哪个位置。在我尝试放置菜单方法的任何地方,我都会遇到异常错误。

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Minesweeper extends Application {

private int TILE_SIZE = 50;
private static final int W = 800;
private static final int H = 600;

private int X_TILES = W / TILE_SIZE;
private int Y_TILES = H / TILE_SIZE;
private final String[] gameType = {"Easy", "Medium", "Hard", "Very Hard"};
private String difficulty;

@FXML
private Menu gameMenu;

private Tile[][] grid = new Tile[X_TILES][Y_TILES];
private Scene scene;

public void menu() {
    for(String game : gameType){
        MenuItem menuItem = new MenuItem(game);
        menuItem.setUserData(game);
        menuItem.setOnAction((ActionEvent event) -> {
            selectGame(event);
        });
        gameMenu.getItems().add(menuItem);
    }
}
private void selectGame(ActionEvent event) {
    MenuItem menuItem = (MenuItem)event.getSource();
    difficulty = (String)menuItem.getUserData();
    switch (difficulty) {
        case "Easy":
            TILE_SIZE = 200;
            break;
        case "Medium":
            TILE_SIZE = 100;
            break;
        case "Hard":
            TILE_SIZE = 50;
            break;
        case "Very Hard":
            TILE_SIZE = 40;
            break;
        default:
            break;
    }
}

private Parent createContent() {
    Pane root = new Pane();
    root.setPrefSize(W, H);

    for (int y = 0; y < Y_TILES; y++) {
        for (int x = 0; x < X_TILES; x++) {
            Tile tile = new Tile(x, y, Math.random() < 0.2);

            grid[x][y] = tile;
            root.getChildren().add(tile);
        }
    }

    for (int y = 0; y < Y_TILES; y++) {
        for (int x = 0; x < X_TILES; x++) {
            Tile tile = grid[x][y];

            if (tile.hasBomb)
                continue;

            long bombs = getNeighbors(tile).stream().filter(t ->      t.hasBomb).count();

            if (bombs > 0)
                tile.text.setText(String.valueOf(bombs));
        }
    }

    return root;
}

private List<Tile> getNeighbors(Tile tile) {
    List<Tile> neighbors = new ArrayList<>();

    int[] points = new int[] {
          -1, -1,
          -1, 0,
          -1, 1,
          0, -1,
          0, 1,
          1, -1,
          1, 0,
          1, 1
    };

    for (int i = 0; i < points.length; i++) {
        int dx = points[i];
        int dy = points[++i];

        int newX = tile.x + dx;
        int newY = tile.y + dy;

        if (newX >= 0 && newX < X_TILES
                && newY >= 0 && newY < Y_TILES) {
            neighbors.add(grid[newX][newY]);
        }
    }

    return neighbors;
}

private class Tile extends StackPane {
    private int x, y;
    private boolean hasBomb;
    private boolean isOpen = false;

    private Rectangle border = new Rectangle(TILE_SIZE - 2, TILE_SIZE - 2);
    private Text text = new Text();

    Alert alert = new Alert(AlertType.CONFIRMATION, "Game Over! Play   Again?");

    public Tile(int x, int y, boolean hasBomb) {
        this.x = x;
        this.y = y;
        this.hasBomb = hasBomb;

        border.setStroke(Color.LIGHTGRAY);

        text.setFont(Font.font(18));
        text.setText(hasBomb ? "X" : "");
        text.setVisible(false);

        getChildren().addAll(border, text);

        setTranslateX(x * TILE_SIZE);
        setTranslateY(y * TILE_SIZE);

        setOnMouseClicked(e -> open());
    }

    public void open() {
        if (isOpen)
            return;

        if (hasBomb) {
           Optional<ButtonType> result = alert.showAndWait();
            if (result.isPresent() && result.get() == ButtonType.OK) {
                scene.setRoot(createContent());   
            }
           return;
        }

        isOpen = true;
        text.setVisible(true);
        border.setFill(null);

        if (text.getText().isEmpty()) {
            getNeighbors(this).forEach(Tile::open);
        }

        switch (text.getText()) {
            case "1":
                text.setFill(Color.BLUE);
                break;
            case "2":
                text.setFill(Color.FORESTGREEN);
                break;
            case "3":
                text.setFill(Color.RED);
                break;
            case "4":
                text.setFill(Color.DARKBLUE);
                break;
            case "5":
                text.setFill(Color.MAROON);
                break;
            case "6":
                text.setFill(Color.AQUAMARINE);
                break;
            case "7":
                text.setFill(Color.BLACK);
                break;
            case "8":
                text.setFill(Color.GRAY);
                break;
            default:
                break;
        }
    }
}

@Override
public void start(Stage stage) throws Exception {
    scene = new Scene(createContent());

    stage.setScene(scene);
    stage.show();     
}

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

【问题讨论】:

  • 您的private Menu gameMenu 从未被初始化。另外,我相信您可能需要MenuBar 来持有gameMenu。您可以在 Java 文档here 阅读更多内容

标签: java javafx


【解决方案1】:

你可以这样添加:

public MenuBar menu() {
    gameMenu = new Menu("Difficulty");
    for(String game : gameType){
        MenuItem menuItem = new MenuItem(game);
        menuItem.setUserData(game);
        menuItem.setOnAction((ActionEvent event) -> {
            selectGame(event);
        });
        gameMenu.getItems().add(menuItem);
    }
    MenuBar menuBar = new MenuBar(gameMenu);
    return menuBar;
}

private Parent createContent() {
    VBox root = new VBox();
    Pane content = new Pane();
    content.setPrefSize(W, H);

    for (int y = 0; y < Y_TILES; y++) {
        for (int x = 0; x < X_TILES; x++) {
            Tile tile = new Tile(x, y, Math.random() < 0.2);

            grid[x][y] = tile;
            content.getChildren().add(tile);
        }
    }

    for (int y = 0; y < Y_TILES; y++) {
        for (int x = 0; x < X_TILES; x++) {
            Tile tile = grid[x][y];

            if (tile.hasBomb)
                continue;

            long bombs = getNeighbors(tile).stream().filter(t ->      t.hasBomb).count();

            if (bombs > 0)
                tile.text.setText(String.valueOf(bombs));
        }
    }
    root.getChildren().addAll(menu(), content);

    return root;
}

menu 方法中,我为gameMenu 创建了实例,在您的示例中使用@FXML 进行了注释,因此可能不需要此行。然而,该方法返回一个包含菜单的MenuBar

这个栏然后作为子元素添加到根元素。我还引入了一个用于布局的新层 (VBox),其中菜单和原始内容为子项。

另见this oracle article

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多