我在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()

不,我想,我的鼠标相对于红色边框的正确坐标被打印出来.但是,当我将鼠标悬停在按钮上时,坐标会发生变化,不再根据红色窗口框表示真实坐标.

有人有解决办法吗?

推荐答案

Binding Motion with Root vs Other Widgets:

在试用了您的代码之后,我做了以下观察:

  1. Motion事件绑定到root时,(event.x, event.y)返回窗口中任何像素相对于像素所在的小部件的坐标.相应小部件(不是root)的左上角被认为是(0,0).
  2. 如果将Motion事件绑定到特定小部件,则仅当像素存在于小部件directly内时,(event.x, event.y)才会返回像素(相对于小部件)的坐标.如果将鼠标悬停在子部件上,则不会打印任何内容.

解决方案:

现在,说到你的问题,当鼠标悬停在按钮上时,你不能直接从(event.x, event.y)计算画布坐标.您必须进行以下转换.

window_coords = topleft_button_coordinates + (event.x, event.y)
canvas_coords = canvas.canvasx(window_coords.x), canvas.canvasy(window_coords.y)

只有当坐标相对于按钮时,才能执行上述转换.可以使用event.widget属性判断事件是否由按钮触发.

按钮左上角的坐标(相对于画布)可以使用.winfo_x().winfo_y()获得.


Working Code:

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相关问答推荐

云上Gunicorn的Flask-socketIO无法工作

解析讨论论坛只给我第一个用户 comments ,但没有给我其他用户回复

CustomTKinter-向表单添加额外的输入字段

Flask主机持续 bootstrap 本地IP| Python

合并同名列,但一列为空,另一列包含值

sys.modulesgo 哪儿了?

如何用symy更新分段函数

计算所有前面行(当前行)中列的值

将jit与numpy linSpace函数一起使用时出错

如何使用matplotlib在Python中使用规范化数据和原始t测试值创建组合热图?

Python json.转储包含一些UTF-8字符的二元组,要么失败,要么转换它们.我希望编码字符按原样保留

如何在polars(pythonapi)中解构嵌套 struct ?

在Wayland上使用setCellWidget时,try 编辑QTable Widget中的单元格时,PyQt 6崩溃

try 将一行连接到Tensorflow中的矩阵

pyscript中的压痕问题

为什么抓取的HTML与浏览器判断的元素不同?

使用groupby方法移除公共子字符串

如何从需要点击/切换的网页中提取表格?

Python Pandas获取层次路径直到顶层管理

OpenCV轮廓.很难找到给定图像的所需轮廓