实现定时点击功能,精确到微秒

import tkinter as tk
from tkinter import ttk
import threading
import datetime
import time
from pynput.mouse import Controller, Button

class MouseClickScheduler:
    def __init__(self, root):
        self.root = root
        self.mouse = Controller()
        self.running = False
        self.setup_ui()

    def setup_ui(self):
        self.root.title("精确鼠标点击工具")
        self.root.resizable(False, False)

        # 时间输入框架
        time_frame = ttk.LabelFrame(self.root, text="设置点击时间")
        time_frame.grid(padx=10, pady=5, sticky="ew")

        # 创建时间输入组件
        self.create_spinbox(time_frame, "时", 0, 23, 0)
        self.create_spinbox(time_frame, "分", 0, 59, 0)
        self.create_spinbox(time_frame, "秒", 0, 59, 59)
        self.create_spinbox(time_frame, "毫秒", 0, 999, 0)
        self.create_spinbox(time_frame, "微秒", 0, 999, 0)

        # 控制按钮
        self.start_btn = ttk.Button(self.root, text="开始", command=self.start_scheduler)
        self.start_btn.grid(pady=5)

        # 状态提示
        self.status = ttk.Label(self.root, text="就绪")
        self.status.grid(pady=5)

    def create_spinbox(self, parent, label, from_, to, default):
        frame = ttk.Frame(parent)
        frame.pack(side=tk.LEFT, padx=5, pady=5)
        
        ttk.Label(frame, text=label).pack()
        spinbox = ttk.Spinbox(
            frame,
            from_=from_,
            to=to,
            width=5,
            validate="key",
            validatecommand=(frame.register(self.validate_spinbox), '%P')
        )
        spinbox.set(default)
        spinbox.pack()
        setattr(self, f"{label}_var", spinbox)

    def validate_spinbox(self, value):
        return value.isdigit() or value == ""

    def get_target_time(self):
        now = datetime.datetime.now()
        try:
            hours = int(self.时_var.get())
            minutes = int(self.分_var.get())
            seconds = int(self.秒_var.get())
            milliseconds = int(self.毫秒_var.get())
            microseconds = int(self.微秒_var.get())

            return datetime.datetime(
                year=now.year,
                month=now.month,
                day=now.day,
                hour=hours,
                minute=minutes,
                second=seconds,
                microsecond=(milliseconds * 1000) + microseconds
            )
        except ValueError:
            return None

    def update_status(self, text):
        self.status.config(text=text)
        
    def start_scheduler(self):
        if self.running:
            return
            
        target_time = self.get_target_time()
        if not target_time:
            self.update_status("错误:无效的时间输入")
            return
            
        if target_time < datetime.datetime.now():
            self.update_status("错误:时间已经过去")
            return

        self.running = True
        self.start_btn.config(state=tk.DISABLED)
        self.update_status("等待中...")
        
        thread = threading.Thread(target=self.run_scheduler, args=(target_time,))
        thread.start()

    def run_scheduler(self, target_time):
        def finalize():
            self.start_btn.config(state=tk.NORMAL)
            self.running = False
        
        while datetime.datetime.now() < target_time:
            remaining = (target_time - datetime.datetime.now()).total_seconds()
            self.root.after(10, self.update_status, f"剩余时间: {remaining:.6f} 秒")
            if remaining > 1:  # 剩余时间较长时使用 sleep
                time.sleep(0.1)
            else:  # 接近目标时间时使用忙等待
                while datetime.datetime.now() < target_time:
                    pass

        try:
            self.mouse.press(Button.left)
            self.mouse.release(Button.left)
            self.root.after(0, self.update_status, "点击成功!")
        except Exception as e:
            self.root.after(0, self.update_status, f"错误: {str(e)}")
        finally:
            self.root.after(0, finalize)

if __name__ == "__main__":
    root = tk.Tk()
    app = MouseClickScheduler(root)
    root.mainloop()