1- __version__ = "2.4"
2-
31import sys
42import os
53import time
1412 QLabel , QComboBox , QSpinBox , QPushButton , QGroupBox ,
1513 QLineEdit , QCheckBox , QTabWidget , QTextEdit , QFileDialog ,
1614 QSystemTrayIcon , QMenu , QAction , QMessageBox , QScrollArea ,
17- QDoubleSpinBox , QTimeEdit , QColorDialog , QProgressBar , QInputDialog )
15+ QDoubleSpinBox , QTimeEdit , QColorDialog , QProgressBar , QInputDialog ,
16+ QStyle )
1817from PyQt5 .QtCore import Qt , QSettings , QTimer , QTime , QSize , QByteArray , QPoint
1918from PyQt5 .QtGui import QIcon , QColor , QPixmap , QImage ,QPainter , QPen
2019import pyautogui
4544 ]
4645)
4746
47+ class ProjectInfo :
48+ """项目信息元数据(集中管理所有项目相关信息)"""
49+ VERSION = "2.10.0"
50+ BUILD_DATE = "2025-06-01"
51+ # BUILD_DATE = datetime.now().strftime("%Y-%m-%d") # 修改为动态获取当前日期
52+ AUTHOR = "杜玛"
53+ LICENSE = "MIT"
54+ COPYRIGHT = "© 永久 杜玛"
55+ URL = "https://github.com/duma520"
56+ MAINTAINER_EMAIL = "不提供"
57+ NAME = "高级鼠标点击模拟器"
58+ DESCRIPTION = "高级鼠标点击模拟器,支持多种触发方式和脚本功能,适用于游戏辅助、自动化测试等场景。"
59+ VERSION_HISTORY = {
60+ "2.8.0" : "fix: 修复了多坐标循环模式下的点击位置问题,优化了脚本执行速度。" ,
61+ "2.9.0" : "fix: 修复了QStyle相关的显示问题" ,
62+ "2.10.0" : "fix: 修复了托盘图标加载失败的情况,优化了系统图标获取方式。"
63+ }
64+ HELP_TEXT = """
65+ 使用说明:
66+
67+ """
68+
69+
70+ @classmethod
71+ def get_metadata (cls ) -> dict :
72+ """获取主要元数据字典"""
73+ return {
74+ 'version' : cls .VERSION ,
75+ 'author' : cls .AUTHOR ,
76+ 'license' : cls .LICENSE ,
77+ 'url' : cls .URL
78+ }
79+
80+
81+ @classmethod
82+ def get_header (cls ) -> str :
83+ """生成标准化的项目头信息"""
84+ return f"{ cls .NAME } { cls .VERSION } | { cls .LICENSE } License | { cls .URL } "
85+
4886class MouseClickSimulator (QMainWindow ):
4987 def __init__ (self ):
5088 super ().__init__ ()
51- self .setWindowTitle ("高级鼠标点击模拟器" )
89+ # self.setWindowTitle(f"高级鼠标点击模拟器 v{__version__}")
90+ self .setWindowTitle (f"{ ProjectInfo .NAME } { ProjectInfo .VERSION } (Build: { ProjectInfo .BUILD_DATE } )" )
5291
5392 # 设置窗口图标
5493 if os .path .exists ("icon.ico" ):
@@ -61,7 +100,7 @@ def __init__(self):
61100 # 根据屏幕分辨率自动调整大小
62101 screen = QApplication .primaryScreen ()
63102 screen_size = screen .size ()
64- self .resize (int (screen_size .width ()* 0.4 ), int (screen_size .height ()* 0.7 ))
103+ self .resize (int (screen_size .width ()* 0.4 ), int (screen_size .height ()* 0.8 ))
65104
66105
67106 # 初始化设置
@@ -88,7 +127,10 @@ def __init__(self):
88127 # 初始化UI
89128 self .init_ui ()
90129 self .setup_hotkeys ()
91- self .setup_tray_icon ()
130+
131+ # 只在系统托盘可用时初始化
132+ if QSystemTrayIcon .isSystemTrayAvailable ():
133+ self .setup_tray_icon ()
92134
93135 # 启动监控定时器
94136 self .monitor_timer = QTimer (self )
@@ -114,7 +156,9 @@ def __init__(self):
114156 self .memory_history = []
115157 self .max_history_points = 60 # 保留60个数据点
116158
159+
117160 def init_ui (self ):
161+
118162 # 创建主滚动区域
119163 scroll = QScrollArea ()
120164 scroll .setWidgetResizable (True )
@@ -211,7 +255,137 @@ def init_ui(self):
211255 self .stop_button .clicked .connect (self .stop_clicking )
212256 self .emergency_button .clicked .connect (self .emergency_stop_func )
213257
258+ # 设置全局样式
259+ self .setStyleSheet ("""
260+ QMainWindow {
261+ background-color: #f5f7fa;
262+ }
263+ QGroupBox {
264+ border: 1px solid #d1d5db;
265+ border-radius: 6px;
266+ margin-top: 10px;
267+ padding-top: 15px;
268+ font-weight: bold;
269+ color: #374151;
270+ }
271+ QGroupBox::title {
272+ subcontrol-origin: margin;
273+ left: 10px;
274+ padding: 0 3px;
275+ }
276+ QPushButton {
277+ background-color: #3b82f6;
278+ color: white;
279+ border: none;
280+ border-radius: 4px;
281+ padding: 6px 12px;
282+ min-width: 80px;
283+ }
284+ QPushButton:hover {
285+ background-color: #2563eb;
286+ }
287+ QPushButton:pressed {
288+ background-color: #1d4ed8;
289+ }
290+ QPushButton:disabled {
291+ background-color: #9ca3af;
292+ }
293+ QLabel {
294+ color: #374151;
295+ }
296+ QLineEdit, QTextEdit, QComboBox, QSpinBox {
297+ border: 1px solid #d1d5db;
298+ border-radius: 4px;
299+ padding: 4px;
300+ }
301+ QTabWidget::pane {
302+ border: 1px solid #d1d5db;
303+ border-radius: 6px;
304+ }
305+ QTabBar::tab {
306+ padding: 8px 16px;
307+ background: #e5e7eb;
308+ border-top-left-radius: 4px;
309+ border-top-right-radius: 4px;
310+ margin-right: 2px;
311+ }
312+ QTabBar::tab:selected {
313+ background: #f5f7fa;
314+ border-bottom: 2px solid #3b82f6;
315+ }
316+ """ )
317+
318+ # 控制按钮特殊样式
319+ self .start_button .setStyleSheet ("""
320+ QPushButton {
321+ background-color: #10b981;
322+ }
323+ QPushButton:hover {
324+ background-color: #059669;
325+ }
326+ """ )
327+
328+ self .stop_button .setStyleSheet ("""
329+ QPushButton {
330+ background-color: #ef4444;
331+ }
332+ QPushButton:hover {
333+ background-color: #dc2626;
334+ }
335+ """ )
336+
337+ # 状态栏样式
338+ self .status_bar .setStyleSheet ("""
339+ QLabel {
340+ background-color: #ffffff;
341+ border: 1px solid #d1d5db;
342+ border-radius: 4px;
343+ padding: 8px;
344+ font-size: 12px;
345+ }
346+ """ )
347+
348+ # 图表区域样式
349+ self .cpu_chart .setStyleSheet ("""
350+ QLabel {
351+ background-color: white;
352+ border: 1px solid #d1d5db;
353+ border-radius: 4px;
354+ }
355+ """ )
356+
357+ self .memory_chart .setStyleSheet ("""
358+ QLabel {
359+ background-color: white;
360+ border: 1px solid #d1d5db;
361+ border-radius: 4px;
362+ }
363+ """ )
364+
365+ # 日志区域样式
366+ self .log_view .setStyleSheet ("""
367+ QTextEdit {
368+ background-color: white;
369+ border: 1px solid #d1d5db;
370+ border-radius: 4px;
371+ font-family: 'Consolas', monospace;
372+ font-size: 10pt;
373+ color: #374151;
374+ }
375+ """ )
376+
377+
378+
379+ def resizeEvent (self , event ):
380+ # 根据窗口宽度调整布局
381+ width = event .size ().width ()
382+ if width < 800 : # 小屏幕布局
383+ self .tabs .setStyleSheet ("QTabBar::tab { padding: 6px 12px; }" )
384+ else : # 大屏幕布局
385+ self .tabs .setStyleSheet ("QTabBar::tab { padding: 8px 16px; }" )
386+ super ().resizeEvent (event )
214387
388+
215389 def create_scrollable_tab (self , content_init_func ):
216390 """创建带有滚动条的可滚动标签页"""
217391 scroll = QScrollArea ()
@@ -988,17 +1162,21 @@ def init_monitor_tab(self, layout=None):
9881162 self .cpu_chart = QLabel ("CPU使用率图表" )
9891163 self .cpu_chart .setFixedHeight (150 )
9901164 self .cpu_chart .setStyleSheet ("""
991- background-color: white;
992- border: 1px solid #C0C0C0;
993- border-radius: 3px;
1165+ QLabel {
1166+ background-color: white;
1167+ border: 1px solid #d1d5db;
1168+ border-radius: 4px;
1169+ }
9941170 """ )
9951171
9961172 self .memory_chart = QLabel ("内存使用率图表" )
9971173 self .memory_chart .setFixedHeight (150 )
9981174 self .memory_chart .setStyleSheet ("""
999- background-color: white;
1000- border: 1px solid #C0C0C0;
1001- border-radius: 3px;
1175+ QLabel {
1176+ background-color: white;
1177+ border: 1px solid #d1d5db;
1178+ border-radius: 4px;
1179+ }
10021180 """ )
10031181
10041182 monitor_layout .addWidget (QLabel ("CPU使用历史:" ))
@@ -1438,40 +1616,53 @@ def setup_tray_icon(self):
14381616 if not QSystemTrayIcon .isSystemTrayAvailable ():
14391617 return
14401618
1441- self .tray_icon = QSystemTrayIcon (self )
1619+ try :
1620+ self .tray_icon = QSystemTrayIcon (self )
1621+
1622+ # 尝试加载自定义图标
1623+ icon_set = False
1624+ for icon_file in ["icon.ico" , "icon.png" ]:
1625+ if os .path .exists (icon_file ):
1626+ try :
1627+ self .tray_icon .setIcon (QIcon (icon_file ))
1628+ icon_set = True
1629+ break
1630+ except :
1631+ continue
1632+
1633+ # 如果自定义图标加载失败,使用系统默认图标
1634+ if not icon_set :
1635+ try :
1636+ # 使用更兼容的方式获取系统图标
1637+ default_icon = self .style ().standardIcon (QStyle .SP_ComputerIcon )
1638+ self .tray_icon .setIcon (default_icon )
1639+ except :
1640+ # 如果所有方法都失败,则不设置图标
1641+ pass
1642+
1643+ # 创建托盘菜单
1644+ tray_menu = QMenu ()
1645+ actions = [
1646+ ("显示" , self .show ),
1647+ ("开始模拟" , self .start_clicking ),
1648+ ("停止模拟" , self .stop_clicking ),
1649+ ("退出" , self .close )
1650+ ]
1651+
1652+ for text , callback in actions :
1653+ action = QAction (text , self )
1654+ action .triggered .connect (callback )
1655+ tray_menu .addAction (action )
1656+
1657+ self .tray_icon .setContextMenu (tray_menu )
1658+ self .tray_icon .show ()
1659+ self .tray_icon .activated .connect (self .tray_icon_activated )
1660+
1661+ except Exception as e :
1662+ logging .error (f"创建系统托盘图标失败: { str (e )} " )
1663+ # 即使托盘图标创建失败,也不影响主程序运行
1664+ self .tray_icon = None
14421665
1443- # 设置托盘图标,优先使用 .ico,其次尝试 .png
1444- if os .path .exists ("icon.ico" ):
1445- self .tray_icon .setIcon (QIcon ("icon.ico" ))
1446- elif os .path .exists ("icon.png" ):
1447- self .tray_icon .setIcon (QIcon ("icon.png" ))
1448- else :
1449- # 如果没有找到图标文件,使用默认图标
1450- self .tray_icon .setIcon (self .style ().standardIcon (QStyle .SP_ComputerIcon ))
1451-
1452-
1453- tray_menu = QMenu ()
1454-
1455- show_action = QAction ("显示" , self )
1456- show_action .triggered .connect (self .show )
1457- tray_menu .addAction (show_action )
1458-
1459- start_action = QAction ("开始模拟" , self )
1460- start_action .triggered .connect (self .start_clicking )
1461- tray_menu .addAction (start_action )
1462-
1463- stop_action = QAction ("停止模拟" , self )
1464- stop_action .triggered .connect (self .stop_clicking )
1465- tray_menu .addAction (stop_action )
1466-
1467- exit_action = QAction ("退出" , self )
1468- exit_action .triggered .connect (self .close )
1469- tray_menu .addAction (exit_action )
1470-
1471- self .tray_icon .setContextMenu (tray_menu )
1472- self .tray_icon .show ()
1473-
1474- self .tray_icon .activated .connect (self .tray_icon_activated )
14751666
14761667 def tray_icon_activated (self , reason ):
14771668 if reason == QSystemTrayIcon .DoubleClick :
@@ -2009,16 +2200,16 @@ def update_performance_charts(self):
20092200
20102201
20112202 def closeEvent (self , event ):
2203+ if hasattr (self , 'tray_icon' ) and self .tray_icon :
2204+ self .tray_icon .hide ()
20122205 self .stop_clicking ()
20132206 self .stop_remote_control ()
20142207 self .save_settings ()
20152208
20162209 if hasattr (self , 'keyboard_listener' ):
20172210 self .keyboard_listener .stop ()
20182211
2019- if self .tray_icon :
2020- self .tray_icon .hide ()
2021-
2212+
20222213 event .accept ()
20232214
20242215
0 commit comments