I have a group with two circles on it, when I move one of them with a translate transition I should see the stationary one remain at the center(which is in the middle of the scene graph) and the other one move. Instead what happens is the "camera" follows the moving circle making it seem like they are both moving apart.
Is there a way to center the camera on 0,0 so that it remains there instead of following the circle?
import javafx.animation.Interpolator;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Test extends Application
{
public static void main(String[] args)
{
launch(args);
}
public void start(Stage stage)
{
BorderPane root = new BorderPane();
root.setStyle("-fx-background-color: Black");
Group graph = new Group();
root.setCenter(graph);
graph.setLayoutX(250);
graph.setLayoutY(250);
Circle circle = new Circle(0,0,5);
circle.setFill(Color.ORANGE);
graph.getChildren().add(circle);
Circle circle2 = new Circle(0, 0, 5);
circle2.setFill(Color.AQUA);
graph.getChildren().add(circle2);
TranslateTransition t = new TranslateTransition(Duration.millis(1000), circle);
t.setFromX(0);
t.setToX(100);
t.setFromY(0);
t.setToY(0);
t.setInterpolator(Interpolator.LINEAR);
t.play();
stage.setTitle("Circle Test");
stage.setScene((new Scene(root, 500, 500)));
stage.show();
}
}
To understand what is happening with the layout here, first note that the layout coordinates of the Group
graph
are ignored entirely, because you place graph
in a layout container (a BorderPane
). (Comment out the setLayoutX
and setLayoutY
lines and you will see they make no difference.) The layout container will size its child nodes according to 1. how much space it has for them, 2. the child nodes' min, preferred, and max sizes. Since the BorderPane
doesn't have any other child nodes in this example, it wants to allocate all its available space to the graph
. Since graph
is in the center, if there is space it cannot allocate to it, it will center it, leaving the rest of the space unused.
Group
s behave differently to Region
s (which include Control
s, Pane
s, and their subclasses): according to the documentation they are not resizable and take on the collective bounds of their children .
At the beginning of your animation, both circles are coincident, centered at (0,0)
and with radius 5
: so their bounding boxes (and consequently the bounding box of the Group
) has top left corner at (-5,-5)
and width and height of 10
. This square 10x10
bounding box cannot be made bigger (since it's a Group
, which is not resizable), and is centered on the screen. Since the BorderPane
has 500
pixels of total width available, there are 490
pixels of unused width, which are divided equally on either side of the Group
to center it: 245
to the left and 245
to the right. So the left edge of the Group
, which is the left edge of both the circles, is at x=245
in the BorderPane
coordinate system.
At the end of the animation, one circle remains at (-5,-5)
with width 10x10
, while the other has been translated 100
pixels to the right, so its bounding box extends from (95, -5)
to (105, 5)
. Consequently, the bounding box of the Group
, which takes on the collective bounds of its child nodes, has top left at (-5, -5)
, width 110
and height 10
. This box cannot be resized, so the BorderPane
's layout mechanism centers this box in the area it has available. Since the BorderPane
has a width of 500
pixels available, there are 390 unused pixels in width which are divided equally on either side: 195
on the left of the Group
and 195
on the right. So at this point, the left edge of the Group
, which is the left edge of the untranslated circle, is at x=195
in the BorderPane
coordinate system. Consequently, at the end of the animation, the untranslated circle has moved 50
pixels (half of the translation distance) to the left in the BorderPane
's coordinate system.
A more natural thing to do here is to use a Pane
instead of a Group
. A Pane
is resizable, so the BorderPane
will simply expand it to fill all the available space. Thus it will sit in the top left of the BorderPane
and fill the BorderPane
. The bounds of the Pane
start at (0,0)
and extend to its width and height. Thus if you simply change Group
to Pane
, the untranslated circle will not move during the animation, as you want.
However, the circles will now both start in the top left of the pane instead of the center. If you want them to start in the center, you can change the coordinates of the circles themselves, so they start centered at (250, 250)
:
import javafx.animation.Interpolator;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
BorderPane root = new BorderPane();
root.setStyle("-fx-background-color: Black");
Pane graph = new Pane();
root.setCenter(graph);
// graph.setLayoutX(250);
// graph.setLayoutY(250);
Circle circle = new Circle(250, 250, 5);
circle.setFill(Color.ORANGE);
graph.getChildren().add(circle);
Circle circle2 = new Circle(250, 250, 5);
circle2.setFill(Color.AQUA);
graph.getChildren().add(circle2);
TranslateTransition t = new TranslateTransition(Duration.millis(1000), circle);
t.setFromX(0);
t.setToX(100);
t.setFromY(0);
t.setToY(0);
t.setInterpolator(Interpolator.LINEAR);
t.play();
stage.setTitle("Circle Test");
stage.setScene((new Scene(root, 500, 500)));
stage.show();
}
}
As an alternative, you could use a Pane
as the root, instead of a BorderPane
. A plain Pane
doesn't do any layout, so in this case the layoutX
and layoutY
settings will take effect. Thus you can revert the centers of the circles to (0,0)
, and use the layout settings on graph
to center it:
import javafx.animation.Interpolator;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
Pane root = new Pane();
root.setStyle("-fx-background-color: Black");
Pane graph = new Pane();
root.getChildren().add(graph);
graph.setLayoutX(250);
graph.setLayoutY(250);
Circle circle = new Circle(0, 0, 5);
circle.setFill(Color.ORANGE);
graph.getChildren().add(circle);
Circle circle2 = new Circle(0, 0, 5);
circle2.setFill(Color.AQUA);
graph.getChildren().add(circle2);
TranslateTransition t = new TranslateTransition(Duration.millis(1000), circle);
t.setFromX(0);
t.setToX(100);
t.setFromY(0);
t.setToY(0);
t.setInterpolator(Interpolator.LINEAR);
t.play();
stage.setTitle("Circle Test");
stage.setScene((new Scene(root, 500, 500)));
stage.show();
}
}
You can change the class name to whatever you want.
The problem you had was that you added it through the setCenter()
method which automatically makes its center the center of the pane.
I hope this came in time.
import javafx.animation.Interpolator;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class NewClass extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
BorderPane root = new BorderPane();
root.setStyle("-fx-background-color: #efefef");
Group graph = new Group();
root.getChildren().add(graph);
graph.setLayoutX(250);
graph.setLayoutY(250);
Circle circle = new Circle(0, 0, 5);
circle.setFill(Color.ORANGE);
graph.getChildren().add(circle);
Circle circle2 = new Circle(0, 0, 5);
circle2.setFill(Color.AQUA);
graph.getChildren().add(circle2);
TranslateTransition t = new TranslateTransition(Duration.millis(1000), circle);
t.setFromX(0);
t.setToX(100);
t.setFromY(0);
t.setToY(0);
t.setInterpolator(Interpolator.LINEAR);
t.setCycleCount(5);
t.play();
stage.setTitle("Circle Test");
stage.setScene((new Scene(root, 500, 500)));
stage.show();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.