Tkinter 鼠标指针无法悬停在按钮上
Tkinter mouse pointer not working for hovering over button
我在 Python Tkinter 中的鼠标指针有问题。
我有以下代码:
import tkinter as tk
root = tk.Tk()
def motion(event):
x, y = window_canvas.canvasx(event.x), window_canvas.canvasy(event.y)
print('{}, {}'.format(x, y))
window_canvas = tk.Canvas(root, borderwidth=0, background="white", width = 300, height = 300, highlightthickness=0)
window_canvas.pack(fill='both')
window_frame = tk.Frame(window_canvas, background='red', borderwidth=0, width = 300, height = 300)
window_frame.pack()
button = tk.Button(window_frame, text=' ', borderwidth=1, highlightbackground='#9c9c9c', bg='black')
button.place(x=50, y=50)
root.bind('<Motion>', motion)
root.mainloop()
不,我想要打印出我的鼠标相对于红框的正确坐标。但是,当我将鼠标悬停在按钮上时,坐标会发生变化,并且不再根据红色 window_frame 表示真实坐标。
有人有解决办法吗?
绑定 Motion
与根与其他小部件:
在试验了您的代码后,我做出了以下观察:
- 当
Motion
事件绑定到root时,(event.x, event.y)
returnswindow中任意像素相对于该像素所在widget的坐标。对应widget(非root
)的左上角取为(0, 0).
- 如果您将
Motion
事件绑定到特定的小部件,(event.x, event.y)
returns 像素的坐标(相对于小部件)仅当像素存在时 直接在小部件内。如果将鼠标悬停在子窗口小部件上,则不会打印任何内容。
解决方案:
现在,来到你的问题,当鼠标悬停在按钮上时,你不能直接从 (event.x, event.y)
计算 canvas 坐标。您将必须进行以下转换。
window_coords = topleft_button_coordinates + (event.x, event.y)
canvas_coords = canvas.canvasx(window_coords.x), canvas.canvasy(window_coords.y)
只有当坐标是相对于按钮时,才必须进行上述转换。您可以使用 event.widget
属性来检查事件是否由按钮触发。
按钮左上角的坐标(相对于canvas)可以通过.winfo_x()
和.winfo_y()
获得。
工作代码:
import tkinter as tk
root = tk.Tk()
def motion(event):
global button
convx, convy = event.x, event.y
if event.widget == button:
convx, convy = button.winfo_x() + event.x, button.winfo_y() + event.y
x, y = window_canvas.canvasx(convx), window_canvas.canvasy(convy)
print('{}, {}'.format(x, y))
window_canvas = tk.Canvas(root, borderwidth=0, background="white", width = 300, height = 300, highlightthickness=0)
window_canvas.pack(fill='both')
window_frame = tk.Frame(window_canvas, background='red', borderwidth=0, width = 300, height = 300)
window_frame.pack()
button = tk.Button(window_frame, text=' ', borderwidth=1, highlightbackground='#9c9c9c', bg='black')
button.place(x=50, y=50)
root.bind('<Motion>', motion)
root.mainloop()
我在 Python Tkinter 中的鼠标指针有问题。
我有以下代码:
import tkinter as tk
root = tk.Tk()
def motion(event):
x, y = window_canvas.canvasx(event.x), window_canvas.canvasy(event.y)
print('{}, {}'.format(x, y))
window_canvas = tk.Canvas(root, borderwidth=0, background="white", width = 300, height = 300, highlightthickness=0)
window_canvas.pack(fill='both')
window_frame = tk.Frame(window_canvas, background='red', borderwidth=0, width = 300, height = 300)
window_frame.pack()
button = tk.Button(window_frame, text=' ', borderwidth=1, highlightbackground='#9c9c9c', bg='black')
button.place(x=50, y=50)
root.bind('<Motion>', motion)
root.mainloop()
不,我想要打印出我的鼠标相对于红框的正确坐标。但是,当我将鼠标悬停在按钮上时,坐标会发生变化,并且不再根据红色 window_frame 表示真实坐标。
有人有解决办法吗?
绑定 Motion
与根与其他小部件:
在试验了您的代码后,我做出了以下观察:
- 当
Motion
事件绑定到root时,(event.x, event.y)
returnswindow中任意像素相对于该像素所在widget的坐标。对应widget(非root
)的左上角取为(0, 0). - 如果您将
Motion
事件绑定到特定的小部件,(event.x, event.y)
returns 像素的坐标(相对于小部件)仅当像素存在时 直接在小部件内。如果将鼠标悬停在子窗口小部件上,则不会打印任何内容。
解决方案:
现在,来到你的问题,当鼠标悬停在按钮上时,你不能直接从 (event.x, event.y)
计算 canvas 坐标。您将必须进行以下转换。
window_coords = topleft_button_coordinates + (event.x, event.y)
canvas_coords = canvas.canvasx(window_coords.x), canvas.canvasy(window_coords.y)
只有当坐标是相对于按钮时,才必须进行上述转换。您可以使用 event.widget
属性来检查事件是否由按钮触发。
按钮左上角的坐标(相对于canvas)可以通过.winfo_x()
和.winfo_y()
获得。
工作代码:
import tkinter as tk
root = tk.Tk()
def motion(event):
global button
convx, convy = event.x, event.y
if event.widget == button:
convx, convy = button.winfo_x() + event.x, button.winfo_y() + event.y
x, y = window_canvas.canvasx(convx), window_canvas.canvasy(convy)
print('{}, {}'.format(x, y))
window_canvas = tk.Canvas(root, borderwidth=0, background="white", width = 300, height = 300, highlightthickness=0)
window_canvas.pack(fill='both')
window_frame = tk.Frame(window_canvas, background='red', borderwidth=0, width = 300, height = 300)
window_frame.pack()
button = tk.Button(window_frame, text=' ', borderwidth=1, highlightbackground='#9c9c9c', bg='black')
button.place(x=50, y=50)
root.bind('<Motion>', motion)
root.mainloop()