Ширина области не обновляется автоматически после изменения панели сетки, к которой привязана ширина области - JavaFX - PullRequest
0 голосов
/ 28 сентября 2019

Я создаю простое приложение с графическим интерфейсом Java, использующее JavaFX, в котором в качестве корневого узла используется Border Pane.
В верхней части Border Pane есть Grid Pane с тремя столбцами (top Grid Pane с этого момента).on).
В первом столбце верхней панели сетки есть кнопка Home, во втором столбце есть пустой регион, который служит только как spacer между первым и третьим столбцом верхней панели сетки.и в третьем столбце есть еще одна GridPane (right Grid Pane отныне).
Правая панель сетки содержит одну кнопку (кнопку входа в систему) при запуске.Однако, когда пользователь успешно входит в приложение, две другие кнопки и метка добавляются на правую панель сетки как часть события нажатия кнопки входа в систему.
Проставки maxWidthProperty и minWidthProperty связаны сtop Grid Pane (tgp) widthProperty и правая Grid Pane (rgp) widthProperty, например, так:

spacer.minWidthProperty().bind(tgp.widthProperty().subtract(80).subtract(rgp.widthProperty()).subtract(3));
spacer.maxWidthProperty().bind(tgp.widthProperty().subtract(80).subtract(rgp.widthProperty()).subtract(3));

, что делает правильное перемещение правой Grid Pane с помощью кнопок, расположенных на правой сторонесцена, когда пользователь изменяет размер основной сцены.
Однако проблема возникает, когда пользователь входит в систему и дополнительные кнопки добавляются в правую панель сетки.Прокладка каким-то образом пропускает это изменение, и его ширина остается той же самой, что заставляет дополнительные кнопки появляться за пределами текущей ширины ступени.Единственный способ обновить ширину распорки - это как-то взаимодействовать со сценой, нажимая свернуть / развернуть / восстановить или нажав любую кнопку на сцене.
Есть ли способ автоматически обновлять ширину области после узлов, к которым она относится?ширина должна быть изменена?Или есть ли лучший подход к созданию верхней панели сетки с одной кнопкой слева и изменяемым количеством кнопок (узлов) справа?

Редактировать: Вот демонстрацияпроблема с несколькими скриншотами, сложенными друг на друга: enter image description here

Минимальный воспроизводимый пример:

BorderPane root = new BorderPane();

GridPane tgp = new GridPane();
tgp.minWidthProperty().bind(root.widthProperty());
tgp.maxWidthProperty().bind(root.widthProperty());
tgp.setStyle("-fx-background-color: WHITE; -fx-border-color: LIGHTGREY;");
tgp.setMinHeight(37);
tgp.setMaxHeight(37);
root.setTop(tgp);

Button homeButton = new Button("Home"));
homeButton.setMinHeight(35);
homeButton.setMaxHeight(35);
homeButton.setMinWidth(80);
homeButton.setMaxWidth(80);
tgp.add(homeButton, 0, 0);

GridPane rgp = new GridPane(); // Right Grid Pane - holds User related nodes
rgp.setHgap(5);
tgp.add(rgp, 2, 0);

Label unl = new Label("My Profile");
unl.setFont(new Font("Calibri", 15));
unl.setTextFill(Color.RED);
unl.setMinWidth(Region.USE_PREF_SIZE);

Button wlButton = new Button("Watchlist");
wlButton.setMinHeight(35);
wlButton.setMaxHeight(35);
wlButton.setMinWidth(80);
wlButton.setMaxWidth(80);

Button cartButton = new Button("Cart");
cartButton.setMinHeight(35);
cartButton.setMaxHeight(35);
cartButton.setMinWidth(60);
cartButton.setMaxWidth(60);

Button logInOutButton = new Button("Log In");
logInOutButton.setMinHeight(35);
logInOutButton.setMaxHeight(35);
logInOutButton.setMinWidth(60);
logInOutButton.setMaxWidth(60);
rgp.add(logInOutButton, 3, 0);

logInOutButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    if (logInOutButton.getText().equals("Log In")) {
                        LogInStage lis = new LogInStage();
                        lis.initStage();

                        if (lis.username != null) {
                            logInOutButton.setText("Log Out");
                            rgp.add(unl, 0, 0);
                            rgp.add(wlButton, 1, 0);
                            rgp.add(cartButton, 2, 0);
                        }

                    } else if (logInOutButton.getText().equals("Log Out")) {
                        logInOutButton.setText("Log In");
                        rgp.getChildren().remove(unl);
                        rgp.getChildren().remove(wlButton);
                        rgp.getChildren().remove(cartButton);
                    }

                }
            });

Region spacer = new Region();
spacer.minWidthProperty().bind(tgp.widthProperty().subtract(80).subtract(rgp.widthProperty()).subtract(3));
spacer.maxWidthProperty().bind(tgp.widthProperty().subtract(80).subtract(rgp.widthProperty()).subtract(3));
tgp.add(spacer, 1, 0)

1 Ответ

0 голосов
/ 28 сентября 2019

Всегда плохо использовать привязки, если вы можете их избежать.Любые изменения в ограничениях размера могут привести к планированию нового прохода макета, но во время прохода макета они предполагаются постоянными.Если вы теперь введете привязку, может произойти следующая последовательность событий:

  1. Для GridPane запрашивается проход макета, требуется установить флаг, чтобы указать, что макет требуется
  2. Макетпройти бывает.Во время прохода макета дети меняются.Это инициирует обновление ограничений дочерних элементов с привязками.
  3. Флаг снят, но изменения в ограничениях уже произошли.Макет не будет отражать это.GridPane получает еще одну причину для создания макета.

Я не знаю, как детально настроена ваша сцена, но я рекомендую использовать ограничения столбцов: установить приоритеты роста для внешнегоодин к SOMETIMES и один для центра к ALWAYS.Если вам требуется некоторый интервал вокруг детей, вы можете использовать GridPane.setMargin (или заполнение самого GridPane, если вам требуется расстояние до краев для всех детей).

@Override
public void start(Stage primaryStage) {
    Button[] rightContent = new Button[3];
    for (int i = 0; i < rightContent.length; i++) {
        Button btn = new Button(Integer.toString(i));
        GridPane.setColumnIndex(btn, i);
        rightContent[i] = btn;
    }

    Button cycle = new Button("cycle");
    GridPane rgp = new GridPane(); // I would usually use a HBox here
    // don't grow larger than needed
    rgp.setMaxWidth(Region.USE_PREF_SIZE);

    // cycle though 0 to 3 buttons on the right
    cycle.setOnAction(new EventHandler<ActionEvent>() {
        int nextIndex = 0;

        @Override
        public void handle(ActionEvent event) {
            if (nextIndex >= rightContent.length) {
                rgp.getChildren().clear();
                nextIndex = 0;
            } else {
                rgp.getChildren().add(rightContent[nextIndex]);
                nextIndex++;
            }

        }
    });

    ColumnConstraints sideConstraints = new ColumnConstraints();
    sideConstraints.setHgrow(Priority.SOMETIMES);

    ColumnConstraints centerConstraints = new ColumnConstraints();
    centerConstraints.setHgrow(Priority.ALWAYS);

    //prefer to grow the center part of the GridPane
    GridPane root = new GridPane();
    root.getColumnConstraints().addAll(sideConstraints, centerConstraints, sideConstraints);

    root.add(cycle, 0, 0);
    root.add(rgp, 2, 0);

    // add something to visualize the center part
    // you could simply leave this part out
    Region center = new Region();
    center.setStyle("-fx-border-radius: 10;-fx-border-width: 1;-fx-border-color:black;");
    root.add(center, 1, 0);

    Scene scene = new Scene(root, 400, 300);
    primaryStage.setScene(scene);
    primaryStage.show();
}

Какупоминается в комментариях, регион center на самом деле не нужен.

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