如何在javafx 2.1中等待转换结束?

时间:2012-06-25 10:57:43

标签: java concurrency javafx

我的场景仅由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();

如何正确等待?谢谢

3 个答案:

答案 0 :(得分:17)

好的,如果您的ft2ft1的反光动画,那么

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

而你没有ft2。如果您仍然需要在ft2之后ft1播放

ft1.setOnFinished(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event) {
        ft2.play();
    }
});

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

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

    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线程中不调用此方法,否则,它对我有效。