Search code examples
pythontkintercustomtkinter

Tkinter, CustomTkinter drag widget


I'm doing a file

I know I can drop files in to my window thanks to tkinterdnd2 and thanks to this creds: Using drag and drop files or file picker with CustomTkinter

class CTkDND(ctk.CTk, TkinterDnD.DnDWrapper):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.TkdndVersion = TkinterDnD._require(self)

but I want to be able to drag a widget(label with file name) from the window, and maybe put it in desktop or in another explorer



new_label.bind("<ButtonPress-1>",   lambda event, label=new_label: self.on_drag_start(event, label))new_label.bind("<ButtonRelease-1>", lambda event, label=new_label: self.on_drag_end(event, label))
def on_drag_start(self, event, label):
     data = label.cget("text")
     label.dnd_start(data, DND_FILES)  
def on_drag_end(self, event, label):
     pass

Solution

  • If you want a label widget as a drag source, you need to call .drag_source_register() and .dnd_bind() on that label. Use DND_FILES if you want the data to be a filename.

    Below is a example:

    from pathlib import Path
    import customtkinter as ctk
    from tkinterdnd2 import TkinterDnD, COPY, DND_FILES
    
    class CTkDND(ctk.CTk, TkinterDnD.DnDWrapper):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.TkdndVersion = TkinterDnD._require(self)
            self.geometry("400x200")
    
            # note that file path is in Posix format
            filename = Path(__file__).as_posix()
            new_label = ctk.CTkLabel(self, text=filename)
            new_label.pack(expand=1)
    
            # attribute _label is the real tkinter label widget
            new_label._label.drag_source_register(1, DND_FILES)
            new_label._label.dnd_bind("<<DragInitCmd>>", self.on_drag_init)
    
        def on_drag_init(self, event):
            filename = event.widget.cget("text")
            return COPY, DND_FILES, filename
    
    app = CTkDND()
    app.mainloop()