How to use AnimationTimer?

So, I've tried to creat cardioid type of shapes with clean animation by using JavaFX. Here is my code:

public class Main extends Application {
    ArrayList<Circle> circles = new ArrayList<>();
    ArrayList<Line> lines = new ArrayList<>();
    Group g;
    int counter = 0;
    int factor = 1;
    int total = 100;
    int j = 0;
    static AnimationTimer draw;
    static AnimationTimer deleteLines;

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

    @Override
    public void start(Stage primaryStage) {
        g = new Group();
        Scene s = new Scene(g, 600, 600);
        s.setFill(Color.BLACK);
        primaryStage.setScene(s);
        primaryStage.show();

        Circle c = new Circle(300, 300,300);
        c.setFill(Color.BLACK);
        c.setStroke(Color.BLACK);
        drawCircle(g);
        g.getChildren().addAll(c);

        draw = new AnimationTimer(){
            @Override
            public void handle(long now) {

                if(counter == total){
                    total++;
                    counter = 0;
                    deleteLines.start();
                    lines.clear();
                    g.getChildren().removeAll(circles);
                    circles.clear();
                    factor++;
                    drawCircle(g);
                } else {
                    drawLines(g);
                    counter++;
                }
            }
        };
        deleteLines = new AnimationTimer() {
            @Override
            public void handle(long now) {
                if (j < lines.size()){
                    draw.stop();
                    g.getChildren().removeIf(node -> node == lines.get(j));
                    j++;
                } else {
                    j = 0;
                    this.stop();
                    draw.start();
                }
            }
        };
        draw.start();
    }

    private void drawLines(Group g) {
        for (int i = 0; i < total; i++) {
            Line l = new Line(circles.get(counter % total).getCenterX(), circles.get(counter % total).getCenterY(), circles.get(counter * factor % total).getCenterX(), circles.get(counter * factor % total).getCenterY());
            l.setStroke(Color.PURPLE);
            g.getChildren().add(l);
            lines.add(l);
        }
    }

    private void drawCircle(Group g) {
        for (int i = 0; i < total; i++) {
            Circle dot = new Circle(Math.cos(2*Math.PI/ total * i + Math.PI / 2)* 300 + 300,Math.sin(2*Math.PI/ total * i + Math.PI / 2 )* 300 + 300, 5);
            dot.setFill(Color.PURPLE);
            circles.add(dot);
        }
        g.getChildren().addAll(circles);
    }
}

My aim was that display all the lines with one by one and than delete them compeletely one by one again (I did it with

 g.getChildren().removeAll(lines); 

but that is not what I want). So, here is my problem:

deleteLines = new AnimationTimer() {
        @Override
        public void handle(long now) {
            if (j < lines.size()){
                draw.stop();
                g.getChildren().removeIf(node -> node == lines.get(j));
                j++;
            } else {
                j = 0;
                this.stop();
                draw.start();
            }
        }
    };

In this part,

 g.getChildren().removeIf(node -> node == lines.get(j));

is working. It removes only from the root not on the screen and I want to know why.

Upvotes: 0

Views: 546

Answers (1)

c0der
c0der

Reputation: 18792

I think the following does what you wanted. Note the comments:

import java.util.ArrayList;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class Main extends Application {

    private final ArrayList<Circle> circles = new ArrayList<>();
    private final ArrayList<Line>lines = new ArrayList<>();
    private int counter = 0,  total = 100;
    private int factor = 2; //factor 1 does not draw lines
    private int deletedLinesCounter = 0; //j is not a good choice of name
    private AnimationTimer draw, deleteLines; //why static ?

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

    @Override
    public void start(Stage primaryStage) {

        Group g = new Group();
        Scene s = new Scene(g, 600, 600);
        s.setFill(Color.BLACK);
        primaryStage.setScene(s);
        primaryStage.show();

        //not needed
        //Circle c = new Circle(300, 300,300);
        //c.setFill(Color.BLACK);
        //c.setStroke(Color.BLACK);
        //g.getChildren().add(c);

        drawCircle(g);

        draw = new AnimationTimer(){
            @Override
            public void handle(long now) {

                if(counter == total){
                    deleteLines.start();
                    stop(); //stop draw until it restarts by deleteLines
                } else {
                    drawLine(g);    // drawLines(g);
                    counter++;
                }
            }
        };

        deleteLines = new AnimationTimer() {
            @Override
            public void handle(long now) {
                if (deletedLinesCounter < lines.size()){
                    //draw.stop();  // no need to stop over again. stop in draw
                    g.getChildren().removeIf(node -> node == lines.get(deletedLinesCounter));
                    deletedLinesCounter++;
                } else {
                    //prepare next draw
                    total++;
                    counter = 0;
                    factor++;
                    deletedLinesCounter = 0;
                    lines.clear();
                    g.getChildren().removeAll(circles);
                    circles.clear();
                    drawCircle(g);
                    stop();
                    draw.start();
                }
            }
        };

        draw.start();
    }

    private void drawLine(Group g) {

        Line l = new Line(circles.get(counter % total).getCenterX(),
                circles.get(counter % total).getCenterY(),
                circles.get(counter * factor % total).getCenterX(),
                circles.get(counter * factor % total).getCenterY());
        l.setStroke(Color.PURPLE);
        g.getChildren().add(l);
        lines.add(l);
    }

    //this method only keeps adding the same line total times
    //      private void drawLines(Group g) {
    //          for (int i = 0; i < total; i++) {
    //              Line l = new Line(circles.get(counter % total).getCenterX(),
    //                                  circles.get(counter % total).getCenterY(),
    //                                  circles.get(counter * factor % total).getCenterX(),
    //                                  circles.get(counter * factor % total).getCenterY());
    //              l.setStroke(Color.PURPLE);
    //              g.getChildren().add(l);
    //              lines.add(l);
    //          }
    //      }

    private void drawCircle(Group g) {
        for (int i = 0; i < total; i++) {
            Circle dot = new Circle(Math.cos(2*Math.PI/ total * i + Math.PI / 2)* 300 + 300,
                    Math.sin(2*Math.PI/ total * i + Math.PI / 2 )* 300 + 300, 5);
            dot.setFill(Color.PURPLE);
            circles.add(dot);
        }
        g.getChildren().addAll(circles);
    }
}

enter image description here

Upvotes: 2

Related Questions