【问题标题】:JavaFX - Animation is not looping properlyJavaFX - 动画没有正确循环
【发布时间】:2016-06-07 09:56:53
【问题描述】:

我目前正在尝试制作这个 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();
        }
        }
}
}

【问题讨论】:

  • 不要在另一个线程中使用 while 循环,只需在时间轴上使用 onFinished handler 即可在完成后立即重新启动它。

标签: java animation javafx


【解决方案1】:

尝试用起始值移除零 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 应该可以工作)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 2021-09-23
    • 2023-03-21
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    相关资源
    最近更新 更多