Вложенная BorderPane с Canvas только растет, а не сжимается

У меня есть BorderPane, содержащий Canvas, со свойствами высоты и ширины Canvas, привязанными к свойствам BorderPane. BorderPane, в свою очередь, является корнем сцены.

Это все работает нормально. Если я изменяю размер окна, размер BorderPane изменяется в соответствии с размером сцены, а Canvas изменяется в соответствии с размером BorderPane.

Однако, если я введу еще одну BorderPane, она перестанет работать: внутренняя BorderPane и Canvas будут увеличиваться по мере роста Scene и внешней BorderPane, но когда я сжимаю окно, они не сжимаются.

  Working:            Not working:

 ┌──────────────┐    ┌────────────────┐
 │    Scene     │    │     Scene      │
 │┌────────────┐│    │┌──────────────┐│
 ││ BorderPane ││    ││  BorderPane  ││
 ││┌──────────┐││    ││┌────────────┐││
 │││  Canvas  │││    │││ BorderPane │││
 ││└──────────┘││    │││┌──────────┐│││
 │└────────────┘│    ││││  Canvas  ││││
 └──────────────┘    │││└──────────┘│││
                     ││└────────────┘││
                     │└──────────────┘│
                     └────────────────┘

Код, который работает:

BorderPane parent = new BorderPane();
Canvas canvas = new Canvas();
canvas.widthProperty().bind(parent.widthProperty());
canvas.heightProperty().bind(parent.heightProperty());
parent.setCenter(canvas);
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();

Код, который не работает:

BorderPane inner = new BorderPane();

Canvas canvas = new Canvas();
canvas.widthProperty().bind(inner.widthProperty());
canvas.heightProperty().bind(inner.heightProperty());
inner.setCenter(canvas);

BorderPane outer = new BorderPane();
outer.setCenter(inner);

Scene scene = new Scene(outer);
stage.setScene(scene);
stage.show();

Я добавил некоторые журналы, чтобы подтвердить проблему:

# scene, outer pane, inner pane, and canvas growing
outer width: 1364.0 -> 1374.0
scene width: 1364.0 -> 1374.0
outer height: 339.0 -> 342.0
scene height: 339.0 -> 342.0
canvas width: 1364.0 -> 1374.0
inner width: 1364.0 -> 1374.0
canvas height: 339.0 -> 342.0
inner height: 339.0 -> 342.0
# scene and outer pane shrinking, canvas and inner not
outer width: 1374.0 -> 1327.0
scene width: 1374.0 -> 1327.0
outer height: 342.0 -> 330.0
scene height: 342.0 -> 330.0
outer width: 1327.0 -> 1290.0
scene width: 1327.0 -> 1290.0
outer height: 330.0 -> 326.0
scene height: 330.0 -> 326.0

Очевидно, что в этом игрушечном примере я могу просто удалить промежуточный элемент BorderPane, но что, если я хочу создать многоразовый компонент с изменяемым размером, обертывающий этот Canvas? Как я могу убедиться, что его размер всегда изменяется вместе с родителем? А как обстоят дела с вложенными BorderPanes?


person David Moles    schedule 14.04.2018    source источник


Ответы (1)


Canvas — это неизменяемый узел. Это означает, что его размер является нижней границей min размера его родителя.

Если вы используете BorderPane в качестве корня сцены, изменение размера окна приводит к изменению размера сцены, а изменение размера сцены приводит к изменению размера корня сцены, чтобы он соответствовал размеру окна. По этой причине родитель Canvas сжимается ниже размера min, а Canvas тоже сжимается.

Если вы уменьшите размер BorderPane ниже его размера min, это не заставит дочерние элементы с изменяемым размером изменять размер ниже их размеров min, а вместо этого установит их размеры равными размеру min. Таким образом, BorderPane, обернутый в BorderPane, никогда не сжимается ниже размера Canvas, а Canvas никогда не сжимается.

Вы можете исправить это, установив для свойства managed Canvas значение false, в результате чего Canvas не будет учитываться при расчете размера min. (Обратите внимание, что неуправляемые дочерние элементы вообще не учитываются при размещении. Поэтому вы должны обернуть Canvas в Pane как единственный дочерний элемент, чтобы предотвратить нежелательные эффекты на одноуровневых элементах.)

Canvas canvas = ...
canvas.setManaged(false);
Pane canvasParent = new Pane(canvas);
canvas.widthProperty().bind(canvasParent.widthProperty());
canvas.heightProperty().bind(canvasParent.heightProperty());

// TODO: put canvasParent in the scene
person fabian    schedule 14.04.2018