Java 如何执行连续动画

Java 如何执行连续动画,java,animation,javafx,Java,Animation,Javafx,我正在用javaFX创建一个基本的动画,我有5个矩形排成一行,我有两个圆环,红色和蓝色。红色圆环设置在第一个矩形上,蓝色圆环设置在第五个矩形上。 这个想法是:如果我点击第一个矩形,我希望红色的圆圈移动到第五个矩形(通过平移),一旦到达,蓝色的矩形(在第五个矩形上)移动到第一个,换句话说,它们交换位置。我在逻辑中使用了AnimationTimer类,但问题是当pressedMouse事件发生时,两个Cirlce的动画是同步的,这不是我想要的,我想要的是蓝色圆圈的动画在红色圆圈的动画完成后开始。我想

我正在用javaFX创建一个基本的动画,我有5个矩形排成一行,我有两个圆环,红色和蓝色。红色圆环设置在第一个矩形上,蓝色圆环设置在第五个矩形上。 这个想法是:如果我点击第一个矩形,我希望红色的圆圈移动到第五个矩形(通过平移),一旦到达,蓝色的矩形(在第五个矩形上)移动到第一个,换句话说,它们交换位置。我在逻辑中使用了AnimationTimer类,但问题是当pressedMouse事件发生时,两个Cirlce的动画是同步的,这不是我想要的,我想要的是蓝色圆圈的动画在红色圆圈的动画完成后开始。我想知道为什么会这样?是不是有点多线程?如果是这样的话,当我运行程序时,红色圆圈被卡在中间,但是蓝色的圆圈会跳出边界并隐藏,但是如果我评论一个CurlCE的位置代码更新(更新方法),应用程序运行正常,我希望我得到一个答案,我非常感激。 另一个问题是:如何使我的动画看起来更平滑,因为它会停止几分之一秒,然后再次移动

这是我的密码:

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;  

public class animation extends Application {
        
        AnchorPane root = new AnchorPane();
        
        //create a matrix from rectangle class to stock 5 rectangle objects
        rectangle rect [] = new rectangle [5];
        
        //isMoving gets the true value when the animation starts
        private boolean isMoving = false;
        
        private int traveledDistance = 30;
    @Override
    public void start(Stage primaryStage) {

        //add 5 rectangles on the anchorpane
        //rect[0], rect[2] and rect[4] have BURLYWOOD color
        //rect[1], rect[3] have DARKBLUE color
        for(int i = 0; i<5; i++)
        {
            
           if(i%2 == 0)
            {
             rect[i] = new rectangle();
             rect[i].setFill(Color.BURLYWOOD);
                       
            }
            else
            {
                rect[i] = new rectangle();
                rect[i].setFill(Color.DARKBLUE);
            }
             //set all 5 rectangles as empty
             rect[i].setRectEmpty(true);
             //set all the 5 rectangles one after the other along the x axis
             rect[i].setTranslateX(i*60);
             //add the 5 rectangles to the parent 
             root.getChildren().add(rect[i]);
        }
        //instantiation of two circles (c and d) from cirlce class
        circle c = new circle(Color.RED);
        c.setName("redCircle");
        
        circle d = new circle(Color.BLUE);
        d.setName("blueCircle");
        
        //set the position of the red circle centered relatively to rect[0] 
        //rect[0] is no longer empty as it contains the red circle
        c.setTranslateX(30);
        c.setTranslateY(30);
        rect[0].setCircle(c);
        rect[0].setCircleName(c.getName());
        rect[0].setRectEmpty(false);
        root.getChildren().add(c);
        
        //set the position of the blue circle centered relatively to rect[4] 
        d.setTranslateX(4*60 +30);
        d.setTranslateY(30);
        rect[4].setCircle(d);
        rect[4].setCircleName(d.getName());
        root.getChildren().add(d);
        displayedScene(primaryStage);
        
        //when the parent is clicked
        root.setOnMousePressed(new EventHandler<MouseEvent>(){
            @Override
            public void handle(MouseEvent event) {
                //get the index of the clicked rectangle
                int index = (int) event.getX()/60;
                //if the clicked rectangle contains the red circle inside
                if(!rect[index].isRectEmpty() && rect[index].getCircleName().equals("redCircle"))
                {
                    Circle circle = rect[index].getCircle();
                    //update the postion of the red circle so that it occupies the last rectangle (rect[4])
                        update(index,5, circle);
                    //update the position of the blue circle so that it occupies the first rectangle(rect[0])
                        update(5,0, rect[4].getCircle());
                       
                }
            }               
                    
        });       
    }
    
    //update method uses the AnimationTimer class
    public void update(int initialPos, int lastPos, Circle circle)
    {
       AnimationTimer timer = new AnimationTimer() {
       @Override
       public void handle(long now) {
             
           updateCirclePosition(initialPos, lastPos, circle);
           if(!isMoving)
           {
               this.stop();
           }   
        }
        };
        timer.start();
    }
 
    public void updateCirclePosition(int initialPos, int lastPos, Circle circle)
    {
       int dx = 2;
       if(initialPos>lastPos)
       {
           dx = -1*dx;
       }
       isMoving = true;
       int distance = Math.abs((lastPos - initialPos)*60);
       
       if(traveledDistance<distance-30)
       {
          circle.setTranslateX(circle.getTranslateX() + dx); 
          traveledDistance +=Math.abs(dx);
       }
       else{
           isMoving = false;
           traveledDistance = 30;
       }
    }
     
    //load the Stage
    public void displayedScene(Stage primaryStage)
    {
      Scene scene = new Scene(root, 300, 60);
        primaryStage.setScene(scene);
        primaryStage.show();
        
    }
    public static void main(String[] args) {
        launch(args);
    }
   // circle class extends Circle
    
        public class circle extends Circle
    {
        private String name;
        public circle(Paint color) {
            
            super(30, color);             
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }       
    }
}

以下是一个mre,演示了所请求的功能。
圆形动画由
animateCircles()
完成。它使用
TranslateTransition
将圆从一个位置平移到另一个位置。
用于启动下一个动画。

import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Animation extends Application {

    private static final double SQUARE_SIZE = 60, RADIUS = SQUARE_SIZE /2, ANIMATION_TIME = 1;
    private final Pane root = new Pane();
    private final Rectangle rect [] = new Rectangle [5];
    private final Circle circles [] = new Circle[2];
    private boolean isMoving = false, isSwapped = false;

    @Override
    public void start(Stage primaryStage) {

        for(int i = 0; i<rect.length; i++) {
            rect[i] = new Rectangle(SQUARE_SIZE, SQUARE_SIZE, i%2 == 0 ? Color.BURLYWOOD :  Color.DARKBLUE);
            //set all the 5 rectangles one after the other along the x axis
            rect[i].setTranslateX(i*SQUARE_SIZE);
            root.getChildren().add(rect[i]);
        }

        circles[0] = new Circle(RADIUS,Color.RED);
        circles[1] = new Circle(RADIUS,Color.BLUE);

        //set the position of the red circle centered to rect[0]
        Point2D center = centerOf(rect[0]);
        circles[0].setTranslateX(center.getX());
        circles[0].setTranslateY(center.getY());

        //set the position of the blue circle centered  to rect[4]
        center = centerOf(rect[4]);
        circles[1].setTranslateX(center.getX());
        circles[1].setTranslateY(center.getY());

        root.getChildren().add(circles[0]);
        root.getChildren().add( circles[1]);

        Scene scene = new Scene(root, SQUARE_SIZE*rect.length, SQUARE_SIZE);
        primaryStage.setScene(scene);
        primaryStage.show();

        root.setOnMousePressed(event -> animateCircles());
    }

    //return the center point 
    private Point2D centerOf(Rectangle rect) {
        Bounds bounds = rect.getBoundsInParent();
        double x = bounds.getMinX() + 0.5 * bounds.getWidth();
        double y = bounds.getMinY() + 0.5 * bounds.getHeight();
        return new Point2D(x, y);
    }

    private void animateCircles() {

        if(isMoving) return;

        TranslateTransition translateCircle0 = new TranslateTransition(Duration.seconds(ANIMATION_TIME), circles[0]);
        translateCircle0.setToX( isSwapped ?  centerOf(rect[0]).getX()  : centerOf(rect[4]).getX());

        TranslateTransition translateCircle1 = new TranslateTransition(Duration.seconds(ANIMATION_TIME), circles[1]);
        translateCircle1.setToX( isSwapped ?  centerOf(rect[4]).getX() : centerOf(rect[0]).getX());

        translateCircle0.setOnFinished(e-> {
            translateCircle1.play();
        });

        translateCircle1.setOnFinished(e-> {
            isMoving = false;
            isSwapped = ! isSwapped;
        });

        isMoving = true;
        translateCircle0.play();
    }

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

这听起来像是一个更好的选择;只需添加适当的关键帧。但是你也可以想出一种方法,当你停止第一个动画定时器时,第二次调用update。在
顺序转换中使用两个
TranslateTransition
似乎就是你要找的。java命名约定请你这么高兴,兄弟!这对我来说非常有效!我还有一个问题:“return”在if语句条件之后代表什么?
return
意味着停止方法的执行并返回到调用它的位置如果(正在移动)返回;`表示如果
isMoving
为true,则不要继续。它非常类似于
return5
返回true
但不返回任何值。
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Animation extends Application {

    private static final double SQUARE_SIZE = 60, RADIUS = SQUARE_SIZE /2, ANIMATION_TIME = 1;
    private final Pane root = new Pane();
    private final Rectangle rect [] = new Rectangle [5];
    private final Circle circles [] = new Circle[2];
    private boolean isMoving = false, isSwapped = false;

    @Override
    public void start(Stage primaryStage) {

        for(int i = 0; i<rect.length; i++) {
            rect[i] = new Rectangle(SQUARE_SIZE, SQUARE_SIZE, i%2 == 0 ? Color.BURLYWOOD :  Color.DARKBLUE);
            //set all the 5 rectangles one after the other along the x axis
            rect[i].setTranslateX(i*SQUARE_SIZE);
            root.getChildren().add(rect[i]);
        }

        circles[0] = new Circle(RADIUS,Color.RED);
        circles[1] = new Circle(RADIUS,Color.BLUE);

        //set the position of the red circle centered to rect[0]
        Point2D center = centerOf(rect[0]);
        circles[0].setTranslateX(center.getX());
        circles[0].setTranslateY(center.getY());

        //set the position of the blue circle centered  to rect[4]
        center = centerOf(rect[4]);
        circles[1].setTranslateX(center.getX());
        circles[1].setTranslateY(center.getY());

        root.getChildren().add(circles[0]);
        root.getChildren().add( circles[1]);

        Scene scene = new Scene(root, SQUARE_SIZE*rect.length, SQUARE_SIZE);
        primaryStage.setScene(scene);
        primaryStage.show();

        root.setOnMousePressed(event -> animateCircles());
    }

    //return the center point 
    private Point2D centerOf(Rectangle rect) {
        Bounds bounds = rect.getBoundsInParent();
        double x = bounds.getMinX() + 0.5 * bounds.getWidth();
        double y = bounds.getMinY() + 0.5 * bounds.getHeight();
        return new Point2D(x, y);
    }

    private void animateCircles() {

        if(isMoving) return;

        TranslateTransition translateCircle0 = new TranslateTransition(Duration.seconds(ANIMATION_TIME), circles[0]);
        translateCircle0.setToX( isSwapped ?  centerOf(rect[0]).getX()  : centerOf(rect[4]).getX());

        TranslateTransition translateCircle1 = new TranslateTransition(Duration.seconds(ANIMATION_TIME), circles[1]);
        translateCircle1.setToX( isSwapped ?  centerOf(rect[4]).getX() : centerOf(rect[0]).getX());

        translateCircle0.setOnFinished(e-> {
            translateCircle1.play();
        });

        translateCircle1.setOnFinished(e-> {
            isMoving = false;
            isSwapped = ! isSwapped;
        });

        isMoving = true;
        translateCircle0.play();
    }

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

    if(isMoving) return;

    TranslateTransition translateCircle0 = new TranslateTransition(Duration.seconds(ANIMATION_TIME), circles[0]);
    translateCircle0.setToX( isSwapped ?  centerOf(rect[0]).getX()  : centerOf(rect[4]).getX());

    TranslateTransition translateCircle1 = new TranslateTransition(Duration.seconds(ANIMATION_TIME), circles[1]);
    translateCircle1.setToX( isSwapped ?  centerOf(rect[4]).getX() : centerOf(rect[0]).getX());

    SequentialTransition sequentialTransition = new SequentialTransition(translateCircle0, translateCircle1);
    isMoving = true;
    sequentialTransition.play();
    sequentialTransition.setOnFinished(e-> {
        isMoving = false;
        isSwapped = ! isSwapped;
    });
}