Arrastrar y soltar widgets tkinter

Estoy tratando de hacer un progtwig Python en el que puedas moverte por los widgets.

Este es mi código:

import tkinter as tk main = tk.Tk() notesFrame = tk.Frame(main, bd = 4, bg = "a6a6a6") notesFrame.place(x=10,y=10) notes = tk.Text(notesFrame) notes.pack() notesFrame.bind("", lambda event: notesFrame.place(x = event.x, y = event.y) 

Pero, esto se vuelve súper glitchy y el widget salta de un lado a otro.

¡Gracias!

El comportamiento que estás observando es causado por el hecho de que las coordenadas del evento son relativas al widget arrastrado. Actualizar la posición del widget (en coordenadas absolutas ) con coordenadas relativas obviamente resulta en un caos.

Para solucionar esto, he usado las .winfo_x() y .winfo_y() (que permiten convertir las coordenadas relativas en absolutas), y el evento Button-1 para determinar la ubicación del cursor en el widget cuando comienza el arrastre . La siguiente es una mezcla que hace que un widget se pueda arrastrar.

 class DragDropMixin: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.drag_start_x = 0 self.drag_start_y = 0 self.bind("", self.drag_start) self.bind("", self.drag_motion) def drag_start(self, event): self.drag_start_x = event.x self.drag_start_y = event.y def drag_motion(self, event): x = self.winfo_x() - self.drag_start_x + event.x y = self.winfo_y() - self.drag_start_y + event.y self.place(x=x, y=y) 

Uso:

 # As always when it comes to mixins, make sure to # inherit from DragDropMixin FIRST! class DnDFrame(DragDropMixin, tk.Frame): pass # This wouldn't work: # class DnDFrame(tk.Frame, DragDropMixin): # pass main = tk.Tk() frame = DnDFrame(main, bd=4, bg="grey") frame.place(x=10, y=10) notes = tk.Text(frame) notes.pack() 

Tkinter tiene un módulo para esto, documentado en la cadena de documentación del módulo. Se esperaba que fuera reemplazado por un módulo tk dnd, pero esto no ha sucedido. Nunca lo he probado. Buscando SO para [tkinter] dnd devuelve esta página . A continuación se muestra el comienzo de la cadena de documentación.

 >>> from tkinter import dnd >>> help(dnd) Help on module tkinter.dnd in tkinter: NAME tkinter.dnd - Drag-and-drop support for Tkinter. DESCRIPTION This is very preliminary. I currently only support dnd *within* one application, between different windows (or within the same window). [snip]