用find_overlapping()替换find_closest()解决博文“Python实现用鼠标拖动Canvas上的图形使其移动”的程序问题

博文“Python实现用鼠标拖动Canvas上的图形或图像使其移动”的程序有一个问题。鼠标点击图形能够拖动该图形。文章发表后,偶然发现鼠标点击图形外的邻近点,也能移动这个图形,这显然不合理。发现是因不正确地使用了Canvas的find_closest方法。Canvas上有许多图形实例,这个方法是发现距离某点最近的那个图形实例ID,并不要求该点必须在图形实例上,这就导致了上边的问题。很是抱歉发表了有问题的文章,希望大家原谅。
解决问题的方法是将其替换为Canvas的find_overlapping(x1,y1,x2,y2)方法,其参数定义了一个矩形,该方法是发现和这个矩形相交的所有图形实例ID。使用方法如下:
allID=cv.find_overlapping(event.x,event.y,event.x+1,event.y+1)
参数定义了一个很小的矩形,和图形相交,即鼠标单击点在图形内。下边是修改后的程序。

import tkinter as tk
root = tk.Tk()
root.geometry('300x300')
cv = tk.Canvas(root, height=300, width=300,bg='silver')
cv.pack()
def StartMove(event):
    global first_x,first_y,clickID
    allID=cv.find_overlapping(event.x, event.y, event.x+1, event.y+1)
    if len(allID) > 0:
        clickID=allID[0]       
        first_x,first_y = event.x,event.y
    else:
        clickID=-1  
def StopMove(event):
    global first_x,first_y,clickID
    #cv.move(clickID,event.x-first_x,event.y-first_y)
    clickID=-1    
def OnMotion(event):
    global first_x,first_y,clickID
    if clickID!=-1:
        cv.move(clickID,event.x-first_x,event.y-first_y)
        first_x,first_y = event.x,event.y
clickID=-1
cv.create_line(10, 10, 50, 50, activefill='red')
cv.create_oval(10,70,100,160,activefill='red')
cv.create_rectangle(50,120,150,180,fill='#CCFFFF',activefill='red')
cv.bind("",StartMove)  #绑定鼠标左键按下事件
cv.bind("",StopMove) #绑定鼠标左键松开事件
cv.bind("", OnMotion)      #绑定鼠标左键被按下时移动鼠标事件
root.mainloop()

你可能感兴趣的:(python,tkinter,PIL,python,鼠标拖动图形,canvas)