TranslateTransition 不改变 (X,Y) 坐标

TranslateTransition does not change (X,Y) co-ordinates

在学习 javafx.animation API 时,我尝试了以下代码, 它只是在 (100,100) 处绘制一个矩形,并在 2 秒内 将其翻译 为 (200,200)。

import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;

public class SimpleAnimation extends Application {

  @Override
  public void start(Stage stage) {
    Group root = new Group();
    Scene scene = new Scene(root, 500, 500);
    stage.setScene(scene);

    VBox vb = new VBox();

    Rectangle rect = new Rectangle (100, 100, 100, 100);
    rect.setArcHeight(50);
    rect.setArcWidth(50);
    rect.setFill(Color.VIOLET);

    final Duration SEC_2 = Duration.millis(2000);

    System.out.println("Location before relocation = "+rect.getX()+","+rect.getY()+")");

    TranslateTransition tt = new TranslateTransition(SEC_2,rect);
    tt.setByX(100f);
    tt.setByY(100f);
    tt.setOnFinished(new EventHandler<ActionEvent>() {
                       @Override
                       public void handle(ActionEvent event) {
                         System.out.println("Location after relocation = " + rect.getX() + "," + rect.getY() + ")");
                       }
                     });
    tt.play();

    vb.getChildren().add(rect);

        scene.setRoot(vb);
        stage.show();
      }

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

在这个 translationTransition 之后,矩形的 (x,y) 坐标应该是 (200,200) 对吗?
为了检查这一点,我尝试在 OnFinished() 事件处理程序中打印坐标。
不知道为什么它仍然打印 (100,100) ?

来自Javadocs

This Transition creates a move/translate animation that spans its duration. This is done by updating the translateX, translateY and translateZ variables of the node at regular interval.

因此,如果您在转换结束时检查 translateXtranslateY 属性,您会发现它们都等于 100;即矩形已从其原始位置在两个方向上平移了 100 个单位。

具体取决于您想要做什么,您可以使用 translateXtranslateY 属性,或者使用 boundsInParent 属性,这给出节点在其父坐标系中的边界(因此包括任何变换,例如平移)。

如果您希望 Rectanglexy 属性直接从动画中更改,请使用 Timeline,它允许您指定属性(或属性)变化:

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class SimpleAnimation extends Application {

    @Override
    public void start(Stage stage) {

        VBox vb = new VBox();

        Rectangle rect = new Rectangle(100, 100, 100, 100);
        rect.setManaged(false);
        rect.setArcHeight(50);
        rect.setArcWidth(50);
        rect.setFill(Color.VIOLET);

        final Duration SEC_2 = Duration.millis(2000);

        System.out.println("Location before relocation = " + rect.getX() + ","
                + rect.getY() + ")");

        Timeline timeline = new Timeline();

        KeyFrame end = new KeyFrame(SEC_2,
                new KeyValue(rect.xProperty(), 200),
                new KeyValue(rect.yProperty(), 200));

        timeline.getKeyFrames().add(end);

        timeline.setOnFinished(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("Location after relocation = " + rect.getX()
                        + "," + rect.getY() + ")");
            }
        });
        timeline.play();

        vb.getChildren().add(rect);

        Scene scene = new Scene(vb, 500, 500);
        stage.setScene(scene);

        stage.show();
    }

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

请注意,为了让它起作用,我添加了调用 rect.setManaged(false)。由于您在 VBox 中有 Rectangle,它管理其子节点的布局,因此更改 xy 属性将不会产生其他影响。 (另一种选择是将 VBox 替换为 Pane,它不管理其子节点的放置。)

动画完成后,将动画节点移动到平移坐标:

tt.setOnFinished(event -> {
    // The transition works by manipulating translation values,
    // After the transition is complete, move the node to the new location
    // and zero the translation after relocating the node.
    rect.setX(rect.getX() + rect.getTranslateX());
    rect.setY(rect.getY() + rect.getTranslateY());
    rect.setTranslateX(0);
    rect.setTranslateY(0);
});

此外,您将 Rectangle 放在 VBox 中,如果您希望矩形的 X&Y 坐标具有任何意义,请不要这样做。 VBox 是一个布局管理器,会忽略矩形的 X 和 Y 坐标(因为它会使内部的所有内容垂直布局)。而是在不执行布局的父级(例如组或窗格)中执行动画。

可执行示例:

import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class SimpleAnimation extends Application {

    @Override
    public void start(Stage stage) {
        Rectangle rect = new Rectangle(100, 100, 100, 100);
        rect.setArcHeight(50);
        rect.setArcWidth(50);
        rect.setFill(Color.VIOLET);

        System.out.println("Location before relocation = " + rect.getX() + "," + rect.getY() + ")");

        TranslateTransition tt = new TranslateTransition(
              Duration.seconds(2), 
              rect
        );

        tt.setByX(100f);
        tt.setByY(100f);
        tt.setOnFinished(event -> {
            rect.setX(rect.getX() + rect.getTranslateX());
            rect.setY(rect.getY() + rect.getTranslateY());
            rect.setTranslateX(0);
            rect.setTranslateY(0);

            System.out.println("Location after relocation = " + rect.getX() + "," + rect.getY() + ")");
        });

        tt.play();

        Scene scene = new Scene(new Group(rect), 500, 500);
        stage.setScene(scene);

        stage.show();
    }

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