我对Python还比较陌生,目前正在尝试使用Tkinter,它看起来非常简单。我尝试使用以下代码实现一个简单的拖放效果(右键创建一个圆,左键允许拖动):
from tkinter import *
class Point:
def __init__(self, ref, x, y):
self.ref = ref
self.x = x
self.y = y
points = []
selected = None
def OnSelect(event):
global selected
for p in points:
if event.x>=(p.x-10) and event.y>=(p.y-10) and event.x<(p.x+10) and event.y<(p.y+10):
selected = p
break
def OnMMove(event):
if selected is not None:
selected.x = event.x
selected.y = event.y
canvas.coords(selected.ref, event.x-10, event.y-10, event.x+10, event.y+10)
def OnStopDrag(event):
global selected
selected = None
def OnCreate(event):
point = canvas.create_oval(event.x-10, event.y-10, event.x+10, event.y+10, fill="black")
points.append(Point(point, event.x, event.y))
window = Tk()
window.wm_title("Python")
canvas = Canvas(window, width=800, height=600, background='white')
canvas.bind("<Button-1>", OnSelect)
canvas.bind("<B1-Motion>", OnMMove)
canvas.bind("<ButtonRelease-1>", OnStopDrag)
canvas.bind("<Button-3>", OnCreate)
canvas.pack(fill=BOTH, expand=YES)
window.mainloop()
如您所见,这段代码中我使用了
canvas.cords
来移动拖拽的对象。当鼠标慢慢地拖拽时,一切都正常运作,但是当鼠标快速移动时,拖拽的圆似乎会在一个矩形范围内被部分裁剪,如下图所示(当拖拽停止或减缓时,整个圆将被正确地完整绘制):
我之前在Win32 C应用程序中使用GDI时也遇到过类似的问题,当调用屏幕无效时,重绘窗口客户区域仅覆盖当前拖拽圆的初始位置。实际上,在我的示例代码中创建的窗口位于不断完全重绘的窗口上方,例如视频游戏窗口时,拖拽元素时的裁剪效果不会出现,拖拽时整个圆会被正确地重绘。
是否有一种方法可以解决这个问题,例如设置画布使窗口无效时调用更广泛或整个客户区域?我想坚持使用Tkinter,所以我对切换到另一个GUI API/框架不是很感兴趣。此代码已在Windows 10上进行了测试。