pythondearpygui

Adding Drag and Drop in DearpyGUI=2.0.0/Python3.12 in Ubuntu


Using DearpyGUI, I'm trying to add some drag and drop functionality.

I tried to attach parent and also child components, it is still not working and the "d.pending_events" is printing 0 even if I drag and drop an image or file.

this is the output when I run the script

(env_312) (base) xam a@xam-58:~/Desktop/Python/310py$ python test1.py ✅ Found Parent window: 0x800df0 🔎 Dumping window tree: ↳ 0x800df0 name: Drag-and-Drop-Example ↳ 0x800df1 name: None ↳ 0x2a00009 name: Drag-and-Drop-Example Child: 0x2a00009, name: Drag-and-Drop-Example

import dearpygui.dearpygui as dpg 
import threading 
import time from Xlib 
import X, display, Xatom


#PARENT  
def _func_find_window_by_name(name, d):
    # d = display.Display()
    root = d.screen().root

    def search(w):
        for child in w.query_tree().children:
            try:
                win_name = child.get_wm_name()
                if win_name and name in win_name:
                    return child
                result = search(child)
                if result:
                    return result
            except:
                pass
        return None

    return search(root)


#CHILDREN 
def find_real_content_window(parent):
    for child in parent.query_tree().children:
        name = child.get_wm_name()
        if name:
            print(f"Child: {hex(child.id)}, name: {name}")
        if name and "Drag-and-Drop-Example" in name:
            # print(f"Found content window: {hex(child.id)}")
            return child
    return parent  # fallback


def _func_setup_xdnd(win, d):
    XdndAware = d.intern_atom("XdndAware")
    win.change_property(XdndAware, Xatom.ATOM, 32, [5])
    d.flush()

    # Verify
    prop = win.get_full_property(XdndAware, Xatom.ATOM)
    if prop:
        print(f"✅ XdndAware property set correctly: {prop.value}")
        print(f"✅ Using child content window: {hex(win.id)}")
    else:
        print("❌ Failed to set XdndAware property.")


def _func_xdnd_loop(win, d):
    XdndEnter = d.intern_atom("XdndEnter")
    XdndPosition = d.intern_atom("XdndPosition")
    XdndDrop = d.intern_atom("XdndDrop")
    XdndSelection = d.intern_atom("XdndSelection")
    UTF8_STRING = d.intern_atom("UTF8_STRING")

    print(f"👂 Listening for XDND events on: {hex(win.id)}")

    while True:
        print(d.pending_events())
        if d.pending_events():
            print("🔄 Processing pending events...")
    # #         e = d.next_event()
    # #         if e.type == X.ClientMessage:
    # #             if e.client_type == XdndEnter:
    # #                 print("📥 Drag entered")
    # #             elif e.client_type == XdndPosition:
    # #                 print("📍 Drag position updated")
    # #             elif e.client_type == XdndDrop:
    # #                 print("📦 Drop detected!")
    # #                 # Ask for the selection contents
    # #                 win.convert_selection(XdndSelection, UTF8_STRING, X.CurrentTime)
    # #         elif e.type == X.SelectionNotify:
    # #             prop = win.get_full_property(e.property, 0)
    # #             if prop:
    # #                 uris = prop.value.decode("utf-8").strip().splitlines()
    # #                 for uri in uris:
    # #                     if uri.startswith("file://"):
    # #                         path = uri[7:]  # strip file://
    # #                         print(f"📄 Dropped file: {path}")
    # #                         # TODO: update DPG UI here if you want
        else:
            time.sleep(0.01)


def dump_tree(w, level=0):
    indent = "  " * level
    name = w.get_wm_name()
    print(f"{indent}↳ {hex(w.id)}  name: {name}")
    for child in w.query_tree().children:
        dump_tree(child, level+1)

dpg.create_context() dpg.create_viewport(title='Drag-and-Drop-Example', width=400, height=300)


with dpg.window(label="main-window", tag="main-window", no_close=True):
    dpg.add_text("🗂 Drag a file from Nautilus here!")


dpg.setup_dearpygui() dpg.show_viewport()

time.sleep(2)
# dpg.set_primary_window("main-window", True)

d = display.Display() win =
_func_find_window_by_name("Drag-and-Drop-Example", d) if not win:
    raise Exception("Could not find DPG window") print(f"✅ Found Parent window: {hex(win.id)}")

print("🔎 Dumping window tree:") dump_tree(win)

win = find_real_content_window(win)

_func_setup_xdnd(win, d)

threading.Thread(target=_func_xdnd_loop, args=(win, d), daemon=True).start()

while dpg.is_dearpygui_running():
    dpg.render_dearpygui_frame()


dpg.destroy_context() 

Solution

  • I already fix it by adding this line inside "xdnd_event_loop" function.

    
        # THIS IS CRUCIAL:
        win.change_attributes(event_mask=X.PropertyChangeMask | X.StructureNotifyMask | X.SubstructureNotifyMask)
        d.flush()
        
        while True:
            while d.pending_events():