在JavaFX中实现ImageView的过渡效果

5
我已经查看了如何在javafx 2.1中等待过渡结束?,但它并没有完全解决我的问题。
我有一个ImageView对象的列表,并且我想迭代这个列表并对每个“幻灯片”执行以下操作:
  1. 淡入
  2. 停留几秒钟
  3. 淡出
我已经编写了下面的代码,但由于过渡是异步的,循环会同时将过渡应用于所有“幻灯片”:
// The method I am running in my class

public void start() {

    for (ImageView slide : slides) {

        SequentialTransition sequentialTransition = new SequentialTransition();

        FadeTransition fadeIn = Transition.getFadeTransition(slide, 0.0, 1.0, 2000);
        FadeTransition stayOn = Transition.getFadeTransition(slide, 1.0, 1.0, 2000);
        FadeTransition fadeOut = Transition.getFadeTransition(slide, 1.0, 0.0, 2000);

        sequentialTransition.getChildren().addAll(fadeIn, stayOn, fadeOut);               
        this.root.getChildren().add(slide);            
        sequentialTransition.play();

    }
}

// the method in the Transition helper class:

public static FadeTransition getFadeTransition(ImageView imageView, double fromValue, double toValue, int durationInMilliseconds) {

    FadeTransition ft = new FadeTransition(Duration.millis(durationInMilliseconds), imageView);
    ft.setFromValue(fromValue);
    ft.setToValue(toValue);

    return ft;

}

有什么想法可以让这些 ImageView 对象一个接一个地动起来(无论列表中有多少个 ImageView,我都不想硬编码)。谢谢。
1个回答

4
因此,显而易见的解决方法是使用一个包围顺序转换的顺序转换,按顺序播放这些转换,而不是一次性全部播放:
public void start() {

    SequentialTransition slideshow = new SequentialTransition();

    for (ImageView slide : slides) {

        SequentialTransition sequentialTransition = new SequentialTransition();

        FadeTransition fadeIn = Transition.getFadeTransition(slide, 0.0, 1.0, 2000);
        FadeTransition stayOn = Transition.getFadeTransition(slide, 1.0, 1.0, 2000);
        FadeTransition fadeOut = Transition.getFadeTransition(slide, 1.0, 0.0, 2000);

        sequentialTransition.getChildren().addAll(fadeIn, stayOn, fadeOut);               
        this.root.getChildren().add(slide);            
        slideshow.getChildren().add(sequentialTransition);

    }
    slideshow.play();
}

其次,你应该使用PauseTransition而不是从1.0插值到1.0的FadeTransition。

一个完整的示例应用程序可能看起来像这样:

package slideshow;

import javafx.animation.FadeTransition;
import javafx.animation.PauseTransition;
import javafx.animation.SequentialTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class SimpleSlideShowTest extends Application{

  class SimpleSlideShow {

    StackPane root = new StackPane();
    ImageView[] slides;

    public SimpleSlideShow() {
      this.slides = new ImageView[4];
      Image image1 = new Image(SlideShowTest.class.getResource("pic1").toExternalForm());
      Image image2 = new Image(SlideShowTest.class.getResource("pic2").toExternalForm());
      Image image3 = new Image(SlideShowTest.class.getResource("pic3").toExternalForm());
      Image image4 = new Image(SlideShowTest.class.getResource("pic4").toExternalForm());
      slides[0] = new ImageView(image1);
      slides[1] = new ImageView(image2);
      slides[2] = new ImageView(image3);
      slides[3] = new ImageView(image4);

    }

    public StackPane getRoot() {
      return root;
    }

    // The method I am running in my class

    public void start() {

      SequentialTransition slideshow = new SequentialTransition();

      for (ImageView slide : slides) {

        SequentialTransition sequentialTransition = new SequentialTransition();

        FadeTransition fadeIn = getFadeTransition(slide, 0.0, 1.0, 2000);
        PauseTransition stayOn = new PauseTransition(Duration.millis(2000));
        FadeTransition fadeOut = getFadeTransition(slide, 1.0, 0.0, 2000);

        sequentialTransition.getChildren().addAll(fadeIn, stayOn, fadeOut);
        slide.setOpacity(0);
        this.root.getChildren().add(slide);
        slideshow.getChildren().add(sequentialTransition);

      }
      slideshow.play();
    }

// the method in the Transition helper class:

    public FadeTransition getFadeTransition(ImageView imageView, double fromValue, double toValue, int durationInMilliseconds) {

      FadeTransition ft = new FadeTransition(Duration.millis(durationInMilliseconds), imageView);
      ft.setFromValue(fromValue);
      ft.setToValue(toValue);

      return ft;

    }
  }

  public static void main(String[] args) {
    launch(args);
  }

  @Override
  public void start(Stage primaryStage) throws Exception {
    SimpleSlideShow simpleSlideShow = new SimpleSlideShow();
    Scene scene = new Scene(simpleSlideShow.getRoot());
    primaryStage.setScene(scene);
    primaryStage.show();
    simpleSlideShow.start();
  }
}

谢谢Sebastian! :) 我还没有尝试过(回家后会尝试),但这很有道理,哈哈..我太蠢了..非常感谢! :) 我回家后会更新你。 - Software Guy
没问题。如果我可以补充一下,我宁愿使用Timer和TimerTask来触发下一张幻灯片,而不是JavaFX,因为这样更具可扩展性。几周前,我为自己编写了一个幻灯片,添加按钮或停止幻灯片是您可能想要稍后添加到应用程序中的功能。 - zhujik
@SoftwareGuy:我不知道你缺少什么,但我发布了一个完整的示例,展示了幻灯片。请注意每张幻灯片的setOpacity(0) - zhujik
谢谢@Sebastian :) 我没有使用setOpacity方法。我晚些时候会尝试一下并更新你。非常感谢你提供完整的示例代码。我真的很感激你的帮助 :) - Software Guy
1
Awesssomeee @Sebastian :) slide.setOpacity(0); 是缺失的部分!非常感谢你!你太棒了! - Software Guy
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接