Одним из возможных решений является создание собственного ImageView
, который содержит код для щелчков мыши внутри.
Вот пример TileButton
класс:
class TileButton extends ImageView {
public TileButton() {
// Set parameters for the image
Image graphic = new Image("minesweeper/tile.png");
setImage(graphic);
setFitWidth(24);
setFitHeight(24);
// When this button is click, set its visibility to false.
setOnMouseClicked(e -> {
setVisible(false);
});
}
}
Используя этот пользовательский класс, вся логика «кнопки» содержится внутри самого TileButton
.
Теперь вы можете заполнить ваше минное поле GridPane
из StackPane
контейнеров в каждой ячейке. StackPane
позволяет размещать узлы друг над другом. Итак, поместите Label
с нужным номером в каждый StackPane
, а затем добавьте новый TileButton
поверх него.
Ниже приведен пример приложения для демонстрации. Обратите внимание, я не реализую здесь никакой реальной игровой логики, а просто предоставляю пример, который вы можете скопировать / вставить и увидеть в действии. Я также не тратил время на форматирование и стилизацию ImageView
, но вы можете использовать CSS, чтобы заставить его работать как стандартная кнопка.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(5);
root.setPadding(new Insets(10));
root.setAlignment(Pos.CENTER);
// GridPane to hold the cells
GridPane gridPane = new GridPane();
gridPane.setGridLinesVisible(true);
gridPane.setHgap(2);
gridPane.setVgap(2);
// Populate the Gridpane with a 10x10 grid
int number = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
// Add a new StackPane for each grid cell. The Stackpane will hold a number and the
// TileButton. When the TileButton is clicked, it disappears, revealing the number below
StackPane pane = new StackPane();
pane.getChildren().add(new Label(String.valueOf(number)));
pane.getChildren().add(new TileButton());
gridPane.add(pane, j, i);
// Just increment our sample number
number++;
}
}
root.getChildren().add(gridPane);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
class TileButton extends ImageView {
public TileButton() {
// Set parameters for the image
Image graphic = new Image("minesweeper/tile.png");
setImage(graphic);
setFitWidth(24);
setFitHeight(24);
// When this button is click, set its visibility to false.
setOnMouseClicked(e -> {
setVisible(false);
});
}
}
Пример приложения выше:
Примечание Я не использую FXML
для этого, поскольку создание сетки из нескольких пользовательских объектов в Java намного проще, чем FXML.
За предложение Клеопатры , это можно сделать, используя вместо этого пользовательский Button
. С новым классом TileButton
, представленным ниже, вы можете добавить кнопки в наш цикл, используя gridPane.add(new TileButton(String.valueOf(number)), j, i);
:
class TileButton extends Button {
public TileButton(String text) {
// Set the button's size
setPrefSize(24,24);
setStyle("-fx-padding: 0");
// Set the graphic to our tile.png image
setGraphic(new ImageView("sample/done/minesweeper/tile.png"){{
setFitWidth(24);
setFitHeight(24);
}});
// Set the button to display only our graphic initially
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// Set the action to remove the graphic when the button is clicked
setOnAction(event -> {
setGraphic(new Label(text));
});
}
}