Распределить оставшееся место в GridPane или как это сделать

Нам нужно решение для макета из 3 столбцов со следующими требованиями:

  • Средний столбец имеет фиксированный размер
  • Средний столбец центрирован в родительском
  • Два других столбца делят оставшееся пространство
  • Два других столбца имеют одинаковый размер

Допустим, у нас есть горизонтальное пространство 440 пикселей и средний столбец с фиксированным размером 40 пикселей. Два других столбца должны разделять оставшиеся 400 пикселей, чтобы каждый столбец имел ширину 200 пикселей.

------------------------------------
|    200px    | 40px |    200px    |
------------------------------------

Если общий размер изменится, скажем, на 500 пикселей, ширина среднего столбца не должна измениться, а остальные должны.

----------------------------------------
|     230px     | 40px |     230px     |
----------------------------------------

Если это возможно с помощью GridPane, расскажите, как это сделать.

Если это невозможно с GridPane, я открыт для других предложений.

Я бы предпочел решение с простым а) кодом Java без FXML и б) только JavaFx, поэтому дополнительные библиотеки.


person Guardian667    schedule 17.01.2018    source источник
comment
Я полагаю, вы имеете в виду GridPane, а не GridLayout?   -  person James_D    schedule 17.01.2018
comment
Да. На мой взгляд, глупое наследие Swing :-D THX   -  person Guardian667    schedule 17.01.2018


Ответы (1)


Вам просто нужны три ограничения столбца:

ColumnConstraints leftCol = new ColumnConstraints();
leftCol.setHgrow(Priority.ALWAYS);
ColumnConstraints middleCol = new ColumnConstraints(40);
ColumnConstraints rightCol = new ColumnConstraints();
rightCol.setHgrow(Priority.ALWAYS);

GridPane gridPane = new GridPane();
gridPane.getColumnConstraints().addAll(leftCol, middleCol, rightCol);

Вы можете сделать то же самое в FXML, если хотите:

<GridPane>
  <columnConstraints>
    <ColumnConstraints hgrow="ALWAYS"/>
    <ColumnConstraints minWidth="40" prefWidth="40" maxWidth="40"/>
    <ColumnConstraints hgrow="ALWAYS"/>
  </columnConstraints>

  <!-- ... -->
</GridPane>

Вот SSCCE:

import javafx.application.Application;
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.stage.Stage;

public class GridPaneTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        ColumnConstraints leftCol = new ColumnConstraints();
        leftCol.setHgrow(Priority.ALWAYS);
        ColumnConstraints middleCol = new ColumnConstraints(40);
        ColumnConstraints rightCol = new ColumnConstraints();
        rightCol.setHgrow(Priority.ALWAYS);


        GridPane gridPane = new GridPane();
        gridPane.getColumnConstraints().addAll(leftCol, middleCol, rightCol);

        Region left = new Region();
        left.setMinHeight(80);
        left.setStyle("-fx-background-color: red;");

        Region middle = new Region();
        middle.setMinHeight(80);
        middle.setStyle("-fx-background-color: green ;");

        Region right = new Region();
        right.setMinHeight(80);
        right.setStyle("-fx-background-color: blue ;");

        gridPane.addRow(0, left, middle, right);

        Scene scene = new Scene(gridPane, 400, 80);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

введите описание изображения здесь

введите описание изображения здесь

person James_D    schedule 17.01.2018
comment
Это работает, но моя проблема не полностью решена. Я сказал, что средний столбец имеет фиксированный размер. Фактически сетка содержит только одну строку, а средний столбец содержит один элемент управления. Размер этого элемента управления может измениться во время выполнения. В вашем примере зеленый регион изменит свою ширину, и GridPane должен отреагировать на это. Поэтому мне нужно продуманное решение, чтобы разделить оставшийся размер за вычетом динамического размера. Это не может работать с ограничениями, не удаляя их, выполняя пересчет и повторно добавляя их вручную. - person Guardian667; 19.01.2018
comment
@ Guardian667 Я не совсем понимаю этот комментарий. В моем коде средний столбец имеет фиксированный размер, как вы указали в вопросе: он всегда равен 40 пикселям. Или вы хотите сказать, что меняете вопрос? - person James_D; 19.01.2018
comment
Да, ваш пример соответствует моему объяснению. Мое объяснение было неточным относительно проблемы. В моем особом случае не сам столбец ограничен фиксированным размером, а его ширина ограничена размером элемента управления, который он содержит. | х | контроль | х | Размер элемента управления может меняться, и при этом оставшееся пространство должно распределяться равномерно. Я делаю это прямо сейчас, воссоздавая ограничения, когда размер элемента управления изменяется, но, возможно, есть более элегантное решение. - person Guardian667; 19.01.2018
comment
@Guardian667 Просто заменить ColumnConstraints middleCol = new ColumnConstraints(40); на ColumnConstraints middleCol = new ColumnConstraints();? (По умолчанию min, max и prefWidth равны Region.USE_COMPUTED_SIZE.) Я думаю, что это должно работать, если вы не делаете ничего необычного с макетом элемента управления, содержащегося в этом столбце. - person James_D; 19.01.2018
comment
USE_COMPUTED_SIZE имеет тот же эффект, что и Priority.ALLWAYS :( Мое решение на данный момент: ColumnConstraints для среднего столбца хранятся в параметре класса. Их минимальное и максимальное значение устанавливается на желаемую ширину i, когда они становятся очевидными. - person Guardian667; 25.01.2018
comment
@Guardian667 Guardian667 Итак, установите hgrow этого столбца явно на Priority.NEVER? - person James_D; 25.01.2018
comment
Это уже пробовал. Может быть, это не действует только в моем особом случае. На данный момент я в порядке с решением. Дата релиза еще впереди (ваааааааа ;-) - person Guardian667; 26.01.2018