我的场景仅由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();
如何正确等待?谢谢
答案 0 :(得分:17)
好的,如果您的ft2
是ft1
的反光动画,那么
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线程中不调用此方法,否则,它对我有效。