0

操作系统:RHEL 7.4
DE:KDE Plasma 4.11.19 和 GNOME 3.22.2
Java 版本:9 和 10

在调用 show() 后,我在尝试计算 Stage 的大小时遇到​​问题。之前在 Java 8/RHEL 6 中一切正常,我可以在 show() 之后一致地获得舞台的大小。我只会听宽度和高度属性,但看起来舞台本身有一个更新,然后另一个更新添加了装饰尺寸,但是如果装饰尺寸为 0 怎么办,如本例中装饰的宽度是 0,所以我不能只听对 width 和 height 属性的两个更改。

我做错了吗?是否有其他我可以听到的事件来保证舞台在 show() 之后已经完全初始化?我添加了一些示例代码来演示下面的问题。

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.stage.Stage;

public class JavaFXTest extends Application {

  public static void main(String[] args) {
      Application.launch(JavaFXTest.class);
  }

  @Override
  public void start(final Stage primaryStage) throws Exception {
    primaryStage.widthProperty().addListener(new ChangeListener<Number>() {
      @Override
      public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
       System.out.println("Width changed! Previous value = " + oldValue + ", new value = " + newValue);
      }
    });
    primaryStage.heightProperty().addListener(new ChangeListener<Number>() {
      @Override
      public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
       System.out.println("Height changed! Previous value = " + oldValue + ", new value = " + newValue);
      }
    });
    primaryStage.showingProperty().addListener(new ChangeListener<Boolean>() {
      @Override
      public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) {
        if(newValue) {
          Platform.runLater(() -> {
            final double width = primaryStage.getWidth();
            final double height = primaryStage.getHeight();
            System.out.println("Stage width and height after change to showing property (Platform.runLater): " + width + ", " + height);
          });
        }
      }
    });
    primaryStage.showingProperty().addListener(new ChangeListener<Boolean>() {
      @Override
      public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) {
        if(newValue) {
          final double width = primaryStage.getWidth();
          final double height = primaryStage.getHeight();
          System.out.println("Stage width and height after change to showing property: " + width + ", " + height);
        }
      }
    });
    primaryStage.show();
    Platform.runLater(() -> {
      final double width = primaryStage.getWidth();
      final double height = primaryStage.getHeight();
      System.out.println("Stage width and height immediately after show (Platform.runLater): " + width + ", " + height);
    });
    final double width = primaryStage.getWidth();
    final double height = primaryStage.getHeight();
    System.out.println("Stage width and height immediately after show:" + width + ", " + height);
  }
}

以下是该程序的一些可能输出。输出不一致。

GNOME 上的输出(和 KDE,数字不同)
示例案例 1:
更改为显示属性后的
舞台宽度和高度:NaN、NaN 显示后立即显示的舞台宽度和高度:NaN、NaN
更改为显示属性后的舞台宽度和高度(Platform. runLater): NaN, NaN
演出后舞台宽度和高度 (Platform.runLater): NaN, NaN
宽度改变了!以前的值 = NaN,新值 = 318.0
高度改变了!以前的值 = NaN,新值 = 171.0
高度改变了!先前值 = 171.0,新值 = 208.0

示例案例 2:
更改为显示属性后的
舞台宽度和高度:NaN,NaN 显示后立即显示的舞台宽度和高度:NaN,NaN
宽度改变了!以前的值 = NaN,新值 = 318.0
高度改变了!先前值 = NaN,新值 = 171.0
更改为显示属性 (Platform.runLater) 后的
舞台宽度和高度:318.0、171.0 显示后立即显示的舞台宽度和高度 (Platform.runLater):318.0、171.0
高度已更改!先前值 = 171.0,新值 = 208.0

编辑:看起来第二遍添加装饰也不能保证,偶尔会在第一遍中完成。

4

2 回答 2

0

我无法给出明确的答案,因为我对 JavaFX 不是很有经验。

所有的窗户都装饰了吗?如果没有,您可以先进行检查,StageStyle并仅在装饰完成时做出响应。

如果所有窗户都装饰了,那么等待应用更改是一个选项吗?如果等待不是一种选择,是否在应用可能的装饰后属性outputScaleX和更新?ouputScaleY如果没有,请改用它们。

最后,theStage本身不包含widthandheight属性,这些是Windowit 扩展的属性。您总是可以尝试使用renderScaleXandrenderScaleY属性并为框架/边距/等占用任何空间。在对这些值进行操作时考虑在内。

否则,您可以将这两个事件作为最后的手段。

于 2018-07-13T14:34:25.560 回答
0

最终得到了这个答案。稍微修改它以等待至少 2 个事件(初始宽度和高度),然后再等待一段时间后查看是否还有更多事件。

我对这个解决方案并不完全满意,但它现在可以工作并且仍然感觉很活泼。除了挂接到本机库之外,我不确定我还能做什么。

但是,此解决方案引起的问题是在移动到我想要的位置之前显示在错误的位置。尝试在 show() 之前使用 setOpacity(0) ,然后在初始化之后使用 setOpacity(1) 似乎只能在一定程度上缓解问题,因为它偶尔仍会在一瞬间显示在错误的位置。

于 2018-07-24T18:35:04.883 回答