hoffstadt/DearPyGui

user_data parameter for bind_item_handler_registry?

giogina opened this issue · 2 comments

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

  • 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.
  • Tried instead checking is_item_toggled_open for every tree node. This is only true for the last toggled-open node (which seems like a bug. Is that expected behaviour?), so it doesn't help me find out which node has been closed.
  • Am I supposed to create a separate item handler registry for every one of my (potentially very numerous) tree nodes? I suppose that might work, but considering every tree node is supposed to react the same way to a click, that seems excessive.
  • Edit: Finally found a workaround: Put a group inside every tree node, check for visibility of the groups upon click on any tree node. But still, I remain confused as to how the item handlers are supposed to be used when applied to more than one item.

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.

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.

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 ^^