JavaFX 绑定仅在调整 window 大小后应用
JavaFX binding only applied after resizing the window
当我 运行 在 Main (JavaFX) class 的启动方法中使用以下代码时,我得到了奇怪的结果。 window 得到显示,但 pane
(带有绿色边框)的宽度为 0。它应该具有与容器高度相同的宽度,因为我将 prefWidth 绑定到高度 属性 .
然后,当我调整 window 的大小时,绑定生效并且窗格变成正方形。请注意,如果我最大化 window 它也不会应用绑定。
谢谢!
//Create a pane with a min width of 10 and a green border to be able to see it
Pane pane = new Pane();
pane.setStyle("-fx-border-color: green; -fx-border-width: 2");
//Bind the pane's preferred width to the pane's height
pane.prefWidthProperty().bind(pane.heightProperty());
//Put the pane in a vbox that does not fill the stage's width and make the pane grow in the vbox
VBox container = new VBox(pane);
container.setFillWidth(false);
VBox.setVgrow(pane, Priority.SOMETIMES);
//Show the vbox
primaryStage.setScene(new Scene(container, 600, 400));
primaryStage.show();
您 运行 遇到的问题是,当容器被布局时,它没有合理的信息来计算容器的宽度和高度 pane
.所以基本上发生的是它计算宽度,它(因为它是空的)为零;然后计算高度(填充容器,因为你告诉 VBox
这样做)。 之后,prefWidth
属性 发生了变化,但到那时实际宽度已经设置好了,所以基本上已经太晚了。下一次发生布局过程时,将考虑新的首选宽度。
我没有检查实际的布局代码,但是(因为默认的内容偏差为空)很可能 vbox 的布局代码将执行与以下伪代码等效的操作:
protected void layoutChildren() {
// content bias is null:
double prefWidth = pane.prefWidth(-1);
double prefHeight = pane.prefHeight(-1);
// no fill width:
double paneWidth = Math.max(this.getWidth(), prefWidth);
// vgrow, so ignore preferred height and size to height of the vbox:
double paneHeight = this.getHeight();
pane.resizeRelocate(0, 0, paneWidth, paneHeight);
}
最后一次调用实际上导致窗格的高度发生变化,然后通过绑定导致 prefWidth
发生变化。当然,这对于当前的layout pass来说已经晚了,它已经根据之前的preferred width calculation设置了宽度。
基本上,像这样依靠绑定来管理布局并不是一种可靠的做事方式,因为您正在更改属性(例如本例中的 prefWidth
)[=34] =] 布局过程,此时可能已经来不及调整组件的大小了。
像这样管理窗格布局的可靠方法是覆盖适当的布局方法,这些方法由布局过程调用以调整组件大小。
对于这个例子,由于宽度取决于高度,你应该 return VERTICAL
为 contentBias
,你应该覆盖 computePrefWidth(double height)
到 return 高度(所以宽度设置为高度):
@Override
public void start(Stage primaryStage) {
Pane pane = new Pane() {
@Override
public Orientation getContentBias() {
return Orientation.VERTICAL ;
}
@Override
public double computePrefWidth(double height) {
return height ;
}
};
pane.setStyle("-fx-border-color: green; -fx-border-width: 2");
//Bind the pane's preferred width to the pane's height
// pane.prefWidthProperty().bind(pane.heightProperty());
//Put the pane in a vbox that does not fill the stage's width and make the pane grow in the vbox
VBox container = new VBox(pane);
container.setFillWidth(false);
VBox.setVgrow(pane, Priority.SOMETIMES);
//Show the vbox
primaryStage.setScene(new Scene(container, 600, 400));
primaryStage.show();
}
当我 运行 在 Main (JavaFX) class 的启动方法中使用以下代码时,我得到了奇怪的结果。 window 得到显示,但 pane
(带有绿色边框)的宽度为 0。它应该具有与容器高度相同的宽度,因为我将 prefWidth 绑定到高度 属性 .
然后,当我调整 window 的大小时,绑定生效并且窗格变成正方形。请注意,如果我最大化 window 它也不会应用绑定。
谢谢!
//Create a pane with a min width of 10 and a green border to be able to see it
Pane pane = new Pane();
pane.setStyle("-fx-border-color: green; -fx-border-width: 2");
//Bind the pane's preferred width to the pane's height
pane.prefWidthProperty().bind(pane.heightProperty());
//Put the pane in a vbox that does not fill the stage's width and make the pane grow in the vbox
VBox container = new VBox(pane);
container.setFillWidth(false);
VBox.setVgrow(pane, Priority.SOMETIMES);
//Show the vbox
primaryStage.setScene(new Scene(container, 600, 400));
primaryStage.show();
您 运行 遇到的问题是,当容器被布局时,它没有合理的信息来计算容器的宽度和高度 pane
.所以基本上发生的是它计算宽度,它(因为它是空的)为零;然后计算高度(填充容器,因为你告诉 VBox
这样做)。 之后,prefWidth
属性 发生了变化,但到那时实际宽度已经设置好了,所以基本上已经太晚了。下一次发生布局过程时,将考虑新的首选宽度。
我没有检查实际的布局代码,但是(因为默认的内容偏差为空)很可能 vbox 的布局代码将执行与以下伪代码等效的操作:
protected void layoutChildren() {
// content bias is null:
double prefWidth = pane.prefWidth(-1);
double prefHeight = pane.prefHeight(-1);
// no fill width:
double paneWidth = Math.max(this.getWidth(), prefWidth);
// vgrow, so ignore preferred height and size to height of the vbox:
double paneHeight = this.getHeight();
pane.resizeRelocate(0, 0, paneWidth, paneHeight);
}
最后一次调用实际上导致窗格的高度发生变化,然后通过绑定导致 prefWidth
发生变化。当然,这对于当前的layout pass来说已经晚了,它已经根据之前的preferred width calculation设置了宽度。
基本上,像这样依靠绑定来管理布局并不是一种可靠的做事方式,因为您正在更改属性(例如本例中的 prefWidth
)[=34] =] 布局过程,此时可能已经来不及调整组件的大小了。
像这样管理窗格布局的可靠方法是覆盖适当的布局方法,这些方法由布局过程调用以调整组件大小。
对于这个例子,由于宽度取决于高度,你应该 return VERTICAL
为 contentBias
,你应该覆盖 computePrefWidth(double height)
到 return 高度(所以宽度设置为高度):
@Override
public void start(Stage primaryStage) {
Pane pane = new Pane() {
@Override
public Orientation getContentBias() {
return Orientation.VERTICAL ;
}
@Override
public double computePrefWidth(double height) {
return height ;
}
};
pane.setStyle("-fx-border-color: green; -fx-border-width: 2");
//Bind the pane's preferred width to the pane's height
// pane.prefWidthProperty().bind(pane.heightProperty());
//Put the pane in a vbox that does not fill the stage's width and make the pane grow in the vbox
VBox container = new VBox(pane);
container.setFillWidth(false);
VBox.setVgrow(pane, Priority.SOMETIMES);
//Show the vbox
primaryStage.setScene(new Scene(container, 600, 400));
primaryStage.show();
}