Вы можете, как , предложенный James_D , использовать GridPane
с соответствующими ограничениями для выполнения sh этого. Вот пример:
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) {
Region region = new Region();
region.setStyle("-fx-background-color: firebrick;");
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.add(region, 0, 0);
ColumnConstraints cc = new ColumnConstraints(0, Region.USE_COMPUTED_SIZE, Double.MAX_VALUE);
cc.setPercentWidth(75);
cc.setHgrow(Priority.ALWAYS);
cc.setHalignment(HPos.CENTER);
grid.getColumnConstraints().add(cc);
RowConstraints rr = new RowConstraints(0, Region.USE_COMPUTED_SIZE, Double.MAX_VALUE);
rr.setPercentHeight(100);
rr.setVgrow(Priority.ALWAYS);
rr.setValignment(VPos.CENTER);
grid.getRowConstraints().add(rr);
primaryStage.setScene(new Scene(grid, 500, 300));
primaryStage.show();
}
}
Другой вариант - создать свой собственный макет, который, если я не ошибся, не слишком сложен:
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
public class CustomPane extends Pane {
// value should be between 0.0 (0%) and 1.0 (100%)
private final DoubleProperty widthRatio =
new SimpleDoubleProperty(this, "widthRatio", 0.75) {
@Override
protected void invalidated() {
requestLayout();
}
};
public final void setWidthRatio(double widthRatio) { this.widthRatio.set(widthRatio); }
public final double getWidthRatio() { return widthRatio.get(); }
public final DoubleProperty widthRatioProperty() { return widthRatio; }
public CustomPane() {}
public CustomPane(double widthRatio) {
setWidthRatio(widthRatio);
}
@Override
protected void layoutChildren() {
double ratio = getWidthRatioClamped();
double x = snappedLeftInset();
double y = snappedTopInset();
double w = getWidth() - snappedRightInset() - x;
double h = getHeight() - snappedBottomInset() - y;
// could do the same thing with the height if you want
x = snapPositionX(x + ((w - w * ratio) / 2.0));
w = snapSizeX(w * ratio);
for (Node child : getManagedChildren()) {
layoutInArea(child, x, y, w, h, -1.0, HPos.CENTER, VPos.CENTER);
}
}
private double getWidthRatioClamped() {
return Math.max(0.0, Math.min(1.0, getWidthRatio()));
}
}
Обратите внимание, что оба решения будет учитывать ширину и высоту дочерних узлов min / pref / max. Если дочерний узел не имеет изменяемого размера (например, ImageView
, MediaView
, et c.), Тогда он не будет работать должным образом. Хотя вы, конечно, можете создать обходные пути для узлов без изменения размера. Например, вот еще один мой ответ , который создает «изменяемый размер ImageView
».
Также обратите внимание, что оба решения размещают дочерние элементы в доступной области после пространство, занимаемое из любых отступов и границ, вычитается.