-3

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?

enter image description here

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).

  • 1
    This is incomprehensible. Create and post a [mre]. Didn't you already ask this question? – James_D Aug 03 '22 at 13:29
  • It seems like you should be starting the next transition from the previous transition’s `onFinished` handler, instead of trying to compute the entire process in a `SequentialTransition`. But the question really isn’t clear enough (to me, at least) to be able to answer it. – James_D Aug 03 '22 at 14:13
  • @James_D: I recall it, too. Slaw's comment [here](https://stackoverflow.com/q/73190823/230513) seemed dispositive: "You have to pause/stop the animation, set the new values, and then play the animation again." – trashgod Aug 03 '22 at 14:19
  • @James_D That question was closed, and I do not know how to open it (I am new to the site), so I created a new one, but slightly modified – Oleg Boldov Aug 03 '22 at 14:20
  • If it was closed the first time, why do you think it will not be closed the second time? By deleting and reposting, you delete all the comments that were on the first version of the question. None of this really makes any sense anyway. On each transition, you delete one of the rectangles in the lower `HBox` with probability 1/2, so it’s perfectly feasible that there is nothing in that `HBox` after the first two transitions. What are the remaining three transitions supposed to do in that case? – James_D Aug 03 '22 at 14:25
  • @James_D I could easily solve this problem in my program. In any case, I have supplemented this code so that this does not occur. My problem is the dynamic calculation of the X coordinate (after the first removal of the rectangle, all other animations go badly). – Oleg Boldov Aug 03 '22 at 14:35
  • But you haven't fixed the problem at all. `h1.getChildren().size()` is `3` every time you call it, and `h2.getChildren().size()` is `2` every time you call it, because nothing is removed until the `TranslateTransition`s finish. My point is it's completely unclear what you're trying to do here. As I said in a previous comment, you probably want to compute (and start) the next transition when the previous one finishes, instead of using a `SequentialTransition`. – James_D Aug 03 '22 at 14:54
  • @James_D Wouldn't such a program be slow. If we assume that the animation is complex, then the computer will stop every time, before each new animation, instead of somehow calculating everything at once. I'm wondering if it's possible to calculate the coordinates for such a task right away? – Oleg Boldov Aug 03 '22 at 15:23
  • 1
    *"If we assume that the animation is complex, then the computer will stop every time, before each new animation"* What do you mean? – James_D Aug 03 '22 at 15:24
  • *" I'm wondering if it's possible to calculate the coordinates for such a task right away?"*. In this example, possibly, though it would be complex. I think you would need to manage the layout yourself, so you can accurately calculate the position of the rectangles given an arbitrary layout. Then create the transitions in a loop, keeping track of the random values you create, so you can calculate the layout coordinates for each transition based on what happened in previous transitions. I don't know if you can do that in your real application or not; if it, e.g., depends on user input, then no. – James_D Aug 03 '22 at 15:54
  • 1
    __DO NOT__ repost a question - instead, edit the previous https://stackoverflow.com/questions/73190823/how-can-i-dynamically-change-coordinates-for-animation to make it answerable – kleopatra Aug 03 '22 at 16:03
  • I just thought that since the animation is rendered at the end of the previous one, the computer will need time between animations to process. If the animation is complicated, then these pauses will be too long. @James_D – Oleg Boldov Aug 03 '22 at 18:39
  • How long do you expect it to take? Presumably you're not connecting to a database or parsing some huge file to compute the next transition? (If so, you can surely avoid that by doing the heavy work ahead of time, but still referencing the results to start the new transition.) Doesn't the code in the answer work? – James_D Aug 03 '22 at 18:43
  • 1
    the code works, thanks! @James_D – Oleg Boldov Aug 03 '22 at 18:50

1 Answers1

1

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();
    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322