Issue
I'm animating some pictures. Animations of each of them are performed sequentially. The pictures are in the hbox, the coordinates of which I track through layoutX. At the end of each animation, I do a check. If the check is successful, then I delete some pictures. Moreover, the coordinates of others are shifted. Since transition was originally set in a loop (before all animations), animations (and recalculation of x) occur during animations, the result is bad. How can I solve this problem?
There are two hboxes (blue rectangles). They contain pictures (dark blue rectangles) that, when animated, beat a picture from another hbox. During the impact, some images may be deleted.
import javafx.animation.SequentialTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage stage) {
stage.setTitle("Есока");
Pane pane = new Pane();
stage.setScene(new Scene(pane,350,300));
HBox h1 = new HBox();
HBox h2 = new HBox();
h2.setAlignment(Pos.CENTER);
h2.setLayoutY(150);
h2.setPrefWidth(330);
pane.getChildren().addAll(h1, h2);
Rectangle r1 = new Rectangle(100, 100, Color.BLUE);
Rectangle r2 = new Rectangle(100, 100, Color.RED);
Rectangle r3 = new Rectangle(100, 100, Color.GREEN);
Rectangle r4 = new Rectangle(100, 100, Color.BLACK);
Rectangle r5 = new Rectangle(100, 100, Color.BROWN);
h1.setSpacing(10);
h2.setSpacing(10);
h1.getChildren().addAll(r1, r2, r3);
h2.getChildren().addAll(r4, r5);
pane.layout();
SequentialTransition st=new SequentialTransition();
for (int i = 0; i < 5; i++) {
int j1= (int) (Math.random()*h1.getChildren().size());
int j2= (int) (Math.random()*h2.getChildren().size());
TranslateTransition translateTransition=new TranslateTransition();
double x=h2.getChildren().get(j2).getLayoutX()-
h1.getChildren().get(j1).getLayoutX();
translateTransition.setByX(x);
double y=150;
translateTransition.setByY(y);
translateTransition.setAutoReverse(true);
translateTransition.setCycleCount(2);
translateTransition.setNode(h1.getChildren().get(j1));
translateTransition.setOnFinished(actionEvent -> {
if(Math.random()>0.5)h2.getChildren().remove(j2);
});
st.getChildren().add(translateTransition);
if(h1.getChildren().size()<=0|h2.getChildren().size()<=0)break;
}
st.setDelay(Duration.seconds(1));
st.play();
stage.show();
}
}
In this code, x is considered in a loop, and some images are deleted after, which is why the animation is incorrect. The problem is visible when the first object is removed (the "blow" trace goes to false coordinates).
Solution
It's not at all clear what you're trying to do, but you probably want to compute the next transition when the previous one finishes, instead of trying to compute them all at once.
public class Main extends Application {
private final Random rng = new Random();
private Pane pane;
private HBox h1;
private HBox h2;
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage stage) {
stage.setTitle("Есока");
pane = new Pane();
stage.setScene(new Scene(pane,350,300));
h1 = new HBox();
h2 = new HBox();
h2.setAlignment(Pos.CENTER);
h2.setLayoutY(150);
h2.setPrefWidth(330);
pane.getChildren().addAll(h1, h2);
Rectangle r1 = new Rectangle(100, 100, Color.BLUE);
Rectangle r2 = new Rectangle(100, 100, Color.RED);
Rectangle r3 = new Rectangle(100, 100, Color.GREEN);
Rectangle r4 = new Rectangle(100, 100, Color.BLACK);
Rectangle r5 = new Rectangle(100, 100, Color.BROWN);
h1.setSpacing(10);
h2.setSpacing(10);
h1.getChildren().addAll(r1, r2, r3);
h2.getChildren().addAll(r4, r5);
doAnimation();
stage.show();
}
private void doAnimation() {
pane.layout();
int j1= rng.nextInt(h1.getChildren().size());
int j2= rng.nextInt(h2.getChildren().size());
TranslateTransition translateTransition=new TranslateTransition();
double x=h2.getChildren().get(j2).getLayoutX()-
h1.getChildren().get(j1).getLayoutX();
translateTransition.setByX(x);
double y=150;
translateTransition.setByY(y);
translateTransition.setAutoReverse(true);
translateTransition.setCycleCount(2);
translateTransition.setNode(h1.getChildren().get(j1));
translateTransition.setOnFinished(actionEvent -> {
if(rng.nextBoolean()) {
h2.getChildren().remove(j2);
}
if (h2.getChildren().size() > 0) {
doAnimation();
}
});
translateTransition.play();
}
}
Answered By - James_D
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)