何时以及为何需要将 window 坐标更改为 canvas 坐标?

When and why do I need to change a window coordinate to a canvas coordinate?

我试图通过给 canvas 一个回调来查看 window 坐标和 canvas 坐标之间的区别,该回调在两种类型中打印鼠标点击的坐标。我希望这两种类型的坐标具有不同的值,但它们没有。此外,我尝试将 window 坐标传递给 find_closest 方法,如 documentation 中所述,该方法接受 canvas 坐标,并且没有错误。

import tkinter as tk

def callback(event):
    canvas = event.widget
    print()
    print("Window x-coordinate:", event.x)
    print("Window y-coordinate:", event.y)
    x = canvas.canvasx(event.x)
    y = canvas.canvasy(event.y)
    print("Canvas x-coordinate:", x)
    print("Canvas y-coordinate:", y)
    print("closest:", canvas.find_closest(x, y))

master = tk.Tk()

frame = tk.Frame(master, width=50, height=50, bd=5, bg="green", relief="groove")
frame.pack_propagate(0)
frame.pack()

button = tk.Button(frame)
button.pack(fill="none")

canvas = tk.Canvas(master, bd=5, width=50, height=50, bg="red", relief="ridge")
canvas.bind("<Button-1>", callback)
canvas.pack_propagate(0)
canvas.pack()

master.mainloop()

如果您的 canvas 能够滚动,您只需要进行转换。否则在 window 和 canvas 坐标之间存在 1:1 映射。

您可以通过在创建 canvas:

之后的某个时刻将以下代码添加到示例中来查看这一点
canvas.configure(scrollregion=(0,0,1000,1000))
canvas.yview_moveto(.5)
canvas.xview_moveto(.5)

还有一个不常用的行为,就是canvasxcanvasy可以将坐标四舍五入到gridspacing单位的大小。

这里是canvasx方法的canonical description

Given a window x-coordinate in the canvas screenx, this command returns the canvas x-coordinate that is displayed at that location. If gridspacing is specified, then the canvas coordinate is rounded to the nearest multiple of gridspacing units.

您可以观察到,通过将对 canvasxcanvasy 的调用更改为如下所示,这将使 return 坐标始终是 2 的倍数。

x = canvas.canvasx(event.x, gridspacing=2)
y = canvas.canvasy(event.y, gridspacing=2)