您观察到的行为是由于事件的坐标相对于拖动的小部件而引起的。用 相对 坐标更新小部件的位置(在 绝对 坐标中)显然会导致混乱。 __
为了解决这个问题,我使用了
.winfo_x()和
.winfo_y()函数(允许将相对坐标转换为绝对坐标),并使用
Button-1事件来确定拖动开始时光标在小部件上的位置。
这是一个使小部件可拖动的函数:
def make_draggable(widget): widget.bind("<Button-1>", on_drag_start) widget.bind("<B1-Motion>", on_drag_motion)def on_drag_start(event): widget = event.widget widget._drag_start_x = event.x widget._drag_start_y = event.ydef on_drag_motion(event): widget = event.widget x = widget.winfo_x() - widget._drag_start_x + event.x y = widget.winfo_y() - widget._drag_start_y + event.y widget.place(x=x, y=y)可以这样使用:
main = tk.Tk()frame = tk.frame(main, bd=4, bg="grey")frame.place(x=10, y=10)make_draggable(frame)notes = tk.Text(frame)notes.pack()
如果您想采用一种更加面向对象的方法,则可以编写一个mixin,使类的所有实例均可拖动:
class DragDropMixin: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) make_draggable(self)
用法:
# 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):# passmain = tk.Tk()frame = DnDframe(main, bd=4, bg="grey")frame.place(x=10, y=10)notes = tk.Text(frame)notes.pack()



