延迟更新javafx中的场景

t8e9dugd  于 2021-08-20  发布在  Java
关注(0)|答案(1)|浏览(351)

我想编写一个javafx应用程序,其中有两个“更新”和“取消”按钮以及三个矩形。当你点击“取消”按钮时,所有矩形都变为黑色。单击“更新”按钮时,我只希望第一个矩形变为红色,半秒钟后,第二个矩形变为绿色(其他矩形变为黑色),半秒钟后,第三个矩形变为蓝色和其他黑色。
我正试图通过以下方式实现这一点: Thread.sleep 但我不能解决我的问题。
有没有关于我如何做到这一点的建议?
这是我到目前为止写的代码,但它似乎忽略了 Thread.sleep 只会让第三个变成蓝色。

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

import static javafx.scene.paint.Color.*;

public class UpdatingSceneWithDelays extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        AnchorPane anchorPane = new AnchorPane();
        Rectangle rectangle1 = new Rectangle(100, 100, 100, 100);
        Rectangle rectangle2 = new Rectangle(100, 250, 100, 100);
        Rectangle rectangle3 = new Rectangle(100, 400, 100, 100);
        Button button1 = new Button("cancel");
        Button button2 = new Button("update");
        button2.setLayoutY(100);
        button1.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                rectangle1.setFill(BLACK);
                rectangle2.setFill(BLACK);
                rectangle3.setFill(BLACK);
            }
        });
        button2.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                rectangle1.setFill(RED);
                rectangle2.setFill(BLACK);
                rectangle3.setFill(BLACK);
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                rectangle1.setFill(BLACK);
                rectangle2.setFill(GREEN);
                rectangle3.setFill(BLACK);
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                rectangle1.setFill(BLACK);
                rectangle2.setFill(BLACK);
                rectangle3.setFill(BLUE);
            }
        });
        anchorPane.getChildren().add(rectangle1);
        anchorPane.getChildren().add(rectangle2);
        anchorPane.getChildren().add(rectangle3);
        anchorPane.getChildren().add(button1);
        anchorPane.getChildren().add(button2);
        Scene scene = new Scene(anchorPane, 800, 800);
        stage.setScene(scene);
        stage.show();
    }
}
qmb5sa22

qmb5sa221#

你不能 sleep javafx应用程序线程。该线程专用于读取和写入ui状态、调度渲染“脉冲”以及处理用户生成的事件。如果您阻止或垄断了它,那么它将无法完成其工作,ui将冻结/变得无响应。
无论何时,只要您想在javafx应用程序线程上执行延迟动作(无论是否循环),都应该使用动画。就我个人而言,我会选择 Timeline 在这种情况下。下面是一个例子:

Timeline timeline =
    new Timeline(
        // first rectangle to red (assumes all start as black)
        new KeyFrame(
            Duration.ZERO, 
            e -> rectangle1.setFill(Color.RED)),
        // first rectangle to black, second to green
        new KeyFrame(
            Duration.seconds(0.5),
            e -> {
              rectangle1.setFill(Color.BLACK);
              rectangle2.setFill(Color.GREEN);
            }),
        // second rectangle to black, third to blue
        new KeyFrame(
            Duration.seconds(1.0), // duration doesn't stack
            e -> {
              rectangle2.setFill(Color.BLACK);
              rectangle3.setFill(Color.BLUE);
            }));
timeline.playFromStart();

可以根据需要重用动画(尽管它不能同时运行自身的多个示例)。请注意 Timeline 将异步播放并调用 playFromStart()play() 我马上回来。如果这是应用程序的一个问题,那么您需要重写它以将其考虑在内。例如,您可以使用 timeline.setOnFinished(...) 完成后做某事。
这里,您至少可以使用两种备选方法(我不详细介绍):
替换每个已完成的处理程序上的 KeyFrame 与一个或多个 KeyValue S对于与以前相同的行为,您需要每个 KeyValue 使用离散 Interpolator .
使用多个 PauseTransition s与a结合在一起 SequentialTransition (持续时间堆栈)或 ParallelTransition (持续时间不堆叠)。

相关问题