import tkinter as tk from tkinter import ttk, scrolledtext import pyautogui import pyperclip import time import threading import csv import os import re from datetime import datetime class AutoClickerApp: def __init__(self, root): self.root = root self.root.title("自动点击采集工具") self.root.geometry("900x700") # 状态变量 self.is_running = False self.thread = None self.stop_event = threading.Event() # 数据存储 self.coord_data = [] # 存储CSV数据 self.last_coords = [] # 存储每次采集到的坐标 (用于去重) self.setup_ui() self.load_csv_data() def setup_ui(self): # 控制按钮框架 control_frame = tk.Frame(self.root) control_frame.pack(pady=10) self.start_btn = tk.Button(control_frame, text="开始", command=self.start_action, bg="green", fg="white", font=("Arial", 12), width=10) self.start_btn.pack(side=tk.LEFT, padx=5) self.stop_btn = tk.Button(control_frame, text="停止", command=self.stop_action, bg="red", fg="white", font=("Arial", 12), width=10) self.stop_btn.pack(side=tk.LEFT, padx=5) # 表格框架 table_frame = tk.Frame(self.root) table_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True) # 创建表格 self.tree = ttk.Treeview(table_frame, columns=('x_range', 'y_range', 'collect_time'), show='headings', height=15) # 设置列 self.tree.heading('x_range', text='X坐标范围') self.tree.heading('y_range', text='Y坐标范围') self.tree.heading('collect_time', text='采集时间') self.tree.column('x_range', width=150, anchor='center') self.tree.column('y_range', width=150, anchor='center') self.tree.column('collect_time', width=250, anchor='center') # 添加滚动条 scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.tree.yview) self.tree.configure(yscrollcommand=scrollbar.set) self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) # 日志框架 log_frame = tk.Frame(self.root) log_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True) tk.Label(log_frame, text="日志:", font=("Arial", 10, "bold")).pack(anchor='w') self.log_text = scrolledtext.ScrolledText(log_frame, height=10, wrap=tk.WORD) self.log_text.pack(fill=tk.BOTH, expand=True) def load_csv_data(self): """加载CSV文件数据""" csv_file = "coordinates.csv" if not os.path.exists(csv_file): self.log_message(f"未找到 {csv_file} 文件,请创建示例文件") self.create_sample_csv() return try: with open(csv_file, 'r', encoding='utf-8') as file: csv_reader = csv.reader(file) self.coord_data = list(csv_reader) # 清空表格 for item in self.tree.get_children(): self.tree.delete(item) # 填充表格 for row in self.coord_data: if len(row) >= 3: self.tree.insert('', 'end', values=(row[0], row[1], row[2])) self.log_message(f"成功加载 {len(self.coord_data)} 条坐标数据") except Exception as e: self.log_message(f"加载CSV文件失败: {str(e)}") def create_sample_csv(self): """创建示例CSV文件""" sample_data = [ ['62-42', '225-73', ''], ['240-300', '100-150', ''], ['180-220', '50-90', ''] ] try: with open('coordinates.csv', 'w', newline='', encoding='utf-8') as file: writer = csv.writer(file) writer.writerows(sample_data) self.log_message("已创建示例CSV文件: coordinates.csv") self.load_csv_data() except Exception as e: self.log_message(f"创建示例CSV文件失败: {str(e)}") def log_message(self, message): """添加日志消息""" timestamp = datetime.now().strftime("%H:%M:%S") self.log_text.insert(tk.END, f"[{timestamp}] {message}\n") self.log_text.see(tk.END) def update_table_time(self, x, y): """根据坐标更新表格中的时间""" try: x_float = float(x) y_float = float(y) # 从最后一行开始向前匹配(只匹配最新的) for i in range(len(self.coord_data) - 1, -1, -1): row = self.coord_data[i] if len(row) >= 2: # 解析X范围 x_range = row[0].strip() if '-' in x_range: x_start, x_end = x_range.split('-') try: x_start = float(x_start.strip()) x_end = float(x_end.strip()) if x_start <= x_float <= x_end: # 解析Y范围 y_range = row[1].strip() if '-' in y_range: y_start, y_end = y_range.split('-') y_start = float(y_start.strip()) y_end = float(y_end.strip()) if y_start <= y_float <= y_end: # 匹配成功,更新时间 current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") row[2] = current_time # 更新表格显示 children = self.tree.get_children() if i < len(children): self.tree.delete(children[i]) self.tree.insert('', i, values=(row[0], row[1], row[2])) self.log_message(f"坐标 ({x_float}, {y_float}) 匹配成功,时间已更新为 {current_time}") return True except ValueError: continue self.log_message(f"坐标 ({x_float}, {y_float}) 未匹配到任何范围") return False except ValueError: self.log_message(f"坐标格式错误: {x}, {y}") return False def parse_clipboard_content(self, content): """解析剪贴板内容,提取坐标""" lines = content.strip().split('\n') found_coords = None # 查找"发现真武矿采集物坐标"的行 for i, line in enumerate(lines): if '发现真武矿采集物坐标' in line: # 检查前一行是否包含"挖着了" if i > 0 and '挖着了' in lines[i-1]: # 提取坐标 match = re.search(r'发现真武矿采集物坐标:([\d.]+),([\d.]+)', line) if match: x = match.group(1) y = match.group(2) found_coords = (x, y) self.log_message(f"发现有效坐标: {x}, {y}") break if found_coords: x, y = found_coords # 检查是否与上次采集的坐标相同(去重) if (x, y) not in self.last_coords: self.last_coords.append((x, y)) # 只保留最近10条记录 if len(self.last_coords) > 10: self.last_coords.pop(0) self.update_table_time(x, y) else: self.log_message(f"坐标 ({x}, {y}) 已存在,跳过重复更新") else: self.log_message("未找到有效的采集坐标") def perform_actions(self): """执行主要操作""" self.log_message("开始执行操作序列...") try: # 1. 右键点击指定位置 pyautogui.click(1730, 300, button='right') self.log_message("已右键点击 (1730, 300)") time.sleep(0.5) # 2. 按键 A pyautogui.press('a') self.log_message("已按键 A") time.sleep(0.5) # 3. 按键 Ctrl+C pyautogui.hotkey('ctrl', 'c') self.log_message("已执行 Ctrl+C") time.sleep(0.5) # 4. 获取剪贴板内容 clipboard_content = pyperclip.paste() if clipboard_content: self.log_message("成功获取剪贴板内容") self.parse_clipboard_content(clipboard_content) else: self.log_message("剪贴板内容为空") except Exception as e: self.log_message(f"操作执行失败: {str(e)}") def worker(self): """工作线程函数""" self.log_message("程序已启动,每10秒执行一次操作") while not self.stop_event.is_set(): if not self.is_running: break self.perform_actions() # 等待10秒,但每秒检查一次停止信号 for _ in range(10): if self.stop_event.is_set() or not self.is_running: break time.sleep(1) self.log_message("操作线程已停止") def start_action(self): """启动按钮回调""" if self.is_running: self.log_message("程序已在运行中") return # 清空上次的坐标记录 self.last_coords = [] self.stop_event.clear() self.is_running = True self.start_btn.config(state=tk.DISABLED) self.stop_btn.config(state=tk.NORMAL) self.thread = threading.Thread(target=self.worker, daemon=True) self.thread.start() def stop_action(self): """停止按钮回调""" if not self.is_running: return self.log_message("正在停止程序...") self.is_running = False self.stop_event.set() self.start_btn.config(state=tk.NORMAL) self.stop_btn.config(state=tk.DISABLED) def main(): root = tk.Tk() app = AutoClickerApp(root) root.mainloop() if __name__ == "__main__": main()