在一个函数中两次更改按钮背景

Change button background twice within one function

我正尝试在 javaFX 中执行 "memoryGame"。我现在正在处理的是更改按钮的背景,使用 CSS,在一个函数中两次,在单击此按钮后。

在这个游戏中,我创建了一个 GridPane,并在每个单元格中放置了带有图片的按钮,每张图片都有两个按钮。在它上面我放了另一个空按钮。如果我点击一个按钮,它会变成透明的,所以我可以看到图片。然后我点击了另一个按钮,同样的事情发生了。现在,如果图片相同,我会得到一分,透明度不会改变,但如果图片不同,程序会等待一秒钟,然后将两个按钮都更改为它们的主要阶段(不透明)。

问题是,如果我更改按钮的样式,请稍等一下,然后再更改一次,在此函数期间按钮不会更改其样式,但会在函数结束后发生。所以我们看不到第一个样式,只能看到最后一个。

我发送的代码是简化版,'works' 仅用于一个按钮。

public void changeTransparent(ActionEvent event) {
        butCver01.setStyle("-fx-background-color: transparent");

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}

        butCver01.setStyle("-fx-background-color: green");

    }

现在我们点击butCver01,一秒后会变成绿色

正如我在评论中提到的,JavaFX 应用程序线程 无法在仍在执行您的方法时安排下一帧渲染(即 "pulse")。由于您使用 Thread.sleep 阻塞 FX 线程,这意味着它无法执行 任何事情,更不用说安排下一个脉冲。被阻止的 FX 线程等于冻结 UI,您的用户将无法点击更多卡片来尝试获得匹配。

您应该使用 animation API 在 FX 线程上执行操作 "over time"。动画执行 "asynchronously"(在 FX 线程上),这意味着可以在动画 运行 时处理其他动作。启动动画的调用也会立即 returns。这是一个示例,该示例将在一秒钟内显示矩形下方的形状;但是,没有逻辑来确定是否显示了两个匹配的形状,一次只显示了两个形状,等等。

import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        HBox box = new HBox(10, createCard(true), createCard(true), createCard(false));
        box.setPadding(new Insets(100));
        primaryStage.setScene(new Scene(box));
        primaryStage.show();
    }

    private StackPane createCard(boolean circle) {
        Shape shape;
        if (circle) {
            shape = new Circle(50, Color.FORESTGREEN);
        } else {
            // create triangle
            shape = new Polygon(0, 0, 50, 100, -50, 100);
            shape.setFill(Color.FIREBRICK);
        }

        Rectangle cover = new Rectangle(0, 0, 100, 150);
        cover.mouseTransparentProperty()
                .bind(cover.fillProperty().isEqualTo(Color.TRANSPARENT));
        cover.setOnMouseClicked(event -> {
            event.consume();

            cover.setFill(Color.TRANSPARENT);

            PauseTransition pt = new PauseTransition(Duration.seconds(1));
            pt.setOnFinished(e -> cover.setFill(Color.BLACK));
            pt.playFromStart();
        });
        return new StackPane(shape, cover);
    }

}