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.36k stars 695 forks source link

What should I do if I want a certain drag-and-drop object to be compatible with multiple types #2433

Open Umbrella167 opened 3 days ago

Umbrella167 commented 3 days ago

image

CODE

import dearpygui.dearpygui as dpg import numpy as np

dpg.create_context() dpg.create_viewport(title='DD', width=800, height=500)

with dpg.window(label='Drag&Drop Window', width=-1, height=-1): with dpg.group(horizontal=True): with dpg.group(): dpg.add_text(default_value='sources:') dpg.add_input_int(label='freq', width=80, default_value=1, tag='freq')

        dpg.add_button(label='sin', tag='sin_src')
        with dpg.drag_payload(parent='sin_src', payload_type='A'):
            dpg.add_text('sin')

        dpg.add_button(label='cos', tag='cos_src')
        with dpg.drag_payload(parent='cos_src', payload_type='B'):
            dpg.add_text('cos')

        dpg.add_button(label='tan', tag='tan_src')
        with dpg.drag_payload(parent='tan_src', payload_type='C'):
            dpg.add_text('tan')
    with dpg.plot(label='Drag&Drop Plot', width=600, height=375, drop_callback=lambda: print(1),
                  payload_type='plotting'):
        dpg.add_plot_legend(drop_callback=lambda: print(2), payload_type='A')
        dpg.add_plot_axis(dpg.mvXAxis, label='x', tag='xaxis')
        dpg.add_plot_axis(dpg.mvYAxis, label='y1', drop_callback=lambda: print(3), payload_type='B')
        dpg.add_plot_axis(dpg.mvYAxis, label='y2', drop_callback=lambda: print(4), payload_type='A&B')
        dpg.add_plot_axis(dpg.mvYAxis, label='y3', drop_callback=lambda: print(5), payload_type='C')

dpg.setup_dearpygui() dpg.show_viewport() dpg.start_dearpygui() dpg.destroy_context()

What should I do if I want a certain drag-and-drop object to be compatible with multiple types? There is also how to add drop_callback to drawlist, window, etc.

nvglucifer commented 3 days ago

For drop callback to work, payload_type need to be specified the same.

Even droppable, you can accept/discard data depend on your user_data. user_data of drag/drop callback, or dpg.get_item_user_data(a_drag_payload_id) might help.

window and drawlist don't have these args: callback, drop_callback, drag_callback.

nvglucifer commented 3 days ago
import dearpygui.dearpygui as dpg
dpg.create_context()

def drag_cb(sender, app_data, user_data):
    # sender is btn_drag
    # app_data is btn_drag (value from drag_data)
    # do some configure(drawing_item), animation
    print(sender, app_data, user_data)
    ...

def drop_cb(sender, app_data, user_data):
    # sender is group, app_data is btn_drag
    dpg.move_item(app_data, parent=sender)

    print(sender, app_data, user_data)
    # user_data seem None all the time
    # but this solve the None above:
    target_drop_user_data = dpg.get_item_user_data(sender)

    # Slot 3: mvDragPayload - drag_payload(parent=btn_drag...)
    a_drag_payload_id = dpg.get_item_children(app_data, slot=3)[0]

    print(target_drop_user_data, dpg.get_item_user_data(a_drag_payload_id))

with dpg.window():
    with dpg.group(horizontal=True):

        with dpg.group(width=300, drop_callback=drop_cb, payload_type="int", user_data="dropped group"):
            dpg.add_text("Group left")
            dpg.add_button(label="not drag this")

        with dpg.child_window(width=300, height=300, drop_callback=drop_cb, payload_type="int", user_data="dropped child"):
            dpg.add_text("Child right")
            dpg.add_button(label="not drag this")
            btn_drag = dpg.add_button(label="drag me to another group then drop", drag_callback=drag_cb)

        with dpg.drag_payload(parent=btn_drag, drag_data=btn_drag, payload_type="int", user_data={btn_drag: "dragging/drop"}):
            dpg.add_text("dragging a button")

            # parent=btn_drag     --> this playload will appear if dragged from the btn_drag
            # drag_data=btn_drag  --> btn_drag will be app_data in the above drag_cb and drop_cb
            # payload_type="int"  --> btn_drag is an int, specified in this playload and drop target - two group above

dpg.create_viewport()
dpg.setup_dearpygui()
dpg.show_viewport()
while dpg.is_dearpygui_running():
    dpg.render_dearpygui_frame()
dpg.destroy_context()
Umbrella167 commented 3 days ago

For drop callback to work, payload_type need to be specified the same.

Even droppable, you can accept/discard data depend on your user_data. user_data of drag/drop callback, or dpg.get_item_user_data(a_drag_payload_id) might help.

window and drawlist don't have these args: callback, drop_callback, drag_callback.

Thank you for your reply , I know that you can pass multiple types through user data and then judge them in a callback, But I don't think it's elegant, The same payload type for multiple items will have a yellow border that tells you it is draggable, The different payload _ type does not display at all

nvglucifer commented 3 days ago

Yes, judge user_data; item's type, info, configuration, state ... in those callbacks might be the only way.

Umbrella167 commented 3 days ago

Yes, judge user_data; item's type, info, configuration, state ... in those callbacks might be the only way.

OK, I see, thank you very much for your reply