JavaFX

时间:2017-04-22 11:15:08

标签: layout javafx resize containers region

我想编写一个扩展Region的新自定义容器类。此CustomContainer的子列表不应显示。它包含一个Pane(称为rootPane),后者又包含一个VBox。并且应该使用此VBox的子列表来真正将子项添加到容器中(可通过getInnerChildren访问)。这是它的简化结构。

我的问题是,添加一个新子节点导致CustomContainer本身的错误布局行为,以防边框应用于它,因为它的高度增长。但只是第一次加入孩子!这是一个非常简单的可执行Demo来测试它:

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();
    }
}

进一步提示:
- 它在高度上增长的大小等于边框的顶部宽度 - 如果用HBox替换VBox,则边框的左边宽度是决定性的 - 它与我重写的layoutChildren()方法有关。如果没有被覆盖,问题就不会出现(但当然我需要正确实现这个方法) - 如上所述,它只会在第一次添加孩子时出现。但删除它不会恢复大小 - &#34; specialAction&#34; method表示内部完成的一些逻辑。这是因为我想在内部添加和删除一些新的子项到CustomContainer(而不是VBox!)但是在向VBox添加子项时问题的出现方式相同。

如果您对我使用此容器的计划感到好奇:它将实现一些拖放行为,以便通过一些自定义视觉反馈来移动孩子。此视觉反馈将安装在CustomContainer的非公开子列表中 请不要建议改变容器结构。相反,我希望你能给我一些建议,为什么我的layoutChildren方法会导致这个问题,以及如何做到这一点。

1 个答案:

答案 0 :(得分:0)

尝试为节点设置最小宽度和高度。我的行为和你的行为非常相似,我遇到了这篇文章https://dzone.com/articles/size-does-matter-in-javafx,然后我将最小高度设置为我的AnchorPane,并且意外行为消失了。