177 lines
7.8 KiB
Python
177 lines
7.8 KiB
Python
import time
|
||
import threading
|
||
from pynput import keyboard
|
||
from pynput.keyboard import Key, Controller
|
||
|
||
|
||
class AutoKeyPresser:
|
||
# =============== 全局配置 ===============
|
||
CONTROL_KEY = 'p' # 控制定时器启动/暂停的快捷键
|
||
TARGET_KEY = Key.f10 # 要自动按下的目标键(默认为F10)
|
||
INTERVAL = 60 + 52 # 定时器间隔时间(1分钟52秒 = 112秒)
|
||
|
||
# =============== 结束配置 ===============
|
||
|
||
def __init__(self):
|
||
self.timer = None
|
||
self.is_active = False
|
||
self.listener = None
|
||
self.keyboard_controller = Controller()
|
||
self.ignore_next_key = False # 标志位,用于忽略程序自动按下的目标键
|
||
self.timer_lock = threading.Lock() # 线程锁确保状态同步
|
||
self.last_activity_time = 0 # 记录最后一次活动时间
|
||
|
||
def simulate_key_press(self):
|
||
"""模拟按下配置的目标键"""
|
||
try:
|
||
self.ignore_next_key = True # 设置标志,忽略接下来的目标键事件
|
||
# 使用正确的键模拟
|
||
self.keyboard_controller.press(self.TARGET_KEY)
|
||
time.sleep(0.05) # 短暂延迟模拟真实按键
|
||
self.keyboard_controller.release(self.TARGET_KEY)
|
||
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
key_name = self._get_key_name(self.TARGET_KEY)
|
||
print(f"[{current_time}] 已自动按下 {key_name} 键")
|
||
except Exception as e:
|
||
print(f"模拟按下 {self._get_key_name(self.TARGET_KEY)} 时发生错误: {e}")
|
||
|
||
def _get_key_name(self, key):
|
||
"""获取按键的可读名称"""
|
||
if hasattr(key, 'name'):
|
||
return key.name.upper()
|
||
elif hasattr(key, 'char'):
|
||
return key.char.upper()
|
||
return str(key)
|
||
|
||
def start_timer(self):
|
||
"""启动定时器(总是重新开始112秒计时)"""
|
||
with self.timer_lock:
|
||
if self.is_active:
|
||
return
|
||
|
||
self.is_active = True
|
||
self.last_activity_time = time.time() # 重置开始时间
|
||
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
key_name = self._get_key_name(self.TARGET_KEY)
|
||
print(f"[{current_time}] 定时器已启动,将在{self.INTERVAL}秒后按下 {key_name} 键")
|
||
print(f"按 {self.CONTROL_KEY.upper()} 键可以暂停定时器")
|
||
|
||
def timer_loop():
|
||
# 记录本次循环的开始时间
|
||
cycle_start_time = time.time()
|
||
|
||
while self.is_active:
|
||
# 计算已经过去的时间
|
||
elapsed_time = time.time() - cycle_start_time
|
||
remaining_time = self.INTERVAL - elapsed_time
|
||
|
||
# 如果已经达到或超过间隔时间,执行按键操作
|
||
if remaining_time <= 0:
|
||
if self.is_active: # 再次检查状态
|
||
self.simulate_key_press()
|
||
# 重置循环开始时间,开始新的周期
|
||
cycle_start_time = time.time()
|
||
continue
|
||
|
||
# 分段等待,便于及时响应暂停命令
|
||
wait_interval = min(0.5, remaining_time) # 每次最多等待0.5秒
|
||
if wait_interval > 0:
|
||
time.sleep(wait_interval)
|
||
|
||
self.timer = threading.Thread(target=timer_loop)
|
||
self.timer.daemon = True
|
||
self.timer.start()
|
||
|
||
def pause_timer(self):
|
||
"""暂停定时器"""
|
||
with self.timer_lock:
|
||
if not self.is_active:
|
||
return
|
||
|
||
self.is_active = False
|
||
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
# 计算已过去的时间(用于显示信息)
|
||
if self.last_activity_time > 0:
|
||
elapsed = time.time() - self.last_activity_time
|
||
remaining = max(0, self.INTERVAL - elapsed)
|
||
print(f"[{current_time}] 定时器已暂停(已等待{elapsed:.1f}秒,剩余{remaining:.1f}秒)")
|
||
else:
|
||
print(f"[{current_time}] 定时器已暂停")
|
||
|
||
def on_press(self, key):
|
||
"""键盘按键事件处理"""
|
||
try:
|
||
# 检测控制键按下,用于控制定时器暂停/恢复
|
||
if hasattr(key, 'char') and (key.char.lower() == self.CONTROL_KEY.lower()):
|
||
if not self.is_active:
|
||
# 按下控制键,启动定时器(重新开始计时)
|
||
self.start_timer()
|
||
else:
|
||
# 定时器运行中按下控制键,暂停定时器
|
||
self.pause_timer()
|
||
|
||
# 处理Esc键事件 - 不再退出程序,只显示信息
|
||
elif key == Key.esc:
|
||
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
status = '运行中' if self.is_active else '已暂停'
|
||
print(f"[{current_time}] 检测到按下Esc键(定时器状态:{status})")
|
||
print("提示:Esc键已禁用退出功能,程序继续运行")
|
||
|
||
# 处理目标键事件(仅用于显示,不影响定时器状态)
|
||
elif key == self.TARGET_KEY:
|
||
if self.ignore_next_key:
|
||
# 如果是程序自动按下的键,忽略它
|
||
self.ignore_next_key = False
|
||
else:
|
||
# 用户手动按下的目标键,只显示信息不影响定时器
|
||
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
status = '运行中' if self.is_active else '已暂停'
|
||
key_name = self._get_key_name(self.TARGET_KEY)
|
||
print(f"[{current_time}] 检测到手动按下 {key_name} 键(定时器状态:{status})")
|
||
|
||
except AttributeError:
|
||
# 处理特殊功能键(没有char属性的键)
|
||
if key == Key.esc:
|
||
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
status = '运行中' if self.is_active else '已暂停'
|
||
print(f"[{current_time}] 检测到按下Esc键(定时器状态:{status})")
|
||
print("提示:Esc键已禁用退出功能,程序继续运行")
|
||
elif key == self.TARGET_KEY:
|
||
if self.ignore_next_key:
|
||
self.ignore_next_key = False
|
||
else:
|
||
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
status = '运行中' if self.is_active else '已暂停'
|
||
key_name = self._get_key_name(self.TARGET_KEY)
|
||
print(f"[{current_time}] 检测到手动按下 {key_name} 键(定时器状态:{status})")
|
||
|
||
def on_release(self, key):
|
||
"""键盘释放事件处理 - 移除Esc键退出功能"""
|
||
pass
|
||
|
||
def start_listening(self):
|
||
"""开始监听键盘事件"""
|
||
key_name = self._get_key_name(self.TARGET_KEY)
|
||
print(f"{key_name}自动按下程序已启动")
|
||
print(f"按 {self.CONTROL_KEY.upper()} 键开始定时器,再次按 {self.CONTROL_KEY.upper()} 键暂停定时器")
|
||
print(f"定时器间隔时间:{self.INTERVAL}秒")
|
||
print(f"目标按键:{key_name}")
|
||
print("提示:定时器暂停后重新启动将重新开始计时")
|
||
print("提示:Esc键退出功能已禁用,如需退出程序请使用Ctrl+C")
|
||
|
||
# 同时监听按下和释放事件
|
||
with keyboard.Listener(on_press=self.on_press, on_release=self.on_release) as self.listener:
|
||
try:
|
||
self.listener.join()
|
||
except Exception as e:
|
||
print(f"监听器错误: {e}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
try:
|
||
auto_presser = AutoKeyPresser()
|
||
auto_presser.start_listening()
|
||
except KeyboardInterrupt:
|
||
print("\n程序被用户中断(Ctrl+C)")
|
||
except Exception as e:
|
||
print(f"程序运行错误: {e}") |