OS:RHEL 7.4
DE:KDE Plasma 4.11.19和GNOME 3.22.2
Java版本:9和10
在调用show()后试图计算舞台的大小时遇到问题。在Java 8 / RHEL 6之前,一切工作正常,在show()之后,我可以一致地获得舞台的大小。我只是听一下width和height属性,但看起来舞台本身有一个更新,然后又添加了装饰大小的另一个更新,但是如果装饰大小为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
编辑:看起来还不能保证第二遍添加装饰,并且偶尔会在第一遍完成。
答案 0 :(得分:0)
我不能给出确切的答案,因为我对JavaFX的使用不是很熟练。
所有窗户都装饰好了吗?如果没有,您可以先对StageStyle
进行检查,并且仅在装饰完成后做出响应。
如果所有窗户都装饰好了,是否可以选择等待更改?
如果无法等待,是否在应用可能的修饰后更新属性outputScaleX
和ouputScaleY
?如果没有,请改用那些。
最后,Stage
本身不包含width
和height
属性,它们是它扩展的Window
的属性。您始终可以尝试使用renderScaleX
和renderScaleY
属性,并为框架/边距/等占用任何空间。在使用这些值时应考虑在内。
否则,您可以对这两个事件做出最后回应。
答案 1 :(得分:0)
最终使用此answer。对其进行了稍微修改,以等待至少2个事件(初始宽度和高度),然后再等待一段时间后再查看是否有其他事件。
我对这种解决方案并不完全满意,但是它目前可以使用,但仍然感觉很敏捷。除了迷上本机库外,我不确定还能做什么。
此解决方案引起的问题是显示器显示在错误的地方,然后转移到我想要的地方。尝试在show()之前使用setOpacity(0),然后在初始化之后使用setOpacity(1)似乎只能缓解该问题,因为它偶尔仍会在错误的位置显示一秒钟。