• Godot HelpGUI
  • Why isn't the size of a HBox Container being updated automatically? I have to do it manually.

I have the following Control hierarchy:

  • ScrollContainer: min size: 468x372, Horizontal Enabled
    • A nested HBox: min size: 468x372 (_item_grids_container)

Then, dynamically, I add Grid containers items inside the HBox, where it grows horizontally: _item_grids_container.add_child(some_new_grid_node)

The problem is that both the size of the ScrollContainer and the HBox do not change dynamically, then in order to scroll to work, I have to change the size with code, as items are added/removed from the HBox.

I always knew that:

The size of the node's bounding rectangle, in pixels. Container nodes update this property automatically.

But for some reason for this specific setup I'm having to do that with code:

# HACK: Update the size of the container of grids	
# Is this a bug? Container nodes should have this updated automatically.
var ui_grid_item_size = _ui_inventory_grid_item.instance().get_size()
var padding = (_item_grids_container.get_constant("separation") * (_item_grids_container.get_child_count() - 1))
var base_width = (ui_grid_item_size.x * _item_grids_container.get_child_count())	
_item_grids_container.set_size(Vector2(base_width + padding, _item_grids_container.get_size().y))
  • alfredbaudisch I removed the "create_timer" and set_visible hacks and solved this with our good old friend:
    yield(get_tree(), "idle_frame")

    This is needed in many scenarios in Godot, sometimes we even need to wait more than a frame. So it also solved the HBox auto positioning.

I think it's because you are setting up min size on Hbox and Scroll Container. Try removing that and see if you get the desired results.

I think the size doesn't automatically refresh. Not sure if this is a bug (it sounds like a bug). I think if you quickly hide/show the node it will refresh.

@SkullReference @cybereality thank you.

I tried both solutions:

  1. Removing Min Size had no effect.
  2. Flashing visibility didn't work. Then I tried the following hack and now it works - a bit of delay is needed after the childs are added dynamically to the container:
_item_grids_container.set_visible(false)
yield(get_tree().create_timer(0.001), "timeout") 
_item_grids_container.set_visible(true)

Quite sure this is a bug (Godot 3.4.2). I'll report it.

    11 days later

    @cybereality said: I think the size doesn't automatically refresh. Not sure if this is a bug (it sounds like a bug). I think if you quickly hide/show the node it will refresh.

    The 'side effect' of yield suggests that the update to size for the box container is not immediate but deferred and processed on the next video frame. This makes enormous sense from the standpoint of efficiency -- wait until the container is completely updated before resizing it and its children,, otherwise each added child would trigger a new layout computation.

    Yes, that would be my understanding. The bug is that it should happen automatically on the next frame and does not. In the editor, you can simply show/hide the root node using the eye icon and that fixes it. So it's not even a code problem. It's just the way the engine works.

    The bug is that is should happen automatically on the next frame and does not.

    Yeah, this is the thing that should happen. Adding a yield after adding a child is just a hack to simulate the show/hide.

    4 months later

    alfredbaudisch I removed the "create_timer" and set_visible hacks and solved this with our good old friend:
    yield(get_tree(), "idle_frame")

    This is needed in many scenarios in Godot, sometimes we even need to wait more than a frame. So it also solved the HBox auto positioning.

    Yes, that is about the only thing I've found yield is actually necessary for.

    5 months later