tkinter中event的x/y鼠标坐标仅在快速向上移动时出错问题
故障原因
event.x与event.y返回的是鼠标相对于触发当前事件的控件的坐标,而非固定相对于主窗口的坐标。你代码中承载图片的label2默认会响应鼠标事件,当快速向上移动鼠标时,受tkinter事件循环的采样延迟影响,前一帧渲染的label2会刚好覆盖下一次鼠标移动到的点位,此时Motion事件的触发源从主窗口变为label2,返回的event.y是相对于label2顶部的坐标,数值会异常偏小,表现为坐标错误。- 向左、向右、向下移动鼠标时,鼠标不会进入
label2的覆盖区域,事件始终由主窗口触发,坐标正常;慢速向上移动时,事件采样间隔短,label2的渲染位置始终跟随在鼠标左上侧,不会被鼠标命中,因此也不会触发异常。
解决方法
方法一:全局坐标换算(推荐)
直接通过窗口方法获取鼠标相对于屏幕的绝对坐标,再减去主窗口左上角的屏幕坐标,得到固定相对于主窗口的坐标,无需关心事件触发源,修改motion函数即可:
def motion(event): global pos_x, pos_y # 换算得到鼠标相对于主窗口的准确坐标 pos_x = root.winfo_pointerx() - root.winfo_rootx() pos_y = root.winfo_pointery() - root.winfo_rooty() # 可选:添加边界限制,避免图片移出主窗口 pos_x = max(60, min(pos_x, root.winfo_width() - 60)) pos_y = max(110, min(pos_y, root.winfo_height() - 110)) label2.place(x=pos_x-60,y=pos_y-110) print('{}, {}'.format(pos_x, pos_y))
该方案无需修改其他逻辑,适配性最高。
方法二:禁用图片控件的鼠标事件响应
让承载图片的label2不响应任何鼠标事件,所有Motion事件始终由主窗口触发,保证event.x、event.y始终返回相对于主窗口的坐标,在创建label2的代码后添加一行配置即可:
label2 = tk.Label(root, image=bild1) label2.place(x=1,y=100) # 新增配置:禁用label2的鼠标事件响应 label2.bindtags(())
内容的提问来源于stack exchange,提问作者MarcoK
相关产品推荐
相关产品推荐

