【问题标题】:How to wait for a transition to end in javafx 2.1?如何在 javafx 2.1 中等待过渡结束?
【发布时间】:2012-06-25 10:57:43
【问题描述】:

我的场景仅包含一个ImageView,显示图像。我想将图像淡化为黑色(场景的指定颜色),然后过一段时间,再次从黑色淡化为图像。我发现FadeTransition 非常适合这个目的。这是我的一段代码:

    // fade to black transition
    FadeTransition ft1 = new FadeTransition(Duration.millis(2000), myImageView);
    ft1.setFromValue(1.0);
    ft1.setToValue(0.0);
    ft1.play();

    // fade from black transition
    FadeTransition ft2 = new FadeTransition(Duration.millis(2000), myImageView);
    ft2.setFromValue(0.0);
    ft2.setToValue(1.0);
    ft2.play();

我的问题是ft1.play() 是异步的,所以下面的代码将在ft1.play() 退出之前开始执行。结果,我只看到第二个过渡。如何等待第一个过渡结束然后启动第二个过渡?我不能让线程在两者之间休眠,因为它是主要的 javafx 线程(尝试过但没有工作)。

我尝试将 onFinishedProperty() 方法与标志上的忙等待结合使用,但我永远卡在 while 循环中。这是我的代码:

    boolean isTransitionPlaying;
    FadeTransition ft = new FadeTransition(Duration.millis(2000), iv);
    ft.setFromValue(1.0);
    ft.setToValue(0.0);
    ft.onFinishedProperty().set(new EventHandler<ActionEvent>() {
        @Override 
        public void handle(ActionEvent actionEvent) {
            transitionPlaying = false;
        }
    });
    transitionPlaying = true;
    ft.play();

    while (transitionPlaying == true)
    {
        // busy wait
        System.out.println("still waiting...");
    }

    FadeTransition ft2 = new FadeTransition(Duration.millis(2000), iv);
    ft2.setFromValue(0.0);
    ft2.setToValue(1.0);
    ft2.play();

等待是如何正确完成的?谢谢

【问题讨论】:

    标签: java concurrency javafx


    【解决方案1】:

    好的,如果您的ft2ft1 的反射动画,那么就这样做

    ft1.setAutoReverse(true);
    ft1.setCycleCount(1);
    // Or
    // ft1.setCycleCount(Timeline.INDEFINITE);
    // to loop infinitely (blinking effect) until stop()
    

    而你没有ft2。如果你还需要ft2ft1 之后播放,那么

    ft1.setOnFinished(new EventHandler<ActionEvent>() {
    
        @Override
        public void handle(ActionEvent event) {
            ft2.play();
        }
    });
    

    【讨论】:

    • 好吧,除了 setOnFinished(),你知道在 play() 结束后执行给定代码的另一种方法吗?我希望能够在我的代码上组织转换,而不是围绕转换组织逻辑......
    • 不幸的是,正如您提到的,将主线程置于睡眠/等待模式并不容易。在显示模态(确认)对话框窗口时也会出现同样的困难。但 showAndWait (v2.2) 方法将提供解决方案,仅适用于模态阶段。
    【解决方案2】:

    在 JavaFX 应用程序线程上忙于等待(甚至是 Thread.sleep)总是一个坏主意 - 您占用了处理 UI 处理的线程,因此您的转换以及 UI 的其余部分永远不会更新 -在繁忙的等待期间有效地冻结您的应用程序 UI。对于响应式 UI,您需要尽快在 FX 应用程序线程上运行您的逻辑,然后让线程运行,以便 JavaFX 系统的其余部分可以继续处理它。这就是过渡具有异步回调的原因 - 一旦您习惯了它们,这是一种非常自然的开发方式。

    除了 Uluk 的解决方案(非常棒)之外,您还可以查看 SequentialTransition 类,以帮助处理按顺序执行转换的帮助。请注意,如果您想在 SequentialTransition 完成后执行操作,您仍需要将 onFinished 处理程序添加到 SequentialTransition 以在此时执行操作。

    【讨论】:

    • 我想我在想,由于转换 play() 是异步的,它们发生在另一个线程上,然后是 JavaFX 应用程序线程。这就是为什么我认为我可以让主线程等待转换完成他们的事情然后恢复。现在我看到如果应用程序线程正在休眠,那么转换也无法处理,对吧?所以我猜 SequentialTransition 是我的案例最清晰的解决方案。感谢你和 Ukuk。
    【解决方案3】:

    我在其他代码进行一些计算时遇到问题,我想在 JavaFX 应用程序中运行动画,但需要制作其他代码来等待动画完成。当动画完成时我无法告诉其他代码,所以我创建了播放动画然后等待它完成的方法:

        private synchronized void playAnimationAndWaitForFinish(final Animation animation) {
        if (Platform.isFxApplicationThread()) {
            throw new IllegalThreadStateException("Cannot be executed on main JavaFX thread");
        }
        final Thread currentThread = Thread.currentThread();
        final EventHandler<ActionEvent> originalOnFinished = animation.getOnFinished();
        animation.setOnFinished(new EventHandler<ActionEvent>() {
    
            @Override
            public void handle(ActionEvent event) {
                if (originalOnFinished != null) {
                    originalOnFinished.handle(event);
                }
                synchronized (currentThread) {
                    currentThread.notify();
                }
            }
        });
        Platform.runLater(new Runnable() {
    
            @Override
            public void run() {
                animation.play();
            }
        });
        synchronized (currentThread) {
            try {
                currentThread.wait();
            } catch (InterruptedException ex) {
                //somebody interrupted me, OK
            }
        }
    }
    

    要求此方法不在JavaFX主线程中调用,否则对我有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-04
      • 1970-01-01
      • 2017-04-13
      • 2014-05-03
      • 2023-03-05
      • 1970-01-01
      • 2014-11-27
      相关资源
      最近更新 更多