有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何居中javafx场景图“摄影机”

我有一个有两个圆圈的组,当我移动其中的一个圆圈时,我应该看到静止的一个留在中心(在场景图的中间),另一个移动。相反,它们“让相机看起来像是在移动”

有没有办法使相机在0,0上居中,使其保持在那里,而不是跟随圆圈

 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();
}
 }

共 (2) 个答案

  1. # 1 楼答案

    为了理解这里的布局发生了什么,首先请注意Group{}的布局坐标被完全忽略,因为您将graph放置在布局容器(a BorderPane)中。(注释掉setLayoutXsetLayoutY行,你会发现它们没有区别。)布局容器将根据1调整其子节点的大小。它有多少空间给他们,2。子节点的最小、首选和最大大小。由于BorderPane在本例中没有任何其他子节点,因此它希望将其所有可用空间分配给graph。由于graph位于中心,如果有空间无法分配给它,它会将其居中,剩下的空间未使用

    Group的行为与Region的行为不同(包括Controls、Panes及其子类):根据documentation,它们是不可调整大小的承担其子类的集体界限

    在动画开始时,两个圆重合,以(0,0)为中心,半径为5:因此它们的边界框(以及Group的边界框)在(-5,-5)处具有左上角,宽度和高度为10。这个方形的10x10边界框不能再大(因为它是一个Group,不能调整大小),并且在屏幕上居中。由于BorderPane500个总宽度可用的像素,因此有490个未使用宽度的像素,它们在Group的两侧等分以使其居中:245在左侧,而245在右侧。所以Group的左边缘,也就是两个圆的左边缘,在BorderPane坐标系中

    在动画结束时,一个圆保持在(-5,-5)处,宽度为10x10,而另一个圆被向右平移了100个像素,因此其边界框从(95, -5)延伸到(105, 5)。因此,Group的边界框在(-5, -5)、宽度110和高度10处具有左上角的属性,它承担其子节点的集体边界。无法调整此框的大小,因此BorderPane的布局机制将此框置于其可用区域的中心。由于BorderPane具有500像素的可用宽度,因此有390个未使用的像素在宽度上被等分在两侧:195Group的左侧,并且195在右侧。所以在这一点上,Group的左边缘,即未翻译圆的左边缘,位于BorderPane坐标系中的x=195。因此,在动画结束时,未翻译的圆在BorderPane的坐标系中向左移动了50个像素(翻译距离的一半)

    这里更自然的做法是使用Pane而不是Group。一个Pane是可调整大小的,因此BorderPane将简单地扩展它以填充所有可用空间。因此,它将位于BorderPane的左上角,并填充BorderPanePane的边界从(0,0)开始,并延伸到其宽度和高度。因此,如果您只是将Group更改为Pane,则未翻译的圆在动画期间不会按您的意愿移动

    但是,现在两个圆都将从窗格的左上角开始,而不是从中间开始。如果希望它们从中心开始,可以更改圆本身的坐标,使它们从^{的中心开始:

    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();
        }
    }
    

    或者,可以使用Pane作为根,而不是BorderPane。普通的Pane不做任何布局,因此在本例中layoutXlayoutY设置将生效。因此,您可以将圆的中心恢复为(0,0),并使用graph上的布局设置使其居中:

    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();
        }
    }
    
  2. # 2 楼答案

    您可以将类名更改为您想要的任何名称

    您遇到的问题是,您通过setCenter()方法添加了它,该方法会自动使其中心成为窗格的中心

    我希望这一切来得及时

    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();
        }
    }