问题
While learning the javafx.animation API, I tried the following code, which simply draws a rectangle at (100,100) and translates it to (200,200) in 2 seconds.
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);
}
}
After this translationTransition, the rectangle is expected to have the (x,y) coordinates as (200,200) right?
To check this, I tried to print the coordinates in the OnFinished() event handler.
Don't know why it still prints (100,100) ?

回答1:
From the 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.
So if you check the translateX
and translateY
properties at the end of the transition, you will find they are both equal to 100
; i.e. the rectangle has been translated from its original position by 100
units in both directions.
Depending on exactly what you are wanting to do, you can either work with the translateX
and translateY
properties, or work with the boundsInParent property, which gives the bounds of a node in its parent's coordinate system (and thus includes any transforms, such as the translation).
If you prefer to have the x
and y
properties of the Rectangle
change directly from the animation, use a Timeline, which allows you to specify the property (or properties) that change:
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);
}
}
Note that for this to work, I added the call rect.setManaged(false)
. Since you have the Rectangle
in a VBox
, which manages layout of its child nodes, changing the x
and y
properties will have no effect otherwise. (The other option would be to replace the VBox
with a Pane
, which doesn't manage placement of its child nodes.)
回答2:
When the animation is finished, move the animated node to the translation co-ordinates:
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);
});
Also you place your Rectangle in a VBox, don't do that if you want the X&Y co-ordinates of the rectangle to mean anything. A VBox is a layout manager and will ignore X&Y co-ordinates of the rectangle (because it will make everything inside it layout vertically). Instead perform your animation in a Parent which does not perform layout (e.g. a Group or a Pane).
Executable sample:
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);
}
}
来源:https://stackoverflow.com/questions/30338598/translatetransition-does-not-change-x-y-co-ordinates