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()
分享了「鼠标定时点击器 Rev1.exe」
链接:https://pan.quark.cn/s/abd00e979160