JavaFX 覆盖和揭示按钮字段中的按钮文本

标签 java button javafx minesweeper

好的,所以在初始化扫雷游戏板时,我的代码会遍历 Pane 中创建的所有按钮,并将文本设置为代表炸弹的 X 或数字(表示有多少炸弹是邻居)。如果两者都不是,则什么也不做。但现在我想知道如何在初始化游戏时隐藏该文本,以便可以通过单击鼠标来发现并恢复它?

enter image description here

这是迭代逻辑:

//iterate through rows and columns to fill board with random bombs
for (int y = 0; y < model.Y_FIELDS; y++) {
    for (int x = 0; x < model.X_FIELDS; x++) {
        Field field = new Field(x, y, Math.random() < 0.2, model);
        model.array[x][y] = field;
        root.getChildren().add(field);

    }
}

for (int y = 0; y < model.Y_FIELDS; y++) {
    for (int x = 0; x < model.X_FIELDS; x++) {
        Field field = model.array[x][y];

        if (field.isBomb())
            continue;

        long number = field.getSurrounding().stream().filter(f -> f.isBomb()).count();

        if (number > 0)
            field.board.setText(String.valueOf(number));
    }
}

我希望它们一开始是空白的。我应该把 setText("") 放在哪里?在鼠标左键单击事件中,我想发现它们。这看起来像 if(leftmouseclick) then set.Visible 或类似的东西......

最佳答案

您可以使用例如 PseudoClass用于在“显示”和“未显示”之间更改 Button 的 CSS 伪状态的 API。

您需要定义一个 CSS 伪类,例如:

.button:unrevealed { -fx-text-fill: transparent; }

这将代表尚未按下的按钮,并使 Button 的文本不可见。

并且您必须定义 JavaFX PseudoClass,如下所示:

PseudoClass unrevealedPseudo = PseudoClass.getPseudoClass("unrevealed");

然后使用它:

Button button = new Button("X");
button.pseudoClassStateChanged(unrevealedPseudo, true);

button.setOnAction(e -> button.pseudoClassStateChanged(unrevealedPseudo, false));

在代码片段中,Button 在创建时设置为“未显示”,然后按下后会保持该状态,因此 -fx-text-fill 属性将改回默认值。

如果您对所有按钮应用相同的创建逻辑,那么它们的初始文本是什么并不重要,因为它会被隐藏,直到不显示为止(通过按下按钮或以编程方式更改它)。

注意1:您可以使用相同的 API 定义更多伪类,如果您想在右键单击按钮上设置“标志”,这将非常方便,因为您可以简单地使用这些 CSS 类来定义按钮在不同状态下的外观。

注意2:如果您有一个后端,它会存储每个字段的状态(显示、标记、未显示),例如在前端创建单独的 Button< 时使用属性 对于领域模型的每个元素,您可以简单地检查模型中元素的 state 属性的更新,并且可以简单地将 Button 放入正确的伪类中。它比改变它要优雅得多,例如单击按钮。

使用注释2中的方法的示例:

型号:

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;

public class MineSweeperField {
    public enum State {
        UNREVEALED, REVEALED, FLAGGED
    };

    private ObjectProperty<State> state = new SimpleObjectProperty<State>(State.UNREVEALED);

    public ObjectProperty<State> stateProperty() {
        return state;
    }

    public State getState() {
        return stateProperty().get();
    }

    public void setState(State state) {
        stateProperty().set(state);
    }
}

按钮:

import application.MineSweeperField.State;
import javafx.css.PseudoClass;
import javafx.scene.control.Button;

public class MineSweepButton extends Button {

    static PseudoClass unrevealedPseudo = PseudoClass.getPseudoClass("unrevealed");
    static PseudoClass revealedPseudo = PseudoClass.getPseudoClass("revealed");
    static PseudoClass flaggedPseudo = PseudoClass.getPseudoClass("flagged");

    public MineSweepButton(MineSweeperField field) {

        this.getStyleClass().add("minesweep-button");

        this.pseudoClassStateChanged(unrevealedPseudo, true);

        field.stateProperty().addListener((obs, oldVal, newVal) -> changePseudoClass(newVal));
        changePseudoClass(field.getState());
    }

    private void changePseudoClass(State state) {
        this.pseudoClassStateChanged(unrevealedPseudo, false);
        this.pseudoClassStateChanged(revealedPseudo, false);
        this.pseudoClassStateChanged(flaggedPseudo, false);

        switch (state) {
        case FLAGGED:
            this.pseudoClassStateChanged(flaggedPseudo, true);
            break;
        case REVEALED:
            this.pseudoClassStateChanged(revealedPseudo, true);
            break;
        case UNREVEALED:
            this.pseudoClassStateChanged(unrevealedPseudo, true);
            break;
        }
    }
}

CSS:

.minesweep-button:unrevealed { -fx-text-fill: transparent; }
.minesweep-button:revealed { -fx-text-fill: black; }
.minesweep-button:flagged { -fx-text-fill: orange; }

用法:

BorderPane root = new BorderPane();

MineSweeperField field = new MineSweeperField();
MineSweepButton msButton = new MineSweepButton(field);
msButton.setText("5");

Button reveal = new Button("Reveal");
Button unreveal = new Button("Unreveal");
Button flag = new Button("Flag");

root.setTop(new VBox(msButton, new HBox(reveal, unreveal, flag)));
reveal.setOnAction(e -> field.setState(State.REVEALED));
unreveal.setOnAction(e -> field.setState(State.UNREVEALED));
flag.setOnAction(e -> field.setState(State.FLAGGED));

输出:

enter image description here

关于JavaFX 覆盖和揭示按钮字段中的按钮文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40588033/

相关文章:

JavaFX addListener 不工作

java - 比较方法违反了它的一般契约和方法 compareTo

java - 我可以否定(!) Spring 配置文件的集合吗?

delphi - TBitBtn 仅使用旧版 Windows 主题显示

css - 在 php 中使用 css 时出现错误?

java - jp2launcher.exe 不会随着小程序关闭而退出

javafx-2 - JavafX 中的组件图

javax.persistence.PersistenceException : Unable to locate persistence units

java - cucumber 测试 java 示例?

c# - 在提交按钮的 OnClientClick 事件上调用 javascript 函数