功能介绍
界面主要分为四个功能区:
1. 窗口选择区
- 下拉框选择游戏窗口(默认"腾讯手游助手(64位)")
- 刷新按钮:更新窗口列表
2. 刷新控制区
- 手动刷新/定时刷新 单选按钮
- 刷新间隔设置(默认60秒)
- 三个控制按钮:
-
- 开始:启动自动化
- 停止:停止自动化
- 立即刷新:执行一次刷新
3. 浇水控制区
- 三个功能按钮:
-
- 浇水:执行一次浇水
- 定时浇水:启动自动浇水
- 停止浇水:停止自动浇水
- 浇水间隔设置(默认300秒)
4. 其他功能
- 去无人机旁边:角色移动到无人机位置
- 状态显示框:实时显示操作日志
使用流程
- 选择游戏窗口
- 根据需要选择:
-
- 单次浇水:点击"浇水"按钮
- 定时浇水:设置间隔时间,点击"定时浇水"
- 位置刷新:可选择手动或定时刷新
- 查看状态框了解执行情况
一、核心实现
1. 窗口控制
def find_game_window(self):
"""查找游戏窗口"""
self.window_handle = self.user32.FindWindowW(None, self.window_title)
# window_handle 就像窗口的身份证号,后续操作都需要用到它
2. 窗口激活
def activate_window(self):
"""激活并前置窗口"""
self.user32.ShowWindow(self.window_handle, 9)
self.user32.SetForegroundWindow(self.window_handle)
3. 浇水操作
def water_plants(self):
"""执行浇水操作"""
# 1. 先移动到无人机旁边
if self.move_to_drone():
# 2. 按Enter键浇水
self.user32.keybd_event(0x0D, 0, 0, 0) # 按下Enter
self.user32.keybd_event(0x0D, 0, 2, 0) # 释放Enter
二、重要知识点
1. Windows API
Windows 提供的系统接口,通过 ctypes 库调用,用于实现系统级的操作控制。
2. 按键码对照
# 游戏中用到的按键码
KEY_T = 0x54 # 刷新位置
KEY_A = 0x41 # 移动到无人机
KEY_ENTER = 0x0D # 浇水确认
3. 异常处理
try:
self.water_plants()
except Exception as e:
print(f"浇水失败:{str(e)}")
三、代码结构
class GameAutomation:
def __init__(self):
# 初始化基础配置
self.window_title = "腾讯手游助手(64位)"
def find_game_window(self):
# 查找窗口
def activate_window(self):
# 激活窗口
def move_to_drone(self):
# 移动到无人机
def water_plants(self):
# 执行浇水
四、使用指南
- 环境准备:
-
- Python 3.6+
- 管理员权限
- 腾讯手游助手
- 使用步骤:
-
- 打开元梦之星
- 运行自动化程序
- 选择浇水功能
- 注意事项:
-
- 需要管理员权限
- 确保角色在农场
- 不要关闭游戏窗口(可最小化)
Windows可运行文件.exe点开主页下载
五、源代码
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QLabel, QComboBox, QPushButton,
QRadioButton, QButtonGroup, QSpinBox, QTextEdit,
QGroupBox, QMessageBox)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QFont, QIcon
import sys
import time
from game_automation import GameAutomation
# 定义样式表
STYLE_SHEET = """
QMainWindow {
background-color: white;
}
QPushButton {
background-color: #87CEEB;
color: white;
border: none;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
}
QPushButton:hover {
background-color: #1E90FF;
}
QPushButton:pressed {
background-color: #4169E1;
}
QPushButton:disabled {
background-color: #B0C4DE;
}
QComboBox {
border: 1px solid #87CEEB;
border-radius: 4px;
padding: 5px;
}
QRadioButton {
font-size: 12px;
padding: 2px;
}
QSpinBox {
border: 1px solid #87CEEB;
border-radius: 4px;
padding: 2px;
}
QTextEdit {
border: 1px solid #87CEEB;
border-radius: 4px;
background-color: white;
font-family: "Microsoft YaHei";
font-size: 11px;
}
"""
class RefreshThread(QThread):
"""自动刷新线程"""
status_signal = pyqtSignal(str)
def __init__(self, game, interval):
super().__init__()
self.game = game
self.interval = interval
self._is_running = True
def run(self):
while self._is_running:
try:
# 直接执行刷新操作
if self.game.refresh_position():
self.status_signal.emit("自动刷新成功")
else:
self.status_signal.emit("自动刷新失败")
# 使用单次sleep,便于及时停止
for i in range(self.interval):
if not self._is_running:
break
time.sleep(1)
except Exception as e:
self.status_signal.emit(f"自动刷新出错: {str(e)}")
break
def stop(self):
"""停止线程"""
self._is_running = False
class WateringThread(QThread):
"""定时浇水线程"""
status_signal = pyqtSignal(str)
def __init__(self, game, interval):
super().__init__()
self.game = game
self.interval = interval
self._is_running = True
def run(self):
while self._is_running:
try:
# 执行浇水操作
if self.game.move_to_drone():
self.status_signal.emit("已移动到无人机旁边")
time.sleep(0.2)
if self.game.click_all_button():
self.status_signal.emit("浇水完成")
else:
self.status_signal.emit("浇水失败")
else:
self.status_signal.emit("移动失败")
# 等待指定时间
for i in range(self.interval):
if not self._is_running:
break
time.sleep(1)
except Exception as e:
self.status_signal.emit(f"浇水时发生错误: {str(e)}")
break
def stop(self):
"""停止线程"""
self._is_running = False
class GameAutomationGUI(QMainWindow):
def __init__(self):
super().__init__()
self.game = GameAutomation()
self.refresh_thread = None
self.watering_thread = None # 添加浇水线程
self.setup_ui()
self.setStyleSheet(STYLE_SHEET)
def setup_ui(self):
self.setWindowTitle("游戏自动化工具")
self.setFixedSize(300, 450) # 减小窗口大小
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
layout.setSpacing(8) # 减小间距
layout.setContentsMargins(10, 10, 10, 10) # 减小边距
# 窗口选择区
window_layout = QHBoxLayout()
self.window_combo = QComboBox()
self.window_combo.addItem("腾讯手游助手(64位)")
refresh_list_btn = QPushButton("刷新")
refresh_list_btn.clicked.connect(self.refresh_window_list)
window_layout.addWidget(self.window_combo, stretch=4)
window_layout.addWidget(refresh_list_btn, stretch=1)
layout.addLayout(window_layout)
# 刷新设置区
refresh_layout = QHBoxLayout()
radio_group = QButtonGroup(self)
self.manual_radio = QRadioButton("手动刷新")
self.auto_radio = QRadioButton("定时刷新")
self.manual_radio.setChecked(True)
radio_group.addButton(self.manual_radio)
radio_group.addButton(self.auto_radio)
self.interval_spin = QSpinBox()
self.interval_spin.setRange(1, 3600)
self.interval_spin.setValue(60)
self.interval_spin.setFixedWidth(60)
refresh_layout.addWidget(self.manual_radio)
refresh_layout.addWidget(self.auto_radio)
refresh_layout.addWidget(QLabel("间隔:"))
refresh_layout.addWidget(self.interval_spin)
refresh_layout.addWidget(QLabel("秒"))
refresh_layout.addStretch()
layout.addLayout(refresh_layout)
# 控制按钮区
control_layout = QHBoxLayout()
self.start_btn = QPushButton("开始")
self.stop_btn = QPushButton("停止")
self.refresh_now_btn = QPushButton("立即刷新")
for btn in [self.start_btn, self.stop_btn, self.refresh_now_btn]:
btn.setFixedHeight(35) # 统一按钮高度
control_layout.addWidget(btn)
self.start_btn.clicked.connect(self.start_automation)
self.stop_btn.clicked.connect(self.stop_automation)
self.refresh_now_btn.clicked.connect(self.refresh_now)
self.stop_btn.setEnabled(False)
layout.addLayout(control_layout)
# 功能按钮区
function_layout = QVBoxLayout() # 改为垂直布局
# 浇水按钮区
water_btn_layout = QHBoxLayout()
self.water_btn = QPushButton("浇水")
self.auto_water_btn = QPushButton("定时浇水")
self.stop_water_btn = QPushButton("停止浇水")
for btn in [self.water_btn, self.auto_water_btn, self.stop_water_btn]:
btn.setFixedHeight(35)
water_btn_layout.addWidget(btn)
self.water_btn.clicked.connect(self.water_plants)
self.auto_water_btn.clicked.connect(self.start_auto_watering)
self.stop_water_btn.clicked.connect(self.stop_auto_watering)
self.stop_water_btn.setEnabled(False)
function_layout.addLayout(water_btn_layout)
# 浇水间隔设置
water_interval_layout = QHBoxLayout()
water_interval_layout.addWidget(QLabel("浇水间隔:"))
self.water_interval_spin = QSpinBox()
self.water_interval_spin.setRange(1, 3600)
self.water_interval_spin.setValue(300) # 默认5分钟
self.water_interval_spin.setFixedWidth(60)
water_interval_layout.addWidget(self.water_interval_spin)
water_interval_layout.addWidget(QLabel("秒"))
water_interval_layout.addStretch()
function_layout.addLayout(water_interval_layout)
# 其他功能按钮
other_btn_layout = QHBoxLayout()
self.drone_btn = QPushButton("去无人机旁边")
self.drone_btn.setFixedHeight(35)
self.drone_btn.clicked.connect(self.go_to_drone)
other_btn_layout.addWidget(self.drone_btn)
function_layout.addLayout(other_btn_layout)
layout.addLayout(function_layout)
# 状态显示区
self.status_text = QTextEdit()
self.status_text.setReadOnly(True)
self.status_text.setFixedHeight(200) # 固定状态框高度
layout.addWidget(self.status_text)
def log_status(self, message):
"""记录状态信息"""
current_time = time.strftime("%H:%M:%S")
self.status_text.append(f"{current_time} - {message}")
def refresh_window_list(self):
"""刷新窗口列表"""
window_titles = self.game.list_all_windows()
self.window_combo.clear()
self.window_combo.addItems(window_titles)
if window_titles:
self.log_status("窗口列表已刷新")
else:
self.log_status("未找到任何窗口")
def refresh_now(self):
"""立即执行一次刷新"""
if not self.game.window_handle:
self.log_status("请先选择并启动游戏窗口!")
return
if self.game.refresh_position():
self.log_status("刷新成功")
else:
self.log_status("刷新失败")
def start_automation(self):
"""开始自动化"""
selected_window = self.window_combo.currentText()
if not selected_window:
QMessageBox.critical(self, "错误", "请选择一个窗口")
return
self.game.window_title = selected_window
if not self.game.find_game_window():
QMessageBox.critical(self, "错误", "无法找到选择的窗口")
return
if not self.game.initialize_game_state():
QMessageBox.critical(self, "错误", "窗口初始化失败")
return
self.start_btn.setEnabled(False)
self.stop_btn.setEnabled(True)
if self.auto_radio.isChecked():
# 立即执行一次刷新
if self.game.refresh_position():
self.log_status("初始刷新成功")
else:
self.log_status("初始刷新失败")
# 启动自动刷新线程
self.refresh_thread = RefreshThread(self.game, self.interval_spin.value())
self.refresh_thread.status_signal.connect(self.log_status)
self.refresh_thread.start()
self.log_status("自动化已启动")
def stop_automation(self):
"""停止自动化"""
if self.refresh_thread and self.refresh_thread.isRunning():
self.refresh_thread.stop()
self.refresh_thread.wait()
self.refresh_thread = None
self.start_btn.setEnabled(True)
self.stop_btn.setEnabled(False)
self.log_status("自动化已停止")
def go_to_drone(self):
"""执行去无人机旁边的操作"""
if not self.game.window_handle:
QMessageBox.critical(self, "错误", "请先选择并启动游戏窗口!")
return
try:
if self.game.move_to_drone():
self.log_status("已移动到无人机旁边")
else:
self.log_status("移动失败")
except Exception as e:
self.log_status(f"移动时发生错误: {str(e)}")
def water_plants(self):
"""执行浇水操作"""
if not self.game.window_handle:
QMessageBox.critical(self, "错误", "请先选择并启动游戏窗口!")
return
try:
if self.game.move_to_drone():
self.log_status("已移动到无人机旁边")
time.sleep(0.2) # 减少等待时间
if self.game.click_all_button():
self.log_status("浇水完成")
else:
self.log_status("浇水失败")
else:
self.log_status("移动失败")
except Exception as e:
self.log_status(f"浇水时发生错误: {str(e)}")
def start_auto_watering(self):
"""开始定时浇水"""
if not self.game.window_handle:
QMessageBox.critical(self, "错误", "请先选择并启动游戏窗口!")
return
self.watering_thread = WateringThread(self.game, self.water_interval_spin.value())
self.watering_thread.status_signal.connect(self.log_status)
self.watering_thread.start()
self.auto_water_btn.setEnabled(False)
self.stop_water_btn.setEnabled(True)
self.log_status("定时浇水已启动")
def stop_auto_watering(self):
"""停止定时浇水"""
if self.watering_thread and self.watering_thread.isRunning():
self.watering_thread.stop()
self.watering_thread.wait()
self.watering_thread = None
self.auto_water_btn.setEnabled(True)
self.stop_water_btn.setEnabled(False)
self.log_status("定时浇水已停止")
def closeEvent(self, event):
"""窗口关闭事件"""
if self.refresh_thread:
self.refresh_thread.stop()
self.refresh_thread.wait()
if self.watering_thread:
self.watering_thread.stop()
self.watering_thread.wait()
event.accept()
if __name__ == "__main__":
app = QApplication(sys.argv)
# 设置应用字体
font = QFont("Microsoft YaHei", 9) # 使用微软雅黑字体
app.setFont(font)
window = GameAutomationGUI()
window.show()
sys.exit(app.exec())
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QLabel, QComboBox, QPushButton,
QRadioButton, QButtonGroup, QSpinBox, QTextEdit,
QGroupBox, QMessageBox)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QFont, QIcon
import sys
import time
from game_automation import GameAutomation
# 定义样式表
STYLE_SHEET = """
QMainWindow {
background-color: white;
}
QPushButton {
background-color: #87CEEB;
color: white;
border: none;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
}
QPushButton:hover {
background-color: #1E90FF;
}
QPushButton:pressed {
background-color: #4169E1;
}
QPushButton:disabled {
background-color: #B0C4DE;
}
QComboBox {
border: 1px solid #87CEEB;
border-radius: 4px;
padding: 5px;
}
QRadioButton {
font-size: 12px;
padding: 2px;
}
QSpinBox {
border: 1px solid #87CEEB;
border-radius: 4px;
padding: 2px;
}
QTextEdit {
border: 1px solid #87CEEB;
border-radius: 4px;
background-color: white;
font-family: "Microsoft YaHei";
font-size: 11px;
}
"""
class RefreshThread(QThread):
"""自动刷新线程"""
status_signal = pyqtSignal(str)
def __init__(self, game, interval):
super().__init__()
self.game = game
self.interval = interval
self._is_running = True
def run(self):
while self._is_running:
try:
# 直接执行刷新操作
if self.game.refresh_position():
self.status_signal.emit("自动刷新成功")
else:
self.status_signal.emit("自动刷新失败")
# 使用单次sleep,便于及时停止
for i in range(self.interval):
if not self._is_running:
break
time.sleep(1)
except Exception as e:
self.status_signal.emit(f"自动刷新出错: {str(e)}")
break
def stop(self):
"""停止线程"""
self._is_running = False
class WateringThread(QThread):
"""定时浇水线程"""
status_signal = pyqtSignal(str)
def __init__(self, game, interval):
super().__init__()
self.game = game
self.interval = interval
self._is_running = True
def run(self):
while self._is_running:
try:
# 执行浇水操作
if self.game.move_to_drone():
self.status_signal.emit("已移动到无人机旁边")
time.sleep(0.2)
if self.game.click_all_button():
self.status_signal.emit("浇水完成")
else:
self.status_signal.emit("浇水失败")
else:
self.status_signal.emit("移动失败")
# 等待指定时间
for i in range(self.interval):
if not self._is_running:
break
time.sleep(1)
except Exception as e:
self.status_signal.emit(f"浇水时发生错误: {str(e)}")
break
def stop(self):
"""停止线程"""
self._is_running = False
class GameAutomationGUI(QMainWindow):
def __init__(self):
super().__init__()
self.game = GameAutomation()
self.refresh_thread = None
self.watering_thread = None # 添加浇水线程
self.setup_ui()
self.setStyleSheet(STYLE_SHEET)
def setup_ui(self):
self.setWindowTitle("游戏自动化工具")
self.setFixedSize(300, 450) # 减小窗口大小
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
layout.setSpacing(8) # 减小间距
layout.setContentsMargins(10, 10, 10, 10) # 减小边距
# 窗口选择区
window_layout = QHBoxLayout()
self.window_combo = QComboBox()
self.window_combo.addItem("腾讯手游助手(64位)")
refresh_list_btn = QPushButton("刷新")
refresh_list_btn.clicked.connect(self.refresh_window_list)
window_layout.addWidget(self.window_combo, stretch=4)
window_layout.addWidget(refresh_list_btn, stretch=1)
layout.addLayout(window_layout)
# 刷新设置区
refresh_layout = QHBoxLayout()
radio_group = QButtonGroup(self)
self.manual_radio = QRadioButton("手动刷新")
self.auto_radio = QRadioButton("定时刷新")
self.manual_radio.setChecked(True)
radio_group.addButton(self.manual_radio)
radio_group.addButton(self.auto_radio)
self.interval_spin = QSpinBox()
self.interval_spin.setRange(1, 3600)
self.interval_spin.setValue(60)
self.interval_spin.setFixedWidth(60)
refresh_layout.addWidget(self.manual_radio)
refresh_layout.addWidget(self.auto_radio)
refresh_layout.addWidget(QLabel("间隔:"))
refresh_layout.addWidget(self.interval_spin)
refresh_layout.addWidget(QLabel("秒"))
refresh_layout.addStretch()
layout.addLayout(refresh_layout)
# 控制按钮区
control_layout = QHBoxLayout()
self.start_btn = QPushButton("开始")
self.stop_btn = QPushButton("停止")
self.refresh_now_btn = QPushButton("立即刷新")
for btn in [self.start_btn, self.stop_btn, self.refresh_now_btn]:
btn.setFixedHeight(35) # 统一按钮高度
control_layout.addWidget(btn)
self.start_btn.clicked.connect(self.start_automation)
self.stop_btn.clicked.connect(self.stop_automation)
self.refresh_now_btn.clicked.connect(self.refresh_now)
self.stop_btn.setEnabled(False)
layout.addLayout(control_layout)
# 功能按钮区
function_layout = QVBoxLayout() # 改为垂直布局
# 浇水按钮区
water_btn_layout = QHBoxLayout()
self.water_btn = QPushButton("浇水")
self.auto_water_btn = QPushButton("定时浇水")
self.stop_water_btn = QPushButton("停止浇水")
for btn in [self.water_btn, self.auto_water_btn, self.stop_water_btn]:
btn.setFixedHeight(35)
water_btn_layout.addWidget(btn)
self.water_btn.clicked.connect(self.water_plants)
self.auto_water_btn.clicked.connect(self.start_auto_watering)
self.stop_water_btn.clicked.connect(self.stop_auto_watering)
self.stop_water_btn.setEnabled(False)
function_layout.addLayout(water_btn_layout)
# 浇水间隔设置
water_interval_layout = QHBoxLayout()
water_interval_layout.addWidget(QLabel("浇水间隔:"))
self.water_interval_spin = QSpinBox()
self.water_interval_spin.setRange(1, 3600)
self.water_interval_spin.setValue(300) # 默认5分钟
self.water_interval_spin.setFixedWidth(60)
water_interval_layout.addWidget(self.water_interval_spin)
water_interval_layout.addWidget(QLabel("秒"))
water_interval_layout.addStretch()
function_layout.addLayout(water_interval_layout)
# 其他功能按钮
other_btn_layout = QHBoxLayout()
self.drone_btn = QPushButton("去无人机旁边")
self.drone_btn.setFixedHeight(35)
self.drone_btn.clicked.connect(self.go_to_drone)
other_btn_layout.addWidget(self.drone_btn)
function_layout.addLayout(other_btn_layout)
layout.addLayout(function_layout)
# 状态显示区
self.status_text = QTextEdit()
self.status_text.setReadOnly(True)
self.status_text.setFixedHeight(200) # 固定状态框高度
layout.addWidget(self.status_text)
def log_status(self, message):
"""记录状态信息"""
current_time = time.strftime("%H:%M:%S")
self.status_text.append(f"{current_time} - {message}")
def refresh_window_list(self):
"""刷新窗口列表"""
window_titles = self.game.list_all_windows()
self.window_combo.clear()
self.window_combo.addItems(window_titles)
if window_titles:
self.log_status("窗口列表已刷新")
else:
self.log_status("未找到任何窗口")
def refresh_now(self):
"""立即执行一次刷新"""
if not self.game.window_handle:
self.log_status("请先选择并启动游戏窗口!")
return
if self.game.refresh_position():
self.log_status("刷新成功")
else:
self.log_status("刷新失败")
def start_automation(self):
"""开始自动化"""
selected_window = self.window_combo.currentText()
if not selected_window:
QMessageBox.critical(self, "错误", "请选择一个窗口")
return
self.game.window_title = selected_window
if not self.game.find_game_window():
QMessageBox.critical(self, "错误", "无法找到选择的窗口")
return
if not self.game.initialize_game_state():
QMessageBox.critical(self, "错误", "窗口初始化失败")
return
self.start_btn.setEnabled(False)
self.stop_btn.setEnabled(True)
if self.auto_radio.isChecked():
# 立即执行一次刷新
if self.game.refresh_position():
self.log_status("初始刷新成功")
else:
self.log_status("初始刷新失败")
# 启动自动刷新线程
self.refresh_thread = RefreshThread(self.game, self.interval_spin.value())
self.refresh_thread.status_signal.connect(self.log_status)
self.refresh_thread.start()
self.log_status("自动化已启动")
def stop_automation(self):
"""停止自动化"""
if self.refresh_thread and self.refresh_thread.isRunning():
self.refresh_thread.stop()
self.refresh_thread.wait()
self.refresh_thread = None
self.start_btn.setEnabled(True)
self.stop_btn.setEnabled(False)
self.log_status("自动化已停止")
def go_to_drone(self):
"""执行去无人机旁边的操作"""
if not self.game.window_handle:
QMessageBox.critical(self, "错误", "请先选择并启动游戏窗口!")
return
try:
if self.game.move_to_drone():
self.log_status("已移动到无人机旁边")
else:
self.log_status("移动失败")
except Exception as e:
self.log_status(f"移动时发生错误: {str(e)}")
def water_plants(self):
"""执行浇水操作"""
if not self.game.window_handle:
QMessageBox.critical(self, "错误", "请先选择并启动游戏窗口!")
return
try:
if self.game.move_to_drone():
self.log_status("已移动到无人机旁边")
time.sleep(0.2) # 减少等待时间
if self.game.click_all_button():
self.log_status("浇水完成")
else:
self.log_status("浇水失败")
else:
self.log_status("移动失败")
except Exception as e:
self.log_status(f"浇水时发生错误: {str(e)}")
def start_auto_watering(self):
"""开始定时浇水"""
if not self.game.window_handle:
QMessageBox.critical(self, "错误", "请先选择并启动游戏窗口!")
return
self.watering_thread = WateringThread(self.game, self.water_interval_spin.value())
self.watering_thread.status_signal.connect(self.log_status)
self.watering_thread.start()
self.auto_water_btn.setEnabled(False)
self.stop_water_btn.setEnabled(True)
self.log_status("定时浇水已启动")
def stop_auto_watering(self):
"""停止定时浇水"""
if self.watering_thread and self.watering_thread.isRunning():
self.watering_thread.stop()
self.watering_thread.wait()
self.watering_thread = None
self.auto_water_btn.setEnabled(True)
self.stop_water_btn.setEnabled(False)
self.log_status("定时浇水已停止")
def closeEvent(self, event):
"""窗口关闭事件"""
if self.refresh_thread:
self.refresh_thread.stop()
self.refresh_thread.wait()
if self.watering_thread:
self.watering_thread.stop()
self.watering_thread.wait()
event.accept()
if __name__ == "__main__":
app = QApplication(sys.argv)
# 设置应用字体
font = QFont("Microsoft YaHei", 9) # 使用微软雅黑字体
app.setFont(font)
window = GameAutomationGUI()
window.show()
sys.exit(app.exec())