如何在Java FX中正确居中窗口?

Mic*_*ung 7 javafx

Java FX提供Window.centerOnScreen()来猜测 - 屏幕上的窗口居中.但是,Java FX对"屏幕中心"的定义似乎是(0.5x; 0.33y).我希望这是一个bug,但我被告知不是.

无论如何.是否有人提出了一个简洁的解决方案,如何在显示窗口之前将窗口居中?我的第一种方法导致屏幕闪烁,因为必须首先显示窗口,然后才能居中.

public static void centerOnScreen(Stage stage) {
  stage.centerOnScreen();
  stage.setY(stage.getY() * 3f / 2f);
}
Run Code Online (Sandbox Code Playgroud)

更新:我忘了提到; 我事先不知道窗口的大小,所以为了手动居中,我必须首先显示它 - 导致它闪烁一次的原因.所以我正在寻找一种解决方案来集中它而不首先显示它 - 就像Java FX能够做到这一点,但是错误的方式.

Rol*_*and 13

这是你在舞台可见之前的方式:

    double width = 640;
    double height = 480;

    Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
    stage.setX((screenBounds.getWidth() - width) / 2); 
    stage.setY((screenBounds.getHeight() - height) / 2);  

    final Scene scene = new Scene( new Group(), width, height);
    stage.setScene(scene);
    stage.show();
Run Code Online (Sandbox Code Playgroud)

在舞台变得可见之后,即你可以使用舞台的属性:

    double width = 640;
    double height = 480;

    final Scene scene = new Scene( new Group(), width, height);
    stage.setScene(scene);
    stage.show();

    Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
    stage.setX((screenBounds.getWidth() - stage.getWidth()) / 2); 
    stage.setY((screenBounds.getHeight() - stage.getHeight()) / 2);  
Run Code Online (Sandbox Code Playgroud)

如果您有多个屏幕,则可以使用Screen.getScreens()方法返回的Screen对象列表手动计算位置.


小智 6

我知道这个帖子大约三年半前就得到了回答,但在我看来,每个人都忽视了这个问题。

你只需要stage.centerOnScreen();在之后键入 ,stage.show()因为如果你在代码之前编写它,代码将被执行一次,然后它会进入其原始状态(这就是我头脑中的解释)。


Jam*_*s_D 5

响应值初始化的一般技巧是为该属性创建一个侦听器,该侦听器在初始化属性时将自身删除。所以你可以做

    Screen screen = Screen.getPrimary();
    Rectangle2D sbounds = screen.getBounds();

    double sw = sbounds.getWidth() ;
    double sh = sbounds.getHeight();

    listenToSizeInitialization(primaryStage.widthProperty(), 
            w -> primaryStage.setX(( sw - w) /2));
    listenToSizeInitialization(primaryStage.heightProperty(), 
            h -> primaryStage.setY(( sh - h) /2));


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

private void listenToSizeInitialization(ObservableDoubleValue size, 
        DoubleConsumer handler) {

    ChangeListener<Number> listener = new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> obs, 
                Number oldSize, Number newSize) {
            if (newSize.doubleValue() != Double.NaN) {
                handler.accept(newSize.doubleValue());
                size.removeListener(this);
            }
        }
    };
    size.addListener(listener);
}
Run Code Online (Sandbox Code Playgroud)