【问题标题】:JavaFX System.currentTimeMillis() + TaskJavaFX System.currentTimeMillis() + 任务
【发布时间】:2014-12-03 00:58:06
【问题描述】:

我目前正在做一些带有一些动画的 GUI。我最终自己编写了标签的颜色变化。为此,我实施了以下任务:

Task tk= new Task() {
            @Override protected Void call() throws Exception
            {
                colorAnimation=true;
                boolean red = true;
                long timer = System.currentTimeMillis();
                long waitTime= 1000;
                nome.setStyle("-fx-background-color: red;");
                main: while(colorAnimation)
                {
                    while(System.currentTimeMillis() < waitTime+ timer)
                    {
                        System.out.println(System.currentTimeMillis()-timer);
                        if(!colorAnimation)
                            break main;
                    }
                    timer=System.currentTimeMillis();

                    red=!red;
                    if(red)
                    {
                        nome.setStyle("-fx-background-color: red;");
                        waitTime=1000;
                    }
                    else
                    {
                        nome.setStyle("-fx-background-color: black;");
                        waitTime=500;
                    }
                }
                nome.setStyle("-fx-background-color: black;");
                return null;
            }
        };
        Thread t = new Thread(tk);
        t.setDaemon(true);
        t.start();

上面的函数应该初始化标签颜色为红色,等待1秒,改成黑色,等待半秒再改成红色,重复这个过程,直到colorAnimation关闭(声明为volatile)。问题是该函数被卡在第二个while内,并且在控制台打印等待时间(System.currentTimeMillis()-timer)被卡在982。如果我将初始等待时间更改为500,那么打印的等待时间卡在 469。我真的不知道发生了什么。

谢谢!

【问题讨论】:

    标签: timer javafx task


    【解决方案1】:

    首先,您的代码对我“有效”,所以我无法解释为什么您会看到您所看到的效果。

    不过,您不应该使用它。它违反了 JavaFX 的规则之一:您不应该从 JavaFX 应用程序线程之外访问场景图的状态。 (例如,参见Threading in the Application Javadocs 部分。)当您尝试执行setStyle(...) 调用时,可能会抛出异常,导致线程终止;这可以解释您所看到的行为。 (但是,这似乎并没有在我的系统上发生。)

    此外,您的代码非常复杂并且难以维护。有为这种功能设计的更高级别的 API,例如Timeline。您应该使用这些 API 来简化代码并避免线程错误。

    例如:

    import javafx.animation.Animation;
    import javafx.animation.KeyFrame;
    import javafx.animation.Timeline;
    import javafx.application.Application;
    import javafx.beans.binding.Bindings;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    import javafx.util.Duration;
    
    public class ColorAnimationTest extends Application {
    
        @Override
        public void start(Stage primaryStage) {
    
            Label nome = new Label("Hello");
    
            // This chunk of code replaces your entire thread/task code
            Timeline animation = new Timeline(
                    new KeyFrame(Duration.millis(1000), 
                            event -> nome.setStyle("-fx-background-color: red;")),
                    new KeyFrame(Duration.millis(1500),
                            event -> nome.setStyle("-fx-background-color: black")));
    
            animation.setCycleCount(Animation.INDEFINITE);
            animation.play();
    
            // Button to stop/start the animation:
            Button button = new Button();
            button.setOnAction(event -> {
                if (animation.getStatus() == Animation.Status.RUNNING) {
                    animation.stop();
                } else {
                    animation.play();
                }
            });
    
            // change text of button approprite to animation state:
            button.textProperty().bind(Bindings
                    .when(animation.statusProperty().isEqualTo(Animation.Status.RUNNING))
                    .then("Stop")
                    .otherwise("Start"));
    
            VBox root = new VBox(10, nome, button);
            root.setAlignment(Pos.CENTER);
            Scene scene = new Scene(root, 350, 100);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    【讨论】:

    • 感谢您的回复和技巧。我正在查看代码,我想知道这是否有效。我的问题在于您为红色和黑色设置的持续时间。据我了解,该代码将使颜色每秒变为红色,并每 1.5 秒将其变为黑色。第二个第三个会不会有问题?据我了解,这两个事件都会尝试同时改变颜色。我说的对吗?
    • 你为什么不运行它?然后阅读各种方法调用的 java 文档,看看它做了什么。
    • 抱歉,我目前不在台式电脑上,所以我现在无法尝试,但我一定会尽快尝试。
    猜你喜欢
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    相关资源
    最近更新 更多