How to spawn a popup menu from a Tree?

Godot Version

4.2.1

Question

I’m trying to create a Tree component and finding it a little complex. One of the things I want to do is right click an item in my tree to bring up a menu to provide editing options. I can’t see any way to do this. The Tree docs do have an event called custom_popup_edited, but there is no info on how this is used.

Do I need to add my own mouse handler by overriding _input(), or is there some other way to spawn a popup menu?

It looks like you probably want to use the custom_item_clicked signal and create your own popupmenu if it was a right click. The tree may be emitting a item_selected first so you might be able to track which one was clicked that way but I don’t know if it does. If it doesn’t select before the click signal then you’ll probably need to do some checking based on the local mouse position.

you could also do it using _input though _gui_input() is probably more appropriate.

custom_item_clicked never gets called. item_selected only gets called on left clicks, and only if the selection changes. _gui_input() never gets called either, but I can capture the mouse event on input()

Did you set the cell mode to custom? there’s a property to enable selecting with the right mouse button

I tried that, but custom_item_clipped still does nothing. Nor does _gui_input get called.

I’m setting the cell mode like this. All it does is make the text that I set no longer display.

root.set_cell_mode(0, TreeItem.CELL_MODE_CUSTOM)

Ah, figured it out, you have to set the text after setting the cell mode to custom. And you also need to set editable to true for that cell too. Tree is a big weird class, but after doing that it looks like it’s working for me.

The trouble with setting the cell mode to custom is that you can no longer edit the text of the line. You also don’t get the mouse position of where you click. There might be a way to configure things to get the event to fire, but I think overriding _input gives me the best results.


Tried making my own tree setup, honestly I’d probably just do a custom layout instead of using Tree, unless it’s a really simple setup. Right now it’s very specific to how it was designed to work in the editor and isn’t very useful outside of that.

EDIT: voi la Code for this example

This should work:

extends Tree


@onready var popup_menu: PopupMenu = $PopupMenu


func _ready() -> void:
	var root = create_item()
	root.set_text(0, "ROOT")
	for i in 10:
		var item = create_item(root)
		item.set_text(0, "Item %s" % (i+1))


func _gui_input(event: InputEvent) -> void:
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
			var item = get_item_at_position(event.position)
			item.select(0)
			popup_menu.popup_on_parent(Rect2(event.global_position, Vector2.ZERO))

Result:

1 Like

I kind of agree. Tree is really badly designed and hard to use to edit your data models. I’ve used tree controls in Qt and Java Swing, and they’re much easier to use than this.

I think the big problem with Tree (and ItemList too) is that they are just focused around building themselves and don’t really even try to present the data you’re trying to manage.

1 Like