我正在尝试创建一个Python程序,您可以在其中移动小部件。
这是我的代码:
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("<B1-Motion>", lambda event: notesFrame.place(x = event.x, y = event.y)
但是,这会出现超级故障并且小部件来回跳跃。
谢谢!
答案 0 :(得分:12)
您观察到的行为是由事件的坐标相对于拖动的窗口小部件引起的。使用相对坐标更新窗口小部件的位置(在绝对坐标中)显然会导致混乱。
要解决此问题,我已使用.winfo_x()
and .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.y
def 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):
# pass
main = tk.Tk()
frame = DnDFrame(main, bd=4, bg="grey")
frame.place(x=10, y=10)
notes = tk.Text(frame)
notes.pack()
答案 1 :(得分:2)
Tkinter有一个模块,记录在模块docstring中。预计它会被tk dnd模块取代,但这种情况并没有发生。我从来没有尝试过。搜索SO [tkinter] dnd
会返回this page。下面是docstring的开头。
>>> 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]