JavaFX - 动画没有正确循环

时间:2016-06-07 09:56:53

标签: java animation javafx

我目前正在尝试制作这个Java动画循环: http://docs.oracle.com/javafx/2/get_started/ColorfulCircles.java.html

总结一下:程序创建圆圈,这些圆圈从生成的起始点以X轴和Y轴漂移到生成的位置,该位置也有X轴和Y轴。 现在,在他们完成了到达结尾的路径之后,while循环中的一个新循环将开始,但这次圆圈将从他们的最后一个结束点(他们的新起点)开始,并且只生成一个新的结束点,所以它看起来就像他们从过去的目的地漫步到另一个目的地。

我的问题是坐标是正确的,但是我的圆圈在错误的位置产生。 这是我的程序的一个小输出:

//First loop with only 3 circles as example
0 StartX: 1110.2994232832264 StartY: 196.5353444146038
0 StartX: 1110.2994232832264 StartY: 196.5353444146038 EndeX: 77.09550167412587 EndeY: 781.9152623844685

1 StartX: 1026.967733288605 StartY: 228.60184379870438
1 StartX: 1026.967733288605 StartY: 228.60184379870438 EndeX: 1495.5868225131878 EndeY: 43.10288101605459

2 StartX: 909.8816160887294 StartY: 599.8395576620894
2 StartX: 909.8816160887294 StartY: 599.8395576620894 EndeX: 739.8188739717103 EndeY: 748.576558089626

3 StartX: 546.8538353648784 StartY: 211.33686550731284
3 StartX: 546.8538353648784 StartY: 211.33686550731284 EndeX: 465.06241304615554 EndeY: 676.2487115928532


//Second loop with the same 3 circles as before
0 StartX: 77.09550167412587 StartY: 781.9152623844685
0 StartX: 77.09550167412587 StartY: 781.9152623844685 EndeX: 609.5200149154447 EndeY: 600.3577965697156

1 StartX: 1495.5868225131878 StartY: 43.10288101605459
1 StartX: 1495.5868225131878 StartY: 43.10288101605459 EndeX: 727.4914318763049 EndeY: 609.0004943773514

2 StartX: 739.8188739717103 StartY: 748.576558089626
2 StartX: 739.8188739717103 StartY: 748.576558089626 EndeX: 435.20715512004284 EndeY: 491.23845197656414

3 StartX: 465.06241304615554 StartY: 676.2487115928532
3 StartX: 465.06241304615554 StartY: 676.2487115928532 EndeX: 1241.2695042799824 EndeY: 400.8279035402024

每一行开头的数字是圆圈的标识符,StartX和StartY是这些圆圈开始的坐标,EndeX和EndeY是这些圆圈漂移的坐标。

正如您所见,圆圈'0'在坐标EndeX: 77.09550167412587 EndeY: 781.9152623844685处停止,并从下一循环中的坐标0 StartX: 77.09550167412587 StartY: 781.9152623844685开始,所以基本上动画应完美循环,但它不会,它会出现圈子仍然在随机位置产生......

这是我的首发课程:

import static java.lang.Math.random;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.BlendMode;
import javafx.scene.effect.BoxBlur;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application
{
    public static void main(String[] args)
    {
        launch(args);
    }




    public static Timeline timeline = new Timeline();
    public static Group circles = new Group();
    @Override
    public void start(Stage primaryStage) {
        Group root = new Group();
        Scene scene = new Scene(root, 1500, 850, Color.BLACK);
        primaryStage.setScene(scene);
        for (int i = 0; i < 15; i++) {
            Circle circle = new Circle(150, Color.web("white", 0.05));
            circle.setStrokeType(StrokeType.OUTSIDE);
            circle.setStroke(Color.web("white", 0.16));
            circle.setStrokeWidth(4);
            circles.getChildren().add(circle);
        }

        Thread t1 = new Thread(new Random());
        Rectangle colors = new Rectangle(scene.getWidth(), scene.getHeight(),
            new LinearGradient(0f, 1f, 1f, 0f, true, CycleMethod.NO_CYCLE, new Stop[]{
                new Stop(0, Color.web("#f8bd55")),
                new Stop(0.14, Color.web("#c0fe56")),
                new Stop(0.28, Color.web("#5dfbc1")),
                new Stop(0.43, Color.web("#64c2f8")),
                new Stop(0.57, Color.web("#be4af7")),
                new Stop(0.71, Color.web("#ed5fc2")),
                new Stop(0.85, Color.web("#ef504c")),
                new Stop(1, Color.web("#f2660f")),}));
    colors.widthProperty().bind(scene.widthProperty());
    colors.heightProperty().bind(scene.heightProperty());
    Group blendModeGroup =
            new Group(new Group(new Rectangle(scene.getWidth(), scene.getHeight(),
                 Color.BLACK), circles), colors);
    colors.setBlendMode(BlendMode.OVERLAY);
    root.getChildren().add(blendModeGroup);      
    circles.setEffect(new BoxBlur(10, 10, 3));

    t1.start();
    // play 40s of animation
    primaryStage.show();
}
}

和我的班级,我在其中生成圆圈运动:

import static java.lang.Math.random;

import java.util.ArrayList;
import java.util.List;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.scene.Node;
import javafx.util.Duration;

public class Random implements Runnable
{

public void run()
{
    Main main = new Main();

    Double[] startingPositionX = new Double[15];
    Double[] startingPositionY = new Double[15];

    boolean firstRun = true;
        while(true)
        {

            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e1)
            {
                System.out.println("Exception");
            }

            int i = 0;
        for (Node circle : main.circles.getChildren()) {

            Double startingPositionXNumber = 0.00;
            Double startingPositionYNumber = 0.00;

            if(firstRun)
            {
                startingPositionXNumber = random() * 1500;
                startingPositionYNumber = random() * 850;
            }
            else
            {
                startingPositionXNumber = startingPositionX[i];
                startingPositionYNumber = startingPositionY[i];

                System.out.println(i + " StartX: " + startingPositionXNumber + " StartY: " + startingPositionYNumber);
            }


            Double endingPositionXNumber = random() * 1500;
            Double endingPositionYNumber = random() * 850;

            main.timeline.getKeyFrames().addAll(
                    new KeyFrame(Duration.ZERO, // set start position at 0
                    new KeyValue(circle.translateXProperty(), startingPositionXNumber),
                    new KeyValue(circle.translateYProperty(), startingPositionYNumber)),
                    new KeyFrame(new Duration(10000), // set end position at 10s
                    new KeyValue(circle.translateXProperty(), endingPositionXNumber),
                    new KeyValue(circle.translateYProperty(), endingPositionYNumber)));

            startingPositionX[i] = endingPositionXNumber;
            startingPositionY[i] = endingPositionYNumber;

            System.out.println(i + " StartX: " + startingPositionXNumber + " StartY: " + startingPositionYNumber + " EndeX: " + endingPositionXNumber + " EndeY: " + endingPositionYNumber);
            i++;
        }

        System.out.println("For each was completed.");
        firstRun = false;
        main.timeline.play();

        try
        {
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
}
}

1 个答案:

答案 0 :(得分:0)

尝试使用起始值删除零KeyFrame。我猜,可能有问题。您的圈子将在第一次运行时从相同的位置开始,但不要担心它只是出于调试原因。

main.timeline.getKeyFrames().addAll(
                    new KeyFrame(new Duration(10000), // set end position at 10s
                    new KeyValue(circle.translateXProperty(), endingPositionXNumber),
                    new KeyValue(circle.translateYProperty(), endingPositionYNumber)));

可悲的是,我现在无法运行您的代码(在工作中),但如果找不到解决方案,我可以稍后在家查看。

此外,您的代码无法保存以免重新排序getChildren()列表中的圈子节点。更好的方法是使用translateXProperty(和Y)而不是数组。因为这些属性正在为您保存最后一个翻译。 (这就是为什么,删除零KeyFrame应该工作)