Automatically set size of Panel Node, based on it's children

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By HalfTough

I want to have a simple Panel with buttons on it.

So I made new Panel node, gave it HBoxContainer and put some Buttons inside HBoxContainer.

Problem is – height of my Panel is 0. Buttons are visible, but Panel is not. I can change it manually, but after I tinker with my layout a bit it goes back to 0.

Can I have a Panel that adjusts itself to it’s content?

I think that’s definitely possible, but I don’t know how off the top of my head.I will try to fiddle with it in a few hours if you don’t get an answer by them.

Diet Estus | 2018-05-16 14:10

:bust_in_silhouette: Reply From: BIGbirddy

Try to use PanelContainer, as what a container does is organizing its children automatically. If you use Panel, it won’t take care of them.

Here’s a sample code for my simple hiearchy:
PanelContainer
|HBoxContainer

For testing, simply add / remove a button by pressing action(‘add’) / action(‘subtract’)

extends PanelContainer

# Reference
onready var hbox_container = $HBoxContainer 

# Helper variable
onready var mim_size = rect_size  # get initial size when ready

func _ready():
	set_process_input(true)


func _input(event):
	if event.is_action_pressed("add"):
		add_button()
		
	elif event.is_action_pressed("subtract"):
		remove_button()


func add_button():
	var btn = Button.new()
	btn.text = "Button"
	hbox_container.add_child(btn)


func remove_button():
	var ch = hbox_container.get_child(0)
	if ch != null:
		ch.hide()
		shrink_size()
		ch.queue_free()


func shrink_size():
	rect_size = mim_size

Note that PanelContainer only resizes its rect when it needs to expand, but not when it can shrink. (I guess the dev should add this feature, if I’m not wrong)
So I manually set it to min_size after the button has been hidden.

And you don’t necessarily need to do this when handling resize:

ch.hide()
shrink_size()
ch.queue_free()

you can do:

ch.free()
shrink_size()

(the first approach is safer though)

Result

And for more gerneral purpose, you can call shrink function when your box container emit sort_children signal, instead of calling shrink when you do an operation everytime.

BIGbirddy | 2019-02-02 09:08