python-script-library/x时间后按下x按键.py

177 lines
7.8 KiB
Python
Raw Permalink Normal View History

2025-10-28 16:02:55 +08:00
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}")