TomSchimansky / CustomTkinter

A modern and customizable python UI-library based on Tkinter
MIT License
11.21k stars 1.06k forks source link

Add draggable option to CTk's widgets #1129

Open saiyam-sandhir opened 1 year ago

saiyam-sandhir commented 1 year ago

Please make widgets have an attribute called say "draggable" and set it default to False.

When the value of this option is True -users can drag the widget or at least be able to drag certain creative elements in canvas, or an image. -allow it to be draggable only inside its parent and not outside. -add some of your own creative ideas.

peer-pri commented 9 months ago

Yes please!

SCASTELLANO6044 commented 9 months ago

That would be awesome, it is a must have

jdsayle commented 1 month ago

(edited 7/18 to add Windows cursor bug & cleaned up code a bit)

I've slightly modified the code from this video: https://www.youtube.com/watch?v=6lIt0TI2cG0 which uses tkinter. I admit this isn't a perfect solution, but of all the code I've tried this was the only way I was able to get the entire widgets move and not just the text in them with customtkinter.

YMMV: On a Windows laptop, the cursor may 'drift' away from the label and button widget. Drift occurs when the widget is clicked and moved form the starting position. Mouse pointer will drift back toward the widget when it's moved back to the starting position. In my testing, this doesn't appear to happen if you have a second monitor and are displaying on the second screen. On the Mac I tested on this didn't occur at all 🤷

CODE:

import customtkinter

class myDragManager():
    def add_draggable_widget(self, widget):
        self.widget = widget
        self.root = widget.winfo_toplevel()
        self.widget.bind("<B1-Motion>", self.on_drag)

    def on_drag(self, event):
        self.widget.place(x=self.root.winfo_pointerx()-self.root.winfo_rootx(), y=self.root.winfo_pointery()-self.root.winfo_rooty())

win = customtkinter.CTk()
win.geometry("650x650")
win.title("Draggable Widgets")

style = customtkinter.CTkFont(size=20)

wrapper =  customtkinter.CTkFrame(win, bg_color="blue")
wrapper.pack(fill="both", expand=True)

label1 =  customtkinter.CTkLabel(wrapper, text="I am dragable label", font=style)
label1.place(x=10, y=10)

button =  customtkinter.CTkButton(wrapper, text="I am draggable button", font=style)
button.place(x=50, y=50)

mydrag1 = myDragManager()
mydrag1.add_draggable_widget(label1)

mydrag2 = myDragManager()
mydrag2.add_draggable_widget(button)

win.mainloop()