Как вы можете расположить узел JavaFX, заполненный пропорционально доступному пространству? - PullRequest
0 голосов
/ 24 марта 2020

Довольно просто использовать стандартные панели макетов в JavaFX для получения фиксированного заполнения вокруг узла контента.

Однако существуют настройки для любой из стандартных панелей макета, которые бы помещали контент в середину ¾ ширины панели с отступом 1/8 ширины с каждой стороны?

1 Ответ

0 голосов
/ 24 марта 2020

Вы можете, как , предложенный 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».

Также обратите внимание, что оба решения размещают дочерние элементы в доступной области после пространство, занимаемое из любых отступов и границ, вычитается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...