How to change images with Timeline in JavaFX

荒凉一梦 提交于 2021-02-11 02:47:15

问题


I intend to change the images of birds over the time by adding key frames in a for loop to the timeline object. It turns out that only the first image is displayed. Could someone point out where part I got it wrong. Thanks in advance.

Besides, I noticed that I have to reset the counter "index" to 0 after for loop otherwise it generates java.lang.ArrayIndexOutOfBoundsException.

package application;

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);
}

}


回答1:


you don't have to declare your index-field outside. this also causes your problem: whenever the handle method is called, it will reference your field: index which you set to 0 after your loop.

therefor you can declare a new field as finaland pass it to the handler:

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]))));
                }

            };
    ...
}


来源:https://stackoverflow.com/questions/34849232/how-to-change-images-with-timeline-in-javafx

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!