当我 scan_dragto 平移我的 canvas 时,所有 canvas 项目 "move" 正确但它们的坐标没有改变

When I scan_dragto to pan my canvas, all canvas items "move" properly but their coordinates don't change

请记住,我绝不会将自己称为任何类型的程序员,所以请对我宽容一点,并像我是 5 岁的孩子一样解释它。

我希望能够平移视口 (canvas) 并让 canvas 项目跟随并且还能够分别移动它们中的每一个。 在创建两个示例矩形时,我给了它们默认坐标,如果我点击它们并拖动它们,它们就会正确移动。

在我平移 canvas 并尝试点击矩形后,尽管它们看起来好像移动正确,但我无法点击它们但是如果我点击它们仍然可以获得注册点击他们在锅前的位置。

from tkinter import *

def make():
    #makes a rectangle(for now)
    global lbl,lbl2
    lbl2=canvas.create_rectangle(50,30,70,50,fill="white",tags="tag")
    lbl=canvas.create_rectangle(20,0,40,20,fill="red",tags="tag")


def click_on_nodes(event):
    #start position of a rectangle when we click to move it(found online)
    global selected
    selected = canvas.find_overlapping(event.x-5, event.y-5, event.x+5, event.y+5)
    if selected:
        canvas.tag_raise(selected)
        canvas.selected = selected[-1]  # select the top-most item
        canvas.startxy = (event.x, event.y)
        print(canvas.selected, canvas.startxy)
    else:
        canvas.selected = None
        print("none")

def drag_the_node(event):
    #position of rectangle while dragging it
    if selected:
        print(f"coords are: {canvas.coords(lbl)}")

        # calculate distance moved from last position
        dx, dy = event.x-canvas.startxy[0], event.y-canvas.startxy[1]
        # move the selected item
        canvas.move(canvas.selected, dx, dy)
        # update last position
        canvas.startxy = (event.x, event.y)
    else:
        canvas.selected==None

def pan_click(event):
    canvas.scan_mark(event.x,event.y)

def pan_move(event):
    canvas.scan_dragto(event.x,event.y,gain=1)
    print(f" winfox: {canvas.coords(lbl)}")

root=Tk()
canvas=Canvas(root,bg="#222222",width=500,height=500)
canvas.pack()
make()

#move the rectangles LEFT CLICK
canvas.bind("<Button-1>",click_on_nodes,add="+")
canvas.bind("<B1-Motion>",drag_the_node,add="+")

#pan the viewport RIGHT CLICK
canvas.bind("<ButtonPress-3>",pan_click)
canvas.bind("<B3-Motion>",pan_move)
canvas.bind("<ButtonRelease-3>",mouse_up)

root.mainloop()

最初 canvas 的原点 (0, 0) 位于视口的左上角,因此 event.xevent.y(坐标相对于顶部- canvas) 的左角与实际坐标匹配。

但是通过平移改变视口后,两个坐标系不同步。您需要使用 canvas.canvasx()canvas.canvasy():

(event.x, event.y) 转换为 canvas 坐标系
def click_on_nodes(event):
    #start position of a rectangle when we click to move it(found online)
    global selected
    # convert (event.x, event.y) to canvas coordinates
    x, y = canvas.canvasx(event.x), canvas.canvasy(event.y)
    selected = canvas.find_overlapping(x-5, y-5, x+5, y+5)
    if selected:
        canvas.tag_raise(selected)
        canvas.selected = selected[-1]  # select the top-most item
        canvas.startxy = (x, y)
        print(canvas.selected, canvas.startxy)
    else:
        canvas.selected = None
        print("none")

def drag_the_node(event):
    #position of rectangle while dragging it
    if selected:
        print(f"coords are: {canvas.coords(lbl)}")
        # convert (event.x, event.y) to canvas coordinates
        x, y = canvas.canvasx(event.x), canvas.canvasy(event.y)
        # calculate distance moved from last position
        dx, dy = x-canvas.startxy[0], y-canvas.startxy[1]
        # move the selected item
        canvas.move(canvas.selected, dx, dy)
        # update last position
        canvas.startxy = (x, y)
    else:
        canvas.selected==None