简体   繁体   中英

Animation using images in javafx application does not work

I am doing Animation of array of Images using Timeline Animation. The array is 299 images. It iterates once from 0 to 298 images and then animation stops.

It should continuously animate but does not work. I am using opacityProperty() for each imageview using timeline animation. Once one image animation is complete then it goes to next image. But I cannot loop continously when it reaches 298 image. The variable x should become 0 and then again start the animation.

public class Animation_Program_version3 extends Application {


    Timeline timeline = null;
    Group rootGroup = null;
    int x = 0;
    Image [] images = new Image[299];;
    ArrayList imageview = null;

    public Animation_Program_version3() {

    }


    @Override
    public void start(Stage primaryStage) {

        primaryStage.setTitle("JavaFX Welcome");

        rootGroup = new Group();

        final Scene scene = new Scene(rootGroup, 800, 400, Color.BEIGE);

        imageview = new ArrayList();  

        int y = 0;
            for(int x = -50; x < 100; x=x+1){ 
                images[y] = new Image("/Image"+x+".jpg", true);
                imageview.add(new ImageView(images[y]));
                y = y+1;
            }

        int y1 = 150;
        for(int x = 99; x > -50; x=x-1){ 
            images[y1] = new Image("/Image"+x+".jpg", true);
            imageview.add(new ImageView(images[y1]));      
            y1 = y1+1;
        }

        rootGroup.getChildren().addAll(imageview);

        int x = 0;

        timeline = new Timeline();  

        doAnimation();  

        primaryStage.setScene(scene);

        `primaryStage.show(); ` 
}
<code>  
public void doAnimation(){

    KeyFrame[] kf = new KeyFrame[images.length];     

    ImageView im = (ImageView)imageview.get(x);

<code>
    im.setImage(images[x]);

     kf[x] = new KeyFrame(Duration.millis(1), new KeyValue(im.opacityProperty(), 0));

     timeline.getKeyFrames().add(kf[x]);

     // When timeline animation is finished it executes the seetOnFinished Event


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

    @Override
    public void handle(ActionEvent event) {

        if( x == 298){
            System.out.println("VALUE OF x:"+x);
            x=0; -------> This is where code does not work When it reaches end of array and x initialize to 0 then animation stops.


            Collections.reverse(imageview);
            doAnimation();
        }

/* This if loop works fine animation iterates through 0 to 298 images. */                   
    if( x < 298){
        x++;
        doAnimation();
    }
    }
    });
    timeline.play();      

}

    /**
     * @param args the command line arguments
     */
public static void main(String[] args) {
    launch(args);
}

}

I have corrected my program and now I am not getting this error java.lang.IllegalArgumentException: Children: duplicate children.

But still the problem is I do not see program running on the screen. I have added root Group in scene but I see nothing on screen. My new Program:

public class Animation_Program_version3 extends Application {


    Timeline timeline = null;
    Group rootGroup = null;
    int x = 0;
    Image [] images = new Image[299];;
    ArrayList imageview = null;

    ImageView im = new ImageView();
    public Animation_Program_version3() {
  //      this.imageview = new TreeSet();
    }


@Override
public void start(Stage primaryStage) {

    primaryStage.setTitle("JavaFX Welcome");




rootGroup = new Group();

    final Scene scene =
         new Scene(rootGroup, 800, 400, Color.BEIGE);

//
     // final Scene scene =
     //    new Scene(rootGroup, 800, 400, Color.BEIGE);


  //   int x = 0;    
 //Image [] images = 
 imageview = new ArrayList();  





      int y = 0;
         for(int x = -50; x < 100; x=x+1){ 
           images[y] = new Image("/Image"+x+".jpg", true);
           imageview.add(new ImageView(images[y]));
          y = y+1;
      }

          int y1 = 150;
         for(int x = 99; x > -50; x=x-1){ 
           images[y1] = new Image("/Image"+x+".jpg", true);
 imageview.add(new ImageView(images[y1]));      

//    imageview[y1] = new ImageView(images[y1]);
          y1 = y1+1;
      }

//for (int i = 0; i < 299; i++) {
// rootGroup.getChildren().addAll(imageview);
//} 


int x = 0;

timeline = new Timeline();  




doAnimation();  

  primaryStage.setScene(scene);

primaryStage.show();  


}


public void doAnimation(){

 KeyFrame[] kf = new KeyFrame[images.length];     

 //  im = (ImageView)imageview.get(x);


   im.setImage(images[x]);


  rootGroup.getChildren().setAll(im);

     kf[x] = new KeyFrame(Duration.millis(1), new KeyValue(im.opacityProperty(), 0));

     timeline.getKeyFrames().add(kf[x]);


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

        @Override
        public void handle(ActionEvent event) {
               //     timeline = null;

                     if( x == 298){
                        System.out.println("VALUE OF x:"+x);
                        x=0;
                  //      Collections.reverse(imageview);
                    //    rootGroup.getChildren().setAll(imageview);
                     //  
                        doAnimation();
                    }

                    if( x < 298){
                        System.out.println("Inside 298 OF x:"+x);

                        x++;
                      //    Animation_Program_version3.rootGroup = null;
                   //     Animation_Program_version3.rootGroup = new Group();

                         doAnimation();
                    }
        }
    });
timeline.play();      


}

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

kf[x] = new KeyFrame(Duration.millis(10), new KeyValue(im.opacityProperty(), 1));

This piece of code does all the work. Here opacity goes from im.opacityProperty() which is 1 and goes to 1. So there is no fading out.

doAnimation() is recursive method and loops. We have used timeline animation to make animation smooth or else if i had used for loop then animation would flicker. This took me almost the month to make it work as I am no expert of animation used in JavaFx api.

The animation that i have done is similar to animated gif where you have series of images which when run one after another gives an animated effect.

The code still needs some work. In doAnimation() method, I have created array of KeyFrame: KeyFrame[] kf = new KeyFrame[images.length]; which i feel is not required.

Also there is no need to use Group class. I have used HBox to include ImageView. ImageView is being animated.

public class Animation_Program_version3 extends Application {

    Timeline timeline = null;
    Group rootGroup = null;
    int x = 0;
    Image [] images = new Image[299];;
    ArrayList imageview = null;

    ImageView im = new ImageView();
    public Animation_Program_version3() {
  //      this.imageview = new TreeSet();
    }


@Override
public void start(Stage primaryStage) {

    primaryStage.setTitle("JavaFX Welcome");




rootGroup = new Group();


//
     // final Scene scene =
     //    new Scene(rootGroup, 800, 400, Color.BEIGE);


  //   int x = 0;    
 //Image [] images = 
 imageview = new ArrayList();  





      int y = 0;
         for(int x = -50; x < 100; x=x+1){ 
           images[y] = new Image("/Image"+x+".jpg", true);
           imageview.add(new ImageView(images[y]));
          y = y+1;
      }

          int y1 = 150;
         for(int x = 99; x > -50; x=x-1){ 
           images[y1] = new Image("/Image"+x+".jpg", true);
 imageview.add(new ImageView(images[y1]));      

//    imageview[y1] = new ImageView(images[y1]);
          y1 = y1+1;
      }

//for (int i = 0; i < 299; i++) {
// rootGroup.getChildren().addAll(imageview);
//} 
  HBox layout2 = new HBox();
        layout2.getChildren().add(im);

 Scene scene =
         new Scene(layout2, 800, 400);

int x = 0;

timeline = new Timeline();  






  primaryStage.setScene(scene);

primaryStage.show();  
doAnimation();  

}


public void doAnimation(){

 KeyFrame[] kf = new KeyFrame[images.length];     

 //  im = (ImageView)imageview.get(x);

 System.out.println("WHAT IS THE VALUE OF:"+x);
   im.setImage(images[x]);
  System.out.println(images[x]);

 // rootGroup.getChildren().setAll(im);

     kf[x] = new KeyFrame(Duration.millis(10), new KeyValue(im.opacityProperty(), 1));

     timeline.getKeyFrames().add(kf[x]);


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

        @Override
        public void handle(ActionEvent event) {
               //     timeline = null;

                     if( x == 298){
                        System.out.println("VALUE OF x:"+x);
                        x=0;
                  //      Collections.reverse(imageview);
                    //    rootGroup.getChildren().setAll(imageview);
                     //  
                        doAnimation();
                    }

                    if( x < 298){
                        System.out.println("Inside 298 OF x:"+x);

                        x++;
                   //       im.setImage(images[x]);
                      //    Animation_Program_version3.rootGroup = null;
                   //     Animation_Program_version3.rootGroup = new Group();

                         doAnimation();
                    }
        }
    });
timeline.play();      


}

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM