我有一个 VBox 作为场景的根节点。里面的每个窗格都有自己的最小-最大高度,我让它们按照我想要的方式行事。我已将 VBox 设置为完全填充窗格。
我想要的另外两件事:
实际上,窗口不断缩小,而 VBox 在发生这种情况时消失在其中。
最好不要指定窗口的最小高度,因为这些组件的大小可能会发生变化。我希望自动计算最小高度。实现这一目标的最直接方法是什么?
这是我的 MWE:
package path.to.package;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class LayoutTestApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Label labelA = new Label("Box A");
Pane labelPaneA = new Pane(labelA);
decoratePane(labelPaneA, 5, Color.TURQUOISE);
labelPaneA.setMinHeight(20);
labelPaneA.setMaxHeight(50);
Label labelB = new Label("Box B");
Pane labelPaneB = new Pane(labelB);
decoratePane(labelPaneB, 5, Color.HOTPINK);
labelPaneB.setMinHeight(30);
labelPaneB.setMaxHeight(60);
Label labelC = new Label("Box C");
Pane labelPaneC = new Pane(labelC);
decoratePane(labelPaneC, 5, Color.MAROON);
labelPaneC.setMinHeight(20);
labelPaneC.setMaxHeight(100);
VBox root = new VBox(labelPaneA, labelPaneB, labelPaneC);
decoratePane(root, 20, Color.BLACK);
root.heightProperty().addListener((obs, ov, nv) -> {
System.out.println("Root changed height to " + nv);
});
VBox.setVgrow(labelPaneA, Priority.ALWAYS);
VBox.setVgrow(labelPaneB, Priority.ALWAYS);
VBox.setVgrow(labelPaneC, Priority.ALWAYS);
Scene scene = new Scene(root);
//Edited after it was explained that this isn't necessary
//root.prefHeightProperty().bind(scene.heightProperty());
//root.prefWidthProperty().bind(scene.widthProperty());
primaryStage.setScene(scene);
primaryStage.show();
}
private static void decoratePane(Pane pane, double pw, Color color) {
pane.setPadding(new Insets(pw, pw, pw, pw));
pane.setBorder(new Border(new BorderStroke(color,
BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
}
}
答案 0 :(得分:0)
这是一个真正的黑客;覆盖根节点的 layoutChildren()
以更新阶段的 minHeight
和 maxHeight
。另请注意,VBox
不会将其最大高度限制为其子节点的最大高度,因此使用 VBox
您还需要覆盖 computeMaxHeight(...)
:
VBox root = new VBox(labelPaneA, labelPaneB, labelPaneC) {
@Override
protected void layoutChildren() {
super.layoutChildren();
Scene scene = getScene();
if (scene == null) return ;
Stage stage = (Stage) scene.getWindow();
if (stage == null) return ;
double heightDelta = stage.getHeight() - scene.getHeight() ;
stage.setMinHeight(computeMinHeight(-1) + heightDelta);
stage.setMaxHeight(computeMaxHeight(-1) + heightDelta);
}
@Override
protected double computeMaxHeight(double width) {
return getChildren().stream()
.collect(Collectors.summingDouble(node -> node.maxHeight(width)));
}
};
不过肯定有更好的方法。