JavaFX-中心子阶段到父阶段

sco*_*i17 5 java javafx javafx-8

我是JavaFX的新手,我在设置新窗口的位置时遇到问题,该位置与父窗口的位置有关。我想在父窗口的中心打开一个新窗口。

我尝试了以下两种方法:

1)初始化所有者-我以为初始化所有者会在父母中心打开我的窗口,但不会

FXMLLoader fxmlLoader = new     FXMLLoader(AddUserController.class.getResource("/view/addUserStage.fxml"));
Parent root = fxmlLoader.load();
Stage stage = new Stage();
stage.initOwner(parentStage);
stage.showAndWait();
Run Code Online (Sandbox Code Playgroud)

2)在显示窗口时重新定位-它可以工作,但是在显示窗口后,我可以看到它的第一个位置,然后看到它已移动到新的计算位置。我不能接受。

FXMLLoader fxmlLoader = new     FXMLLoader(AddUserController.class.getResource("/view/addUserStage.fxml"));
Parent root = fxmlLoader.load();
Stage stage = new Stage();
stage.initOwner(parentStage);
stage.setOnShown(event -> controller.onWindowShown());
stage.showAndWait();
Run Code Online (Sandbox Code Playgroud)

在onWindowShown函数中,我正在设置窗口的新X和Y位置,因为只有知道了所显示的窗口的宽度和高度之后,我才能轻松计算出新位置。

在showAndWait函数之前,如何设置子窗口在父窗口中心的位置?

Dar*_*ryl 6

正如其他答案正确指出的那样,JavaFX在显示窗口时计算载物台的宽度和高度。onShowing()属性在计算发生之前和窗口设置为可见之前被调用,因此在其中放置stage.hide()命令实际上不会执行任何操作。正如问题所指出的,在重新定位窗口之前在屏幕上看到一个斑点是一个不希望的结果。

我发现解决此问题的唯一方法(尽管我很想知道是否存在更好的方法)是将侦听器添加到舞台的width和height属性,并让它们触发事件以更改窗口的位置。然后,在窗口可见后,删除侦听器。

例如:

//Let's say we want to center the new window in the parent window

ChangeListener<Number> widthListener = (observable, oldValue, newValue) -> {
        double stageWidth = newValue.doubleValue();
        stage.setX(parentStage.getX() + parentStage.getWidth() / 2 - stageWidth / 2);
};
ChangeListener<Number> heightListener = (observable, oldValue, newValue) -> {
        double stageHeight = newValue.doubleValue();
        stage.setY(parentStage.getY() + parentStage.getHeight() / 2 - stageHeight / 2);   
};

stage.widthProperty().addListener(widthListener);
stage.heightProperty().addListener(heightListener);

//Once the window is visible, remove the listeners
stage.setOnShown(e -> {
    stage.widthProperty().removeListener(widthListener);
    stage.heightProperty().removeListener(heightListener);
});

stage.show();
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用。我不能相信他们没有在Swing上包含-setLocationRelativeTo(something)之类的方法。 (2认同)

DVa*_*rga 5

如果要显示 a Stage,则必须将从 FXML 文件加载的内容放到 a 中Scene,这Scene将在Stage.

不幸的Stage是,在渲染之前,的大小是未知的(如您所提到的),但是要将其重新定位到 parent 的中心Stage,您必须知道大小。

可以工作一个技巧是隐藏Stage显示它之前,重新定位,然后使其可见再上新的位置。

例子

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root, 400, 400);

            Button button = new Button("Open another Stage");
            button.setOnAction(e -> {

                Stage popUpStage = new Stage();

                // Here add the FXML content to the Scene
                Scene popUpScene = new Scene(new Button());
                popUpStage.setScene(popUpScene);

                // Calculate the center position of the parent Stage
                double centerXPosition = primaryStage.getX() + primaryStage.getWidth()/2d;
                double centerYPosition = primaryStage.getY() + primaryStage.getHeight()/2d;

                // Hide the pop-up stage before it is shown and becomes relocated
                popUpStage.setOnShowing(ev -> popUpStage.hide());

                // Relocate the pop-up Stage
                popUpStage.setOnShown(ev -> {
                    popUpStage.setX(centerXPosition - popUpStage.getWidth()/2d);
                    popUpStage.setY(centerYPosition - popUpStage.getHeight()/2d);
                    popUpStage.show();
                });

                popUpStage.showAndWait();
            });

            root.setCenter(button);


            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)