[Windows] 利用AI技術打造超精準鼠標定時點擊器_精確到毫秒

一個朋友有這方面的需求,于是用AI寫了一個小工具,順便分享給大家
https://wwzh.lanzout.com/idSTx31o9bkj
升級一版:新增自定義多次點擊時間間隔設置功能;顯著優化文件大小。下載鏈接:
https://wwzh.lanzout.com/iZ2Mg31ri6ri

圖片[1]-[Windows] 利用AI技術打造超精準鼠標定時點擊器_精確到毫秒
import tkinter as tk
from tkinter import messagebox, ttk
import pyautogui
import time
import threading
from datetime import datetime, timedelta
from pynput import keyboard
 
class MouseAutoClicker:
    def __init__(self, root):
        self.root = root
        self.root.title("鼠標自動點擊器")
        self.root.geometry("650x450")  # 增加窗口高度
        self.root.resizable(False, False)
         
        # 確保中文顯示正常
        self.style = ttk.Style()
        self.style.configure("TLabel", font=("SimHei", 10))
        self.style.configure("TButton", font=("SimHei", 10))
        self.style.configure("TCheckbutton", font=("SimHei", 10))
         
        # 設置變量
        self.hour_var = tk.StringVar(value="15")
        self.minute_var = tk.StringVar(value="40")
        self.second_var = tk.StringVar(value="59")
        self.millisecond_var = tk.StringVar(value="300")
         
        self.x_pos = tk.StringVar(value="0")
        self.y_pos = tk.StringVar(value="0")
         
        self.click_type = tk.StringVar(value="左鍵")
        self.click_count = tk.StringVar(value="1")
        self.click_interval = tk.StringVar(value="0.1")  # 新增:點擊間隔(秒)
         
        self.is_running = False
        self.click_thread = None
        self.position_set = False
         
        # 創建鍵盤監聽器
        self.key_listener = keyboard.Listener(on_press=self.on_key_press)
        self.key_listener.start()
         
        # 創建界面
        self.create_widgets()
     
    def create_widgets(self):
        # 時間設置框架
        time_frame = ttk.LabelFrame(self.root, text="設置點擊時間")
        time_frame.pack(fill="x", padx=15, pady=10)
         
        ttk.Label(time_frame, text="小時:").grid(row=0, column=0, padx=5, pady=5)
        self.hour_combo = ttk.Combobox(time_frame, textvariable=self.hour_var, width=5)
        self.hour_combo['values'] = tuple(f"{i:02d}" for i in range(24))
        self.hour_combo.grid(row=0, column=1, padx=5, pady=5)
        self.hour_combo.bind('<FocusOut>', self.validate_time_input)
         
        ttk.Label(time_frame, text="分鐘:").grid(row=0, column=2, padx=5, pady=5)
        self.minute_combo = ttk.Combobox(time_frame, textvariable=self.minute_var, width=5)
        self.minute_combo['values'] = tuple(f"{i:02d}" for i in range(60))
        self.minute_combo.grid(row=0, column=3, padx=5, pady=5)
        self.minute_combo.bind('<FocusOut>', self.validate_time_input)
         
        ttk.Label(time_frame, text="秒:").grid(row=0, column=4, padx=5, pady=5)
        self.second_combo = ttk.Combobox(time_frame, textvariable=self.second_var, width=5)
        self.second_combo['values'] = tuple(f"{i:02d}" for i in range(60))
        self.second_combo.grid(row=0, column=5, padx=5, pady=5)
        self.second_combo.bind('<FocusOut>', self.validate_time_input)
         
        ttk.Label(time_frame, text="毫秒:").grid(row=0, column=6, padx=5, pady=5)
        self.millisecond_combo = ttk.Combobox(time_frame, textvariable=self.millisecond_var, width=5)
        self.millisecond_combo['values'] = tuple(f"{i:03d}" for i in range(0, 1000, 50))
        self.millisecond_combo.grid(row=0, column=7, padx=5, pady=5)
        self.millisecond_combo.bind('<FocusOut>', self.validate_time_input)
         
        # 位置設置框架
        position_frame = ttk.LabelFrame(self.root, text="設置點擊位置")
        position_frame.pack(fill="x", padx=15, pady=10)
         
        ttk.Label(position_frame, text="X坐標:").grid(row=0, column=0, padx=5, pady=5)
        x_entry = ttk.Entry(position_frame, textvariable=self.x_pos, width=10)
        x_entry.grid(row=0, column=1, padx=5, pady=5)
        x_entry.bind('<FocusOut>', self.validate_position_input)
         
        ttk.Label(position_frame, text="Y坐標:").grid(row=0, column=2, padx=5, pady=5)
        y_entry = ttk.Entry(position_frame, textvariable=self.y_pos, width=10)
        y_entry.grid(row=0, column=3, padx=5, pady=5)
        y_entry.bind('<FocusOut>', self.validate_position_input)
         
        ttk.Label(position_frame, text="按F8記錄當前鼠標位置").grid(row=0, column=4, padx=5, pady=5)
         
        # 點擊設置框架
        click_frame = ttk.LabelFrame(self.root, text="點擊設置")
        click_frame.pack(fill="x", padx=15, pady=10)
         
        ttk.Label(click_frame, text="點擊類型:").grid(row=0, column=0, padx=5, pady=5)
        click_type_combo = ttk.Combobox(click_frame, textvariable=self.click_type, width=8, state="readonly")
        click_type_combo['values'] = ("左鍵", "右鍵", "中鍵")
        click_type_combo.grid(row=0, column=1, padx=5, pady=5)
         
        ttk.Label(click_frame, text="點擊次數:").grid(row=0, column=2, padx=5, pady=5)
        click_count_combo = ttk.Combobox(click_frame, textvariable=self.click_count, width=5)
        click_count_combo['values'] = tuple(range(1, 11))
        click_count_combo.grid(row=0, column=3, padx=5, pady=5)
        click_count_combo.bind('<FocusOut>', self.validate_click_count)
         
        # 新增:點擊間隔設置
        ttk.Label(click_frame, text="點擊間隔(秒):").grid(row=1, column=0, padx=5, pady=5)
        interval_entry = ttk.Entry(click_frame, textvariable=self.click_interval, width=10)
        interval_entry.grid(row=1, column=1, padx=5, pady=5)
        interval_entry.bind('<FocusOut>', self.validate_interval)
         
        # 狀態顯示
        self.status_var = tk.StringVar(value="就緒")
        ttk.Label(self.root, textvariable=self.status_var).pack(pady=10)
         
        # 按鈕框架
        button_frame = ttk.Frame(self.root)
        button_frame.pack(pady=20)
         
        self.start_button = ttk.Button(button_frame, text="開始", command=self.start_clicking, width=15)
        self.start_button.pack(side="left", padx=10)
         
        self.stop_button = ttk.Button(button_frame, text="停止", command=self.stop_clicking, width=15, state="disabled")
        self.stop_button.pack(side="left", padx=10)
         
        # 底部信息
        ttk.Label(self.root, text="提示: 程序運行時請不要移動鼠標").pack(side="bottom", pady=10)
     
    def on_key_press(self, key):
        """處理鍵盤按下事件"""
        try:
            if key == keyboard.Key.f8:
                self.root.after(0, self.get_mouse_position)
        except AttributeError:
            pass
     
    def get_mouse_position(self):
        """獲取當前鼠標位置"""
        x, y = pyautogui.position()
        self.x_pos.set(str(x))
        self.y_pos.set(str(y))
        self.position_set = True
        self.status_var.set(f"已記錄鼠標位置: ({x}, {y})")
     
    def validate_time_input(self, event):
        """驗證并格式化時間輸入"""
        widget = event.widget
         
        if widget == self.hour_combo:
            value = self.hour_var.get()
            try:
                num = int(value)
                if 0 <= num <= 23:
                    self.hour_var.set(f"{num:02d}")
                else:
                    self.hour_var.set("00")
                    messagebox.showerror("輸入錯誤", "小時數必須在0-23之間")
            except ValueError:
                self.hour_var.set("00")
                messagebox.showerror("輸入錯誤", "小時數必須是數字")
         
        elif widget == self.minute_combo:
            value = self.minute_var.get()
            try:
                num = int(value)
                if 0 <= num <= 59:
                    self.minute_var.set(f"{num:02d}")
                else:
                    self.minute_var.set("00")
                    messagebox.showerror("輸入錯誤", "分鐘數必須在0-59之間")
            except ValueError:
                self.minute_var.set("00")
                messagebox.showerror("輸入錯誤", "分鐘數必須是數字")
         
        elif widget == self.second_combo:
            value = self.second_var.get()
            try:
                num = int(value)
                if 0 <= num <= 59:
                    self.second_var.set(f"{num:02d}")
                else:
                    self.second_var.set("00")
                    messagebox.showerror("輸入錯誤", "秒數必須在0-59之間")
            except ValueError:
                self.second_var.set("00")
                messagebox.showerror("輸入錯誤", "秒數必須是數字")
         
        elif widget == self.millisecond_combo:
            value = self.millisecond_var.get()
            try:
                num = int(value)
                if 0 <= num <= 999:
                    self.millisecond_var.set(f"{num:03d}")
                else:
                    self.millisecond_var.set("000")
                    messagebox.showerror("輸入錯誤", "毫秒數必須在0-999之間")
            except ValueError:
                self.millisecond_var.set("000")
                messagebox.showerror("輸入錯誤", "毫秒數必須是數字")
     
    def validate_position_input(self, event):
        """驗證并格式化坐標輸入"""
        widget = event.widget
        var = self.x_pos if widget == event.widget.master.children['!entry'] else self.y_pos
         
        value = var.get()
        try:
            num = int(value)
            if num < 0:
                var.set("0")
                messagebox.showerror("輸入錯誤", "坐標值不能為負數")
        except ValueError:
            var.set("0")
            messagebox.showerror("輸入錯誤", "坐標值必須是數字")
     
    def validate_click_count(self, event):
        """驗證點擊次數輸入"""
        value = self.click_count.get()
        try:
            num = int(value)
            if 1 <= num <= 10:
                self.click_count.set(str(num))
            else:
                self.click_count.set("1")
                messagebox.showerror("輸入錯誤", "點擊次數必須在1-10之間")
        except ValueError:
            self.click_count.set("1")
            messagebox.showerror("輸入錯誤", "點擊次數必須是數字")
     
    def validate_interval(self, event):
        """驗證點擊間隔輸入"""
        value = self.click_interval.get()
        try:
            num = float(value)
            if num <= 0:
                self.click_interval.set("0.1")
                messagebox.showerror("輸入錯誤", "點擊間隔必須大于0")
            elif num > 10:
                self.click_interval.set("10.0")
                messagebox.showerror("輸入錯誤", "點擊間隔不宜超過10秒")
        except ValueError:
            self.click_interval.set("0.1")
            messagebox.showerror("輸入錯誤", "點擊間隔必須是數字")
     
    def calculate_time_difference(self):
        """計算當前時間與目標時間的差值"""
        try:
            hour = int(self.hour_var.get())
            minute = int(self.minute_var.get())
            second = int(self.second_var.get())
            millisecond = int(self.millisecond_var.get())
             
            # 獲取今天的日期
            now = datetime.now()
            target_time = now.replace(
                hour=hour, 
                minute=minute, 
                second=second, 
                microsecond=millisecond * 1000
            )
             
            # 如果目標時間已經過去,則設置為明天
            if target_time <= now:
                target_time += timedelta(days=1)
             
            # 計算時間差(秒)
            time_diff = (target_time - now).total_seconds()
            return time_diff
        except Exception as e:
            messagebox.showerror("錯誤", f"時間計算出錯: {str(e)}")
            return -1
     
    def start_clicking(self):
        """開始點擊任務"""
        # 檢查是否已設置位置
        if not self.position_set:
            messagebox.showwarning("警告", "請先設置點擊位置")
            return
         
        # 計算時間差
        time_diff = self.calculate_time_difference()
        if time_diff < 0:
            return
         
        # 更新狀態
        self.is_running = True
        self.start_button.config(state="disabled")
        self.stop_button.config(state="normal")
         
        # 計算倒計時顯示
        hours, remainder = divmod(int(time_diff), 3600)
        minutes, seconds = divmod(remainder, 60)
        milliseconds = int((time_diff - int(time_diff)) * 1000)
        countdown_str = f"{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}"
        self.status_var.set(f"倒計時: {countdown_str}")
         
        # 創建并啟動線程
        self.click_thread = threading.Thread(target=self.perform_clicking, args=(time_diff,))
        self.click_thread.daemon = True
        self.click_thread.start()
     
    def perform_clicking(self, time_diff):
        """執行點擊任務的線程函數"""
        start_time = time.time()
        target_time = start_time + time_diff
         
        # 倒計時循環
        while self.is_running and time.time() < target_time:
            remaining = target_time - time.time()
            if remaining < 0:
                remaining = 0
                 
            hours, remainder = divmod(int(remaining), 3600)
            minutes, seconds = divmod(remainder, 60)
            milliseconds = int((remaining - int(remaining)) * 1000)
            countdown_str = f"{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}"
             
            # 使用線程安全的方式更新UI
            self.root.after(0, lambda cs=countdown_str: self.status_var.set(f"倒計時: {cs}"))
            time.sleep(0.1)
         
        # 執行點擊
        if self.is_running:
            try:
                x = int(self.x_pos.get())
                y = int(self.y_pos.get())
                count = int(self.click_count.get())
                interval = float(self.click_interval.get())
                 
                # 移動到指定位置
                pyautogui.moveTo(x, y)
                 
                # 根據選擇的點擊類型執行點擊
                click_func = {
                    "左鍵": pyautogui.click,
                    "右鍵": pyautogui.rightClick,
                    "中鍵": pyautogui.middleClick
                }.get(self.click_type.get(), pyautogui.click)
                 
                for i in range(count):
                    if not self.is_running:
                        break
                    click_func()
                    if i < count - 1:  # 最后一次點擊不需要等待
                        time.sleep(interval)
                        # 更新狀態顯示點擊進度
                        self.root.after(0, lambda i=i+1: self.status_var.set(
                            f"正在執行點擊 {i}/{count},間隔 {interval} 秒"))
                 
                self.root.after(0, lambda: self.status_var.set(
                    f"已完成所有點擊: 在位置 ({x}, {y}) 執行 {count} 次{self.click_type.get()}點擊,間隔 {interval} 秒"))
            except Exception as e:
                self.root.after(0, lambda: messagebox.showerror("錯誤", f"點擊執行出錯: {str(e)}"))
         
        # 重置狀態但不關閉程序
        self.root.after(0, self.reset_after_complete)
     
    def reset_after_complete(self):
        """任務完成后重置狀態"""
        self.is_running = False
        self.start_button.config(state="normal")
        self.stop_button.config(state="disabled")
        self.status_var.set("就緒 - 點擊次數和間隔已完成")
     
    def stop_clicking(self):
        """停止點擊任務"""
        self.is_running = False
        self.start_button.config(state="normal")
        self.stop_button.config(state="disabled")
        self.status_var.set("已停止")
     
    def on_close(self):
        """關閉應用時的清理工作"""
        self.is_running = False
        self.key_listener.stop()
        self.root.destroy()
 
if __name__ == "__main__":
    root = tk.Tk()
    app = MouseAutoClicker(root)
    root.protocol("WM_DELETE_WINDOW", app.on_close)
    root.mainloop()    
圖片[2]-[Windows] 利用AI技術打造超精準鼠標定時點擊器_精確到毫秒
------本頁內容已結束,喜歡請分享------
溫馨提示:由于項目或工具都有失效性,如遇到不能做的項目或不能使用的工具,可以根據關鍵詞在站點搜索相關內容,查看最近更新的或者在網頁底部給我們留言反饋。
? 版權聲明
THE END
喜歡就支持一下吧
點贊1438 分享