英文:
How can I bind stage width and height in JavaFX?
问题
我想将舞台的宽度和高度绑定在一起,这样用户只能通过保持纵横比来调整大小。
以下方法无效:
stage.widthProperty().bind(stage.heightProperty());
还有另一种方法:
stage.minHeightProperty().bind(scene.widthProperty().multiply(1.3));
stage.maxHeightProperty().bind(scene.widthProperty().multiply(1.3));
但是用这种方法只设置了宽度值。
我该如何解决这个问题?
谢谢,
Tibor
英文:
I want to bind the stage width and height together, so the user can only resize it by keeping the aspect ration.
This doesn't work:
stage.widthProperty().bind(stage.heightProperty());
There is another way:
stage.minHeightProperty().bind(scene.widthProperty().multiply(1.3));
stage.maxHeightProperty().bind(scene.widthProperty().multiply(1.3));
But in this way I only set the width value.
How could I solve this?
Thanks,
Tibor
答案1
得分: 2
由于width
和height
属性是只读的,因此您无法将它们绑定到任何内容,更不用说彼此之间了。它们只读的原因在文档中有说明:
>许多Stage
属性是只读的,因为它们可以在底层平台上被外部更改,因此不能进行绑定[因为绑定属性无法被设置]。
width
和height
属性在它们的文档中都有类似的说明。
您仍然可以为每个属性添加监听器,并在一个属性更改时将另一个属性设置为新值。为了确保这不会导致StackOverflowError
,您需要跟踪您当前是否正在监听器中设置值。例如:
// 在 Property.bind(...) 的上下文中实际上不是“绑定”
public static void bindWidthAndHeightTogether(Window window, double widthToHeightRatio) {
ChangeListener<Number> listener =
new ChangeListener<>() {
private boolean changing;
@Override
public void changed(ObservableValue<? extends Number> obs, Number ov, Number nv) {
if (!changing) {
changing = true;
try {
if (obs == window.widthProperty()) {
window.setHeight(nv.doubleValue() / widthToHeightRatio);
} else {
window.setWidth(nv.doubleValue() * widthToHeightRatio);
}
} finally {
changing = false;
}
}
}
};
window.widthProperty().addListener(listener);
window.heightProperty().addListener(listener);
}
上述代码对我在使用JavaFX 14的Windows 10上有效。请注意,它可以防止窗口被适当地最大化,但无法防止窗口进入全屏模式(至少在Windows 10上是如此)。
英文:
Since the width
and height
properties are read-only you cannot bind them to anything, let alone each other. The reason they're read-only is documented:
>Many of the Stage
properties are read only because they can be changed externally by the underlying platform and therefore must not be bindable [because bound properties cannot be set].
Both the width
and height
properties have similar statements in their documentation.
You can still add a listener to each property and, when one property changes, set the other property to the new value. To make sure this doesn't lead to a StackOverflowError
you'll have to track if you're currently setting the value in the listener. For example:
// not actually "binding" in the context of Property.bind(...)
public static void bindWidthAndHeightTogether(Window window, double widthToHeightRatio) {
ChangeListener<Number> listener =
new ChangeListener<>() {
private boolean changing;
@Override
public void changed(ObservableValue<? extends Number> obs, Number ov, Number nv) {
if (!changing) {
changing = true;
try {
if (obs == window.widthProperty()) {
window.setHeight(nv.doubleValue() / widthToHeightRatio);
} else {
window.setWidth(nv.doubleValue() * widthToHeightRatio);
}
} finally {
changing = false;
}
}
}
};
window.widthProperty().addListener(listener);
window.heightProperty().addListener(listener);
}
The above worked for me on Windows 10 using JavaFX 14. Note that it prevents the window from being maximized properly but not from going full-screen (at least on Windows 10).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论