Reputation: 35
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
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);
}
}
Upvotes: 2