hoffstadt / DearPyGui

Dear PyGui: A fast and powerful Graphical User Interface Toolkit for Python with minimal dependencies
https://dearpygui.readthedocs.io/en/latest/
MIT License
13.31k stars 691 forks source link

user_data parameter for bind_item_handler_registry? #2283

Open giogina opened 9 months ago

giogina commented 9 months ago

Is your feature request related to a problem? Please describe. I am creating a lot of tree nodes dynamically, and binding the same item handler registry to each. I cannot figure out how to extract from within the callback function which tree node was clicked - the callback receives only the tag of the handler, no information about the item.

Describe the solution you'd like It would be useful to be able to do e.g.

node_handlers = dpg.add_item_handler_registry()
dpg.add_item_clicked_handler(parent=node_handlers, callback=callback)
for i in range(5):
    with dpg.tree_node(label=f"node {i}") as n:
        dpg.bind_item_handler_registry(n, node_handlers, user_data=n)

and have the user_data given to the callbacks; or always add extra arguments indicating the clicked item to the callbacks calls.

Describe alternatives you've considered

Additional context For background: I'm trying to implement a file explorer, where directories are displayed as tree nodes. I managed to include an open or closed folder icon in the label by replacing two characters in my font file by those icons; now I just need to switch between them when a tree node is opened or closed... Which seemed like the easiest part but somehow is not.

v-ein commented 9 months ago

I see that add_item_clicked_handler accepts user_data; but I have failed to figure out a method of providing variable item tags there.

Get user data directly from the tree node:

def callback(sender, app_data, handler_user_data):
    tree_node_user_data = dpg.get_item_user_data(app_data[1])
    print(f"Clicked: {tree_node_user_data}")

with dpg.item_handler_registry() as node_handlers:
    dpg.add_item_clicked_handler(callback=callback)

for i in range(5):
    with dpg.tree_node(label=f"node {i}", user_data=i) as n:
        dpg.bind_item_handler_registry(n, node_handlers)

Note: handler_user_data is what you pass in user_data on dpg.add_item_clicked_handler, so it won't work for you. I've just added it to show the full signature of the callback. You can remove that argument altogether.

This is only true for the last toggled-open node (which seems like a bug. Is that expected behaviour?),

Kind of expected, yes. See #1280. Unfortunately "toggled open" only works for nodes that have been opened (unlike Dear ImGui, where it works both ways). I hope one day to add an option to make it two-way again.

Am I supposed to create a separate item handler registry for every one of my (potentially very numerous) tree nodes?

No, absolutely not.

Edit: Finally found a workaround: Put a group inside every tree node, check for visibility of the groups upon click on any tree node.

I believe dpg.get_value on a tree node will tell you whether it's currently open or closed, so instead of adding an extra group, you can check get_value. Haven't tested it though. Anyway, proper use of user_data makes this unnecessary altogether.

giogina commented 9 months ago

Oooh thank you!!! I got as far as testing user_data in the tree node but had no clue about get_item_user_data. This one could really use a hint in the handlers section of the wiki ^^