好的,所以在初始化扫雷游戏板时,我的代码会遍历 Pane 中创建的所有按钮,并将文本设置为代表炸弹的 X 或数字(表示有多少炸弹是邻居)。如果两者都不是,则什么也不做。但现在我想知道如何在初始化游戏时隐藏该文本,以便可以通过单击鼠标来发现并恢复它?
这是迭代逻辑:
//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));
输出:
关于JavaFX 覆盖和揭示按钮字段中的按钮文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40588033/