如何在JavaFX中绑定舞台的宽度和高度?

huangapple go评论74阅读模式
英文:

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

由于widthheight属性是只读的,因此您无法将它们绑定到任何内容,更不用说彼此之间了。它们只读的原因在文档中有说明:

>许多Stage属性是只读的,因为它们可以在底层平台上被外部更改,因此不能进行绑定[因为绑定属性无法被设置]。

widthheight属性在它们的文档中都有类似的说明。

您仍然可以为每个属性添加监听器,并在一个属性更改时将另一个属性设置为新值。为了确保这不会导致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).

huangapple
  • 本文由 发表于 2020年3月16日 23:17:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/60708600.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定