基于tkinter的30FPS鼠标活动检测程序问题求助
解决方案
先看修改后的完整代码:
from tkinter import * from datetime import datetime # 全局状态变量 is_touching = False counter_id = None # 保存after任务ID,用于取消重复任务 fps_interval = 1000 // 30 # 30FPS对应的时间间隔,约33ms root = Tk() root.geometry("500x500+0+0") root.title("Mouse Activity") def log_activity(activity_type): """统一日志记录逻辑,避免重复代码""" current_time = datetime.now().isoformat(sep=' ', timespec='milliseconds') print([[activity_type, current_time]], is_touching) def idle_counter(): """无鼠标活动时的定时检测""" global counter_id if not is_touching: log_activity(0) # 0代表无活动 counter_id = root.after(fps_interval, idle_counter) def start_active_detection(): """按住左键时启动30FPS的活动检测""" global is_touching, counter_id is_touching = True # 取消之前的无活动检测任务,避免重复执行 if counter_id is not None: root.after_cancel(counter_id) counter_id = None # 立即记录一次,再启动循环检测 log_activity(1) counter_id = root.after(fps_interval, active_loop) def active_loop(): """按住左键时的循环检测逻辑""" global is_touching, counter_id if is_touching: log_activity(1) # 1代表按住/拖动活动 counter_id = root.after(fps_interval, active_loop) def stop_active_detection(e): """释放左键时停止活动检测,恢复无活动检测""" global is_touching, counter_id is_touching = False log_activity(2) # 2代表释放按键 # 重新启动无活动检测 idle_counter() canvas = Canvas(root, bd=10, highlightthickness=0, width=500, height=500, bg="#ABFFFA") canvas.pack() box1 = canvas.create_rectangle(100,100,400,400,fill='white') # 绑定事件:按下左键启动活动检测,释放左键停止检测 canvas.tag_bind(box1, '<ButtonPress-1>', lambda e: start_active_detection()) canvas.tag_bind(box1, '<ButtonRelease-1>', stop_active_detection) # 启动初始的无活动检测 idle_counter() root.mainloop()
逐个问题解决说明
按住左键不动停止检测
原代码依赖<B1-Motion>事件(仅鼠标移动时触发),按住不动不会触发回调。现在绑定<ButtonPress-1>事件,按下左键就启动active_loop定时循环,每隔33ms自动记录一次活动,实现按住不动时的持续检测。按住未移动释放后帧率变快
之前释放按键时会重复启动counter(),导致多个检测任务同时运行。现在通过counter_id保存定时任务的ID,启动新任务前用after_cancel取消旧任务,确保同一时间只有一个检测循环在执行,避免帧率翻倍。启动时的线程错误
手动启动的Thread(target=handler2, args=())完全多余,且handler2需要事件参数e,线程调用时未传入导致报错。tkinter事件回调无需手动用线程触发,直接通过tag_bind绑定即可,删掉这段线程代码即可解决。
内容的提问来源于stack exchange,提问作者SM287
相关产品推荐
相关产品推荐

