如何在 JavaFX 中使用时间轴更改图像

How to change images with Timeline in JavaFX

我打算通过将 for 循环中的关键帧添加到时间轴对象来随时间改变鸟类的图像。原来只显示了第一张图片。有人可以指出我在哪里弄错了。提前致谢。

此外,我注意到我必须在 for 循环后将计数器 "index" 重置为 0,否则它会生成 java.lang.ArrayIndexOutOfBoundsException。

打包申请;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.BoxBlur;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;

public class Main extends Application 

{

int index=0;
@Override
public void start(Stage primaryStage) {
    try {

        ImageView bgV = new ImageView();
        Image img_BG = new Image(Main.class.getResourceAsStream("background.png"));
        bgV.setImage(img_BG);
        bgV.setEffect(new BoxBlur());
        bgV.setOpacity(0.5);

        ImageView t1V = new ImageView();
        Image img_t1 = new Image(Main.class.getResourceAsStream(
                "t1.png"
                ));
        t1V.setImage(img_t1);

        ImageView t2V = new ImageView();
        Image img_t2 = new Image(Main.class.getResourceAsStream(
                "t2.png"
                ));
        t2V.setImage(img_t2);

        ImageView t3V = new ImageView();
        Image img_t3 = new Image(Main.class.getResourceAsStream(
                "t3.png"
                ));
        t3V.setImage(img_t3);

        Group foreground = new Group(t1V,t2V,t3V);

        t1V.setTranslateX(20);
        t1V.setTranslateY(200);

        t2V.setTranslateX(300);
        t2V.setTranslateY(200);

        t3V.setTranslateX(550);
        t3V.setTranslateY(200);
        foreground.setEffect(new DropShadow());

        String[]
                birdFiles = {"b1.png", "b2.png", "b3.png", "b4.png", "b5.png", "b6.png"};
        double[] ds = { 300,            600,                900,            1200,   1500,   1800};

        ImageView birdV = new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[0])));
        Group birds = new Group(birdV);
        birds.setTranslateX(img_BG.getWidth()-100);

        Timeline timeline  = new Timeline(); 
        timeline.setCycleCount(
                Animation.INDEFINITE
                ); 


        KeyFrame[] kframs = new KeyFrame[birdFiles.length];

        for( index=0; index<birdFiles.length; index++)
        {
            EventHandler<ActionEvent>
                onFishined = new EventHandler<ActionEvent>()
            {

                @Override
                public void handle(ActionEvent arg0)
                {
                    birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[index]))));

                }

            };
            Duration duration = Duration.millis(ds[index]);
            KeyFrame
                kf = new KeyFrame(duration, onFishined,null,null    );
             timeline.getKeyFrames().add(kf);

        }//End for i
        index = 0;







        timeline.play();





        Group root = new Group(bgV,foreground,birds);

        Scene scene = new Scene(root,img_BG.getWidth(), img_BG.getHeight());
        scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

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

}

您不必在外部声明您的 index 字段。这也会导致您的问题:每当调用 handle 方法时,它都会引用您的字段:index,您在循环后将其设置为 0。

因此您可以将新字段声明为 final 并将其传递给处理程序:

for (int index = 0; index < birdFiles.length; index++) {
    final int birdIndex = index;
    EventHandler<ActionEvent> onFishined = new EventHandler<ActionEvent>() {

                @Override
                public void handle(ActionEvent arg0) {
                    birds.getChildren().setAll(new ImageView(new Image(Main.class.getResourceAsStream(birdFiles[birdIndex]))));
                }

            };
    ...
}