我是JavaFX新手,我在设置新窗口的位置时遇到了问题,这与父窗口的位置有关。我想在父窗口的中心打开新窗口。
我尝试了这两种方法:
1) Init owner -我以为init owner会在parent的中心打开我的窗口,但它没有
FXMLLoader fxmlLoader = new FXMLLoader(AddUserController.class.getResource("/view/addUserStage.fxml"));
Parent root = fxmlLoader.load();
Stage stage = new Stage();
stage.initOwner(parentStage);
stage.showAndWait();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();在onWindowShown函数中,我正在设置我的窗口的新的X和Y位置,因为只有在显示之后,我的窗口的宽度和高度才是已知的,我可以很容易地计算出新的位置。
如何在showAndWait函数之前将子窗口位置设置在父窗口的中心?
发布于 2016-10-18 18:09:59
如果您想要显示一个Stage,您必须将从FXML文件加载的内容放到一个Scene中,此Scene将在Stage上设置。
不幸的是,在渲染之前,Stage的大小是未知的(正如您所提到的),但是要将它重新定位到父Stage的中心,您必须知道它的大小。
一个可行的技巧是在Stage显示之前对其执行hide操作,重新定位它,然后在新位置再次执行make it visible操作。
示例
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);
}
}发布于 2017-05-25 01:38:39
正如另一个答案所说的那样,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();发布于 2016-10-18 18:47:51
您可以在显示Scene之前对Stage进行布局,并根据Scene大小确定位置。但是,这不会考虑窗口装饰,因此位置可能会略有偏移,除非您有一个具有相同类型装饰的窗口,以考虑这些装饰的大小:
@Override
public void start(Stage primaryStage) {
Button btnMain = new Button("show");
btnMain.setOnAction(evt -> {
Stage stage = new Stage();
Button btn = new Button("Close");
btn.setOnAction((ActionEvent event) -> {
stage.close();
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Bounds mainBounds = primaryStage.getScene().getRoot().getLayoutBounds();
Scene scene = new Scene(root, 400, 400);
stage.setScene(scene);
// layout new scene
scene.getRoot().applyCss();
scene.getRoot().layout();
Bounds rootBounds = scene.getRoot().getLayoutBounds();
stage.setX(primaryStage.getX() + (mainBounds.getWidth() - rootBounds.getWidth()) / 2);
stage.setY(primaryStage.getY() + (mainBounds.getHeight() - rootBounds.getHeight()) / 2);
stage.showAndWait();
System.out.println("done");
});
Scene mainScene = new Scene(new StackPane(btnMain), 600, 600);
primaryStage.setScene(mainScene);
primaryStage.show();
}https://stackoverflow.com/questions/40104688
复制相似问题