smart-clicker 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.1
2
+ Name: smart_clicker
3
+ Version: 0.1.0
4
+ Summary: A simple screen automation tool with hotkey snapshot capability.
5
+ Author: Your Name
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,15 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="smart_clicker",
5
+ version="0.1.0",
6
+ packages=find_packages(),
7
+ install_requires=[
8
+ "pyautogui",
9
+ "opencv-python",
10
+ "keyboard",
11
+ "pillow"
12
+ ],
13
+ author="Your Name",
14
+ description="A simple screen automation tool with hotkey snapshot capability.",
15
+ )
@@ -0,0 +1,7 @@
1
+ from .core import AutoBot
2
+
3
+ # 为了方便用户直接使用,实例化一个默认对象,或者暴露类
4
+ _bot = AutoBot()
5
+
6
+ def init(img_dir, **kwargs):
7
+ return _bot.init(img_dir, **kwargs)
@@ -0,0 +1,114 @@
1
+ import time
2
+ import os
3
+ import threading
4
+ import keyboard
5
+ import pyautogui
6
+ from pyautogui import ImageNotFoundException
7
+ from .snipper import take_snapshot
8
+
9
+ class AutoBot:
10
+ def __init__(self):
11
+ self.img_dir = None
12
+ self.target_name = "target.png" # 默认图片名
13
+ self.target_path = None
14
+ self.running = False
15
+ self.stop_event = threading.Event()
16
+ self.worker_thread = None
17
+
18
+ # 配置参数
19
+ self.confidence = 0.8
20
+ self.grayscale = True
21
+
22
+ # 快捷键
23
+ self.hk_snapshot = 'f2' # 截图快捷键
24
+ self.hk_toggle = 'f4' # 开关快捷键
25
+
26
+ def init(self, img_dir, target_filename="target.png", snapshot_key='f2', toggle_key='f4'):
27
+ """初始化配置"""
28
+ self.img_dir = img_dir
29
+ self.target_name = target_filename
30
+ self.target_path = os.path.join(self.img_dir, self.target_name)
31
+ self.hk_snapshot = snapshot_key
32
+ self.hk_toggle = toggle_key
33
+
34
+ # 确保目录存在
35
+ if not os.path.exists(self.img_dir):
36
+ os.makedirs(self.img_dir)
37
+
38
+ return self # 支持链式调用
39
+
40
+ def _toggle_automation(self):
41
+ """切换运行状态"""
42
+ self.running = not self.running
43
+ if self.running:
44
+ print(f"\n🚀 自动化已启动! (目标: {self.target_name})")
45
+ # 检查图片是否存在
46
+ if not os.path.exists(self.target_path):
47
+ print(f"⚠️ 警告: 未找到 {self.target_path},请先按 {self.hk_snapshot} 截图!")
48
+ self.running = False
49
+ else:
50
+ print("\n⏸️ 自动化已暂停")
51
+
52
+ def _trigger_snapshot(self):
53
+ """触发截图流程(需要暂停自动化以防冲突)"""
54
+ was_running = self.running
55
+ if was_running:
56
+ self.running = False
57
+ print("📸 暂停任务以进行截图...")
58
+
59
+ print(">>> 请框选要识别的区域...")
60
+ # 这里的截图需要在主线程或者完全独立的进程中调用,因为 tkinter 在子线程运行会有问题
61
+ # 但 keyboard 的回调通常在一个独立的线程。
62
+ # 这里为了简单,直接调用,若有 GUI 冲突需使用队列通信,但在纯脚本环境下通常可行。
63
+ take_snapshot(self.target_path)
64
+
65
+ if was_running:
66
+ self.running = True
67
+ print("▶️ 恢复任务")
68
+
69
+ def _loop_logic(self):
70
+ """后台循环查找线程"""
71
+ print(f"🤖 服务已就绪 | 截图: [{self.hk_snapshot}] | 开关: [{self.hk_toggle}]")
72
+ print("按 Ctrl+C 强制退出程序")
73
+
74
+ while not self.stop_event.is_set():
75
+ if self.running and os.path.exists(self.target_path):
76
+ try:
77
+ location = pyautogui.locateCenterOnScreen(
78
+ self.target_path,
79
+ confidence=self.confidence,
80
+ grayscale=self.grayscale
81
+ )
82
+
83
+ if location:
84
+ print(f"✨ 点击坐标: {location}")
85
+ pyautogui.click(location)
86
+ time.sleep(1) # 点击冷却
87
+
88
+ except ImageNotFoundException:
89
+ pass # 没找到是正常的,继续找
90
+ except Exception as e:
91
+ print(f"❌ 错误: {e}")
92
+
93
+ time.sleep(0.1) # 避免CPU占用过高
94
+
95
+ def start(self):
96
+ """启动监听和循环"""
97
+ if not self.img_dir:
98
+ raise ValueError("请先调用 init('path') 设置目录")
99
+
100
+ # 注册热键
101
+ keyboard.add_hotkey(self.hk_snapshot, self._trigger_snapshot)
102
+ keyboard.add_hotkey(self.hk_toggle, self._toggle_automation)
103
+
104
+ # 启动后台工作线程
105
+ self.worker_thread = threading.Thread(target=self._loop_logic)
106
+ self.worker_thread.daemon = True # 设置为守护线程,主程序退出时自动销毁
107
+ self.worker_thread.start()
108
+
109
+ # 阻塞主线程,保持程序运行,直到用户按 Ctrl+C
110
+ try:
111
+ keyboard.wait()
112
+ except KeyboardInterrupt:
113
+ print("\n👋 程序退出")
114
+ self.stop_event.set()
@@ -0,0 +1,75 @@
1
+ import tkinter as tk
2
+ from PIL import ImageGrab
3
+ import os
4
+ import pyautogui
5
+
6
+ class ScreenSnipper:
7
+ def __init__(self, save_path):
8
+ self.save_path = save_path
9
+ self.root = tk.Tk()
10
+ # 设置全屏、无边框、顶层
11
+ self.root.attributes("-fullscreen", True)
12
+ self.root.attributes("-alpha", 0.3) # 透明度
13
+ self.root.attributes("-topmost", True)
14
+ self.root.overrideredirect(True)
15
+
16
+ # 灰色遮罩
17
+ self.canvas = tk.Canvas(self.root, cursor="cross", bg="grey")
18
+ self.canvas.pack(fill="both", expand=True)
19
+
20
+ self.start_x = None
21
+ self.start_y = None
22
+ self.rect = None
23
+
24
+ # 绑定鼠标事件
25
+ self.canvas.bind("<ButtonPress-1>", self.on_button_press)
26
+ self.canvas.bind("<B1-Motion>", self.on_move_press)
27
+ self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
28
+
29
+ # 按 ESC 退出截图
30
+ self.root.bind("<Escape>", lambda e: self.root.destroy())
31
+
32
+ def start_capture(self):
33
+ self.root.mainloop()
34
+
35
+ def on_button_press(self, event):
36
+ self.start_x = event.x
37
+ self.start_y = event.y
38
+ # 创建矩形框
39
+ self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, 1, 1, outline='red', width=3)
40
+
41
+ def on_move_press(self, event):
42
+ cur_x, cur_y = (event.x, event.y)
43
+ self.canvas.coords(self.rect, self.start_x, self.start_y, cur_x, cur_y)
44
+
45
+ def on_button_release(self, event):
46
+ end_x, end_y = (event.x, event.y)
47
+ self.root.destroy() # 关闭遮罩
48
+
49
+ # 计算坐标 (处理从右下往左上拉的情况)
50
+ x1 = min(self.start_x, end_x)
51
+ y1 = min(self.start_y, end_y)
52
+ x2 = max(self.start_x, end_x)
53
+ y2 = max(self.start_y, end_y)
54
+
55
+ if x2 - x1 < 5 or y2 - y1 < 5:
56
+ print("❌ 选区太小,已取消截图")
57
+ return
58
+
59
+ # 截图保存
60
+ try:
61
+ # ImageGrab 截取的是物理屏幕坐标
62
+ img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
63
+
64
+ # 确保目录存在
65
+ if not os.path.exists(os.path.dirname(self.save_path)):
66
+ os.makedirs(os.path.dirname(self.save_path))
67
+
68
+ img.save(self.save_path)
69
+ print(f"✅ 目标图片已更新: {self.save_path}")
70
+ except Exception as e:
71
+ print(f"❌ 截图失败: {e}")
72
+
73
+ def take_snapshot(path):
74
+ snipper = ScreenSnipper(path)
75
+ snipper.start_capture()
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.1
2
+ Name: smart-clicker
3
+ Version: 0.1.0
4
+ Summary: A simple screen automation tool with hotkey snapshot capability.
5
+ Author: Your Name
@@ -0,0 +1,9 @@
1
+ setup.py
2
+ smart_clicker/__init__.py
3
+ smart_clicker/core.py
4
+ smart_clicker/snipper.py
5
+ smart_clicker.egg-info/PKG-INFO
6
+ smart_clicker.egg-info/SOURCES.txt
7
+ smart_clicker.egg-info/dependency_links.txt
8
+ smart_clicker.egg-info/requires.txt
9
+ smart_clicker.egg-info/top_level.txt
@@ -0,0 +1,4 @@
1
+ pyautogui
2
+ opencv-python
3
+ keyboard
4
+ pillow
@@ -0,0 +1 @@
1
+ smart_clicker