Layout JavaFX中的意外布局行为

Layout JavaFX中的意外布局行为,layout,javafx,resize,containers,region,Layout,Javafx,Resize,Containers,Region,我想编写一个新的自定义容器类扩展区域。此CustomContainer的子列表不应可见。它包含一个窗格(称为rootPane),而该窗格又包含一个VBox。应该使用此VBox的子项列表将子项添加到容器中(可通过getInnerChildren访问)。这就是它的简化结构 我的问题是,添加一个新的子项会导致CustomContainer本身的错误布局行为,以防因为其高度增加而对其应用边框。但这只是第一次添加孩子!下面是一个非常简单的可执行演示来测试它: public class LayoutDemo

我想编写一个新的自定义容器类扩展区域。此CustomContainer的子列表不应可见。它包含一个窗格(称为rootPane),而该窗格又包含一个VBox。应该使用此VBox的子项列表将子项添加到容器中(可通过getInnerChildren访问)。这就是它的简化结构

我的问题是,添加一个新的子项会导致CustomContainer本身的错误布局行为,以防因为其高度增加而对其应用边框。但这只是第一次添加孩子!下面是一个非常简单的可执行演示来测试它:

public class LayoutDemo extends Application
{
    @Override
    public void start(Stage stage)
    {
        CustomContainer container = new CustomContainer(new Label("First Label"), new Label("Second Label"), new Label("Third Label"));
        // The border here is involved in the problem. In fact, only the top width has influence.
        container.setBorder(new Border(new BorderStroke(Color.GRAY, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(30, 3, 3, 3))));

        Button buttonAddNode = new Button("Add node");
        buttonAddNode.setOnAction(e -> container.specialAction());
        Button buttonSysout = new Button("Sysout height");
        buttonSysout.setOnAction(e -> System.out.println(container.getHeight()));

        HBox boxButtons = new HBox(10, buttonAddNode, buttonSysout);
        VBox sceneRoot = new VBox(20, container, boxButtons);
        sceneRoot.setPadding(new Insets(15)); // Just to make it look nicer.
        stage.setScene(new Scene(sceneRoot, 200, 200));
        stage.show();
    }

    public static class CustomContainer extends Region
    {
        private VBox innerBox = new VBox();
        private Pane rootPane = new StackPane(innerBox);

        public CustomContainer(Node... children)
        {
            getChildren().addAll(rootPane);
            getInnerChildren().addAll(children);
        }

        public void specialAction()
        {
            // Just for testing... Forces the CustomContainer to add a child to itself. And this is where the trouble begins...
            Node newChild = new Pane();
            newChild.setManaged(false); // I tried this, but it really has no influence.

            // The new child won't be visible in this test because it is not considered by layoutChildren(). But even layouting it would have no influence.
            getChildren().add(newChild);
        }

        @Override
        protected void layoutChildren()
        {
            System.out.println("LAYOUT");
            Insets borderInsets = getBorder().getInsets();
            double left = borderInsets.getLeft(),
                top = borderInsets.getTop(),
                width = getWidth() - left - borderInsets.getRight(),
                height = getHeight() - top - borderInsets.getBottom();
            layoutInArea(rootPane, left, top, width, height, 0, HPos.CENTER, VPos.CENTER);
        }

        public ObservableList<Node> getInnerChildren()
        {
            return innerBox.getChildren();
        }
    }

    public static void main(String... args)
    {
        launch();
    }
}
public类LayoutDemo扩展应用程序
{
@凌驾
公众假期开始(阶段)
{
CustomContainer容器=新CustomContainer(新标签(“第一标签”)、新标签(“第二标签”)、新标签(“第三标签”);
//这里的边界与问题有关。事实上,只有顶部宽度有影响。
container.setOrder(新边框(新边框笔划(Color.GRAY,BorderStrokeStyle.SOLID,CornerRadii.EMPTY,新边框宽度(30,3,3,3)));
Button buttonAddNode=新按钮(“添加节点”);
ButtonAdNode.setOnAction(e->container.specialAction());
Button buttonSysout=新按钮(“Sysout高度”);
按钮ysout.setOnAction(e->System.out.println(container.getHeight());
HBox-boxButtons=新的HBox(10,ButtonAdNode,buttonSysout);
VBox sceneRoot=新的VBox(20,容器,框按钮);
setPadding(新插图(15));//只是为了让它看起来更好。
舞台场景(新场景(sceneRoot,200200));
stage.show();
}
公共静态类CustomContainer扩展区域
{
私有VBox innerBox=新VBox();
私有窗格rootPane=新堆栈窗格(innerBox);
公共CustomContainer(节点…子节点)
{
getChildren().addAll(根窗格);
getInnerChildren().addAll(子对象);
}
公共空间专题()
{
//仅用于测试…强制CustomContainer向其自身添加子项。这就是问题的开始。。。
节点newChild=新窗格();
newChild.setManaged(false);//我尝试过这个,但它确实没有影响。
//新的子项在此测试中不可见,因为layoutChildren()不考虑它。但即使是LayoutIt也没有影响。
getChildren().add(newChild);
}
@凌驾
受保护的void layoutChildren()
{
系统输出打印(“布局”);
Insets borderInsets=getBorder().getInsets();
double left=borderInsets.getLeft(),
top=borderInsets.getTop(),
width=getWidth()-left-borderInsets.getRight(),
height=getHeight()-top-borderInsets.getBottom();
布局区域(根窗格、左侧、顶部、宽度、高度、0、HPos.CENTER、VPos.CENTER);
}
公共可观察列表getInnerChildren()
{
返回innerBox.getChildren();
}
}
公共静态void main(字符串…参数)
{
发射();
}
}
进一步提示:
-其高度增长的大小等于边框的顶部宽度。
-如果将VBox替换为HBox,则边框的左侧宽度将起决定性作用。
-这与我重写的layoutChildren()方法有关。如果未被覆盖,则不会出现问题(但我当然需要正确实现此方法)。
-如前所述,它仅在第一次添加子级时出现。但移除它不会恢复大小。
-“specialAction”方法表示一些内部完成的逻辑。这是因为我想在内部向CustomContainer(而不是VBox!)添加和删除一些新的子项,但在向VBox添加子项时,问题以相同的方式出现

如果你想知道我打算用这个容器做什么:它将实现一些拖放行为,通过一些定制的视觉反馈来移动孩子们。此视觉反馈将安装在CustomContainer的非公共子项列表中。

请不要建议改变容器结构。相反,我希望您能给我一些建议,说明为什么我的layoutChildren方法会导致此问题,以及如何正确处理此问题。

尝试设置节点的最小宽度和高度。我的行为与你的行为非常相似,我遇到了这篇文章,然后我为我的锚链设置了最小高度,意外的行为消失了。

没有。但解决方案是覆盖计算方法。