yolo自动化项目实例解析(四)ui页面整理1 (1.85)

我们在上一章整理main.py 的if __name__ == '__main__':  内容还留下面这一段,

            from PyQt5.QtWidgets import *from lanrenauto.moni.moni import *from PyQt5.QtGui import *app = QApplication(sys.argv)  # 初始化Qt应用ratio = screen_width / 2560  # 分辨率比例# 设置全局字体大小# 计算字体大小base_font_size = 13# 基准字体大小,适合1920*1080分辨率new_font_size = int(base_font_size * ratio)font = QFont("Arial", new_font_size)# 子控件的宽度item_width=320item_height=240item_height_min = 60window_main = MainWindow()window_main.show()sys.exit(app.exec_())  # 监听消息不关闭

在说这个之前先了解一些基本的ui工具及使用

一、ui工具Qt Designer

pip install pyqt5
pip install pyside2

上面这两个工具支持两个不同版本的ui页面创建,并且保存的文件的依赖库也不一样,我们这里主要用pyqt5

1、启动ui编辑器

#pyqt5
designer#pyside2
pyside2-designerr

编辑器都一样,执行一个就行,这里打开pyqt5的

 

 

这里注意一下,你创建的ui项目这里的类名,你如果想要在项目里面调用窗口的信息都是基于类名的

2、保存ui文件

我们这里随便整俩按钮,然后保存到项目ui/目录下叫test.ui

 

3、ui转py代码

pyuic5 -o ./test.py ./test.ui#如果是pyside2 则是
#pyside2-uic --from-imports -o ./test.py  ./test.ui

test.py

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file './test.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(800, 600)self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.pushButton = QtWidgets.QPushButton(self.centralwidget)self.pushButton.setGeometry(QtCore.QRect(572, 90, 131, 28))self.pushButton.setObjectName("pushButton")self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_2.setGeometry(QtCore.QRect(572, 240, 131, 28))self.pushButton_2.setObjectName("pushButton_2")MainWindow.setCentralWidget(self.centralwidget)self.menubar = QtWidgets.QMenuBar(MainWindow)self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))self.menubar.setObjectName("menubar")MainWindow.setMenuBar(self.menubar)self.statusbar = QtWidgets.QStatusBar(MainWindow)self.statusbar.setObjectName("statusbar")MainWindow.setStatusBar(self.statusbar)self.retranslateUi(MainWindow)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))self.pushButton.setText(_translate("MainWindow", "PushButton1"))self.pushButton_2.setText(_translate("MainWindow", "PushButton2"))

4、py调用页面打开

import sys
from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from ui.test import Ui_MainWindow#MainWindow 是继承了俩父类QMainWindow 和Ui_MainWindow
#QMainWindow 类是我们上面建窗口的时候的类,提供了一系列那种类型窗口的方法调用
#比如窗口标题、导航条、页面显示啥啥的
#Ui_MainWindow 是我们刚才去窗口的页面主窗口,我们继承后就可以通过self直接调用窗口
class MainWindow(QMainWindow , Ui_MainWindow):def __init__(self):super().__init__()  # 调用基类构造方法self.setupUi(self)  # 设置UI布局self.retranslateUi(self)  # 重新翻译UI组件的文字if __name__ == '__main__':app = QApplication(sys.argv)  # 初始化Qt应用# 创建主窗口实例window_main = MainWindow()# 显示主窗口window_main.show()# 进入事件循环sys.exit(app.exec_())

5、ui页面与代码交互

import sys
from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from ui.test import Ui_MainWindow#MainWindow 是继承了俩父类QMainWindow 和Ui_MainWindow
#QMainWindow 类是我们上面建窗口的时候的类,提供了一系列那种类型窗口的方法调用
#比如窗口标题、导航条、页面显示啥啥的
#Ui_MainWindow 是我们刚才去窗口的页面主窗口,我们继承后就可以通过self直接调用窗口
class MainWindow(QMainWindow , Ui_MainWindow):def __init__(self):super().__init__()  # 调用基类构造方法self.setupUi(self)  # 设置UI布局self.retranslateUi(self)  # 重新翻译UI组件的文字# 连接按钮箱的信号到槽函数self.pushButton.clicked.connect(self.on_push_button_clicked)self.pushButton_2.clicked.connect(self.on_push_button_2_clicked)def on_push_button_clicked(self):print("PushButton1 被点击")# 在这里执行PushButton1的操作def on_push_button_2_clicked(self):print("PushButton2 被点击")# 在这里执行PushButton2的操作
if __name__ == '__main__':app = QApplication(sys.argv)  # 初始化Qt应用# 创建主窗口实例window_main = MainWindow()# 显示主窗口window_main.show()# 进入事件循环sys.exit(app.exec_())

关于按键怎么找

    def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))#看这里pushButton 和pushButton_2就是我们要用的链接信号槽的名称self.pushButton.setText(_translate("MainWindow", "PushButton1"))self.pushButton_2.setText(_translate("MainWindow", "PushButton2"))

 

二、main解析

            from PyQt5.QtWidgets import *from lanrenauto.moni.moni import *from PyQt5.QtGui import *app = QApplication(sys.argv)  # 初始化Qt应用ratio = screen_width / 2560  # 分辨率比例# 设置全局字体大小# 计算字体大小base_font_size = 13# 基准字体大小,适合1920*1080分辨率new_font_size = int(base_font_size * ratio)font = QFont("Arial", new_font_size)# 子控件的宽度item_width=320item_height=240item_height_min = 60window_main = MainWindow()window_main.show()sys.exit(app.exec_())  # 监听消息不关闭

这个其实和我们上面做的基本一致,我们主要这里看下MainWindow类

1、添加MainWindow类主窗口

vi main.py

try:import subprocessimport asyncioimport functoolsimport os.pathfrom datetime import datetimeimport configparserimport reimport shutilimport timeimport threadingimport webbrowserimport pyautoguifrom qtpy import QtWidgetsfrom lanrenauto.logger_module import loggerfrom lanrenauto.moni.moni import *import autoimport sysimport statefrom wayfinding import *from PyQt5.Qt import *from PyQt5.QtGui import *from PyQt5.QtCore import *from PyQt5.QtWidgets import QMessageBoxfrom lanrenauto.jianchaupdate import get_var_data, get_updatetxtfrom lanrenauto.moni.moni import *import osfrom lanrenauto.findpic.findimg import *  # 找图 搜图from lanrenauto.tools.screenshot import screenshot  # 截图from lanrenauto.yolov.lanrenonnx import LanRenOnnxYolov
except:logger.error(traceback.format_exc())class MainWindow(QMainWindow, Ui_mainWindow):def __init__(self):super().__init__()self.set_ui()self.setupUi(self)self.setWindowIcon(QIcon("datas/logo.png"))self.setWindowTitle(f"懒人原神AI{state.版本号}  F8暂停 F9停止 F10标记")self.resize(state.WINDOW_WIDTH, state.WINDOW_HEIGHT)self.move(state.WINDOW_LEFT, state.WINDOW_TOP)self.g_box = QGridLayout()self.container_widget = QWidget()  # 创建一个中间部件  为了可以让g_布局超过窗口大小self.container_widget.setLayout(self.g_box)  # 将网格布局设置给中间部件self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft)  # 布局 左上对齐self.g_box.setContentsMargins(0, 0, 0, 0)  # 边距self.g_box.setAlignment(Qt.AlignTop)self.sa_main.setWidget(self.container_widget)  # 将中间部件设置为QScrollArea的子部件# 获取纵向滚动条控件vertical_scrollbar = self.findChild(QScrollArea)self.v_scrollbar = vertical_scrollbar.verticalScrollBar()self.setWindowFlags(Qt.WindowStaysOnTopHint)self.row = 0self.column = -1self.run_times = 1self.column_step = 310# 所有数据self.datas = []# 创建一个计时器,用于延迟布局self.timer = QTimer(self)self.timer.setSingleShot(True)  # 设置为单次触发self.timer.timeout.connect(self.update_layout)self.connect_set()# 加载任务包列表self.load_task_packs()self.show_tool_item(state.PATH_TASK)self.timer_luzhi = QTimer(self)self.timer_luzhi.timeout.connect(self.timeout_luzhi)self.timer_luzhi_chuansong = QTimer(self)self.timer_luzhi_chuansong.timeout.connect(self.timeout_luzhi_chuansong)self.timer_luzhi_lianzhao = QTimer(self)self.timer_luzhi_lianzhao.timeout.connect(self.timeout_luzhi_lianzhao)self.timer_huifang = QTimer(self)self.timer_huifang.timeout.connect(self.timeout_huifang)# 获取主窗口的状态栏对象self.statusbar = self.statusBar()# 设置状态栏文本self.statusbar.showMessage('本工具仅在QQ群789467094中免费分享!欢迎使用懒人原神AI!')# 禁止截图# set_window_display_affinity(int(self.winId()))# self.toolBar.setMovable(True)# self.toolBar.setFloatable(True)# self.toolBar.setAllowedAreas(Qt.AllToolBarAreas)def load_task_packs(self):self.toolBar.clear()packs = state.PACKS_TASK.split("#@@#")try:if len(packs) >= 1:for pack in packs:if pack != "":self.add_tool_item(pack)else:self.add_tool_item(state.PACKS_TASK)except:passdef update_tasks(self):try:self.datas = []self.row = 0self.column = -1# 清空当前布局for i in reversed(range(self.g_box.count())):self.g_box.itemAt(i).widget().setParent(None)# 遍历文件夹下有哪些目录# 判断这个路径是否存在if not os.path.exists(state.PATH_TASK):state.PATH_TASK = "./datas/Task/"# 创建 ConfigParser 对象config_main = configparser.ConfigParser()# 加载 INI 文件config_main.read(os.path.join(state.PATH_TASK, "细节参数.ini"))self.run_times = int(config_main.get('seting', 'run_times', fallback='1'))self.action_run_times.setText(f"设置:当前任务包 执行次数:{self.run_times}")# 获取文件夹列表folders = [item for item in os.listdir(state.PATH_TASK) ifos.path.isdir(os.path.join(state.PATH_TASK, item))]# 将文件夹名称中的数字提取出来,并按照数字大小排序sorted_folders = sorted(folders, key=lambda x: extract_number(x))for item in sorted_folders:item_path = os.path.join(state.PATH_TASK, item)if os.path.isdir(item_path):# 创建 ConfigParser 对象config = configparser.ConfigParser()# 加载 INI 文件config.read(os.path.join(item_path, "jiaoben.ini"))if config.get('seting', 'type', fallback='1') == "2":# 副本任务self.add_taskfuben(item_path, config)elif config.get('seting', 'type', fallback='1') == "3":# 脚本任务self.add_taskjiaoben(item_path, config)elif config.get('seting', 'type', fallback='1') == "4":# 脚本任务self.add_xuanjue(item_path, config)elif config.get('seting', 'type', fallback='1') == "5":# 脚本任务self.add_xuanlianzhao(item_path, config)elif config.get('seting', 'type', fallback='1') == "6":self.add_taskpy(item_path, config)else:# 锄地任务self.add_task(item_path, config)except Exception:logger.info(f"请选择任务文件夹,目前没有这个文件夹{state.PATH_TASK}")def resizeEvent(self, event):super().resizeEvent(event)self.data = []# 每当用户调整窗口大小时,启动计时器self.timer.start(300)  # 500毫秒后触发timeout信号def timeout_luzhi(self):if state.录制_脚本文本 != "":tangbaowss.send_msg("是否禁止录制#@@#真")state.状态_是否禁止录制 = Truedir_ = os.path.join(state.PATH_TASK, self.datas[state.录制_当前任务索引]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成path = dir_ + "/脚本.txt"with open(path, "w", encoding="gbk", newline='') as f:f.write(state.录制_脚本文本)self.datas[state.录制_当前任务索引]["jiaoben"] = "脚本.txt"self.datas[state.录制_当前任务索引]["f_item"].bt_jiaoben.setProperty("OK_jiaoben", True)logger.info(f"导入脚本成功:{path}")self.sg.mysig_tishi.emit(f"导入脚本成功:{path}")self.datas[state.录制_当前任务索引]["f_item"].bt_jiaoben.setStyleSheet("""#bt_jiaoben[OK_jiaoben="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")state.录制_脚本文本 = ""self.save_ini(dir_, self.datas[state.录制_当前任务索引])self.timer_luzhi.stop()def timeout_luzhi_chuansong(self):if state.录制_脚本文本 != "":tangbaowss.send_msg("是否禁止录制#@@#真")state.状态_是否禁止录制 = Truedir_ = os.path.join(state.PATH_TASK, self.datas[state.录制_当前任务索引]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成path = dir_ + "/传送脚本.txt"with open(path, "w", encoding="gbk", newline='') as f:f.write(state.录制_脚本文本)self.datas[state.录制_当前任务索引]["chuansong"] = "传送脚本.txt"self.datas[state.录制_当前任务索引]["f_item"].bt_chuansong.setProperty("OK_chuansong", True)logger.info(f"导入脚本成功:{path}")self.sg.mysig_tishi.emit(f"导入脚本成功:{path}")self.datas[state.录制_当前任务索引]["f_item"].bt_chuansong.setStyleSheet("""#bt_chuansong[OK_chuansong="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")state.录制_脚本文本 = ""self.save_ini(dir_, self.datas[state.录制_当前任务索引])self.timer_luzhi_chuansong.stop()def timeout_luzhi_lianzhao(self):if state.录制_脚本文本 != "":tangbaowss.send_msg("是否禁止录制#@@#真")state.状态_是否禁止录制 = Truedir_ = os.path.abspath(state.PATH_JIAOBEN)if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成path = os.path.join(dir_, state.LIANZHAO)with open(path, "w", encoding="gbk", newline='') as f:f.write(state.录制_脚本文本)state.录制_脚本文本 = ""logger.info("录制并选择连招脚本成功!")self.sg.mysig_tishi.emit("录制并选择连招脚本成功!")self.save_ini_seting()self.timer_luzhi_lianzhao.stop()def timeout_huifang(self):if state.状态_循环开关 == False:state.状态_需重新传送 = Falsetangbaowss.send_msg("是否回放#@@#假")logger.info("回放结束1")self.sg.mysig_tishi.emit("回放结束1")self.timer_huifang.stop()returnif state.状态_是否回放中 == False:logger.info("回放结束2")self.sg.mysig_tishi.emit("回放结束2")self.timer_huifang.stop()def update_layout(self):try:# 获取主窗口的宽度width = self.centralWidget().width()# 计算每行可以容纳的组件数量num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1# 清空当前布局for i in reversed(range(self.g_box.count())):self.g_box.itemAt(i).widget().setParent(None)# 重新添加组件到网格布局for i, data in enumerate(self.datas):self.row = int(i // num_per_row)self.column = int(i % num_per_row)self.g_box.addWidget(data["f_item"], self.row, self.column)except:passdef connect_set(self):'''绑定信号:return:'''self.sg = MySignal()state.QT_信号 = self.sgself.sg.mysig_shutdown.connect(self.show_shutdown_dig)self.sg.mysig_mouse_through.connect(self.set_mouse_through)self.sg.mysig_tishi.connect(self.set_tishi)self.sg.mysig_next_pack.connect(self.next_pack)self.sg.mysig_show_xunlu.connect(self.show_xunlu)self.sg.mysig_show_yolov.connect(self.show_yolov)self.sg.mysig_dingwei.connect(self.dingwei)self.menu = self.menuBar()# 创建一个顶级菜单self.menu_file = self.menu.addMenu("文件")# 创建一个动作self.action_addtask = QAction("新增-AI锄地任务-大世界寻路打怪", self)self.action_addtask.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_1))self.action_addtask.triggered.connect(self.hotkey_addtask)self.menu_file.addAction(self.action_addtask)# 创建一个动作self.action_addtaskfuben = QAction("新增-AI副本任务-只需定制传送", self)self.action_addtaskfuben.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_2))self.action_addtaskfuben.triggered.connect(self.hotkey_addtaskfuben)self.menu_file.addAction(self.action_addtaskfuben)# 创建一个动作self.action_addtaskjiaoben = QAction("新增-脚本回放任务-采集/挖矿/晶蝶/等等", self)self.action_addtaskjiaoben.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_3))self.action_addtaskjiaoben.triggered.connect(self.hotkey_addtaskjiaoben)self.menu_file.addAction(self.action_addtaskjiaoben)# 创建一个动作self.action_addtaskpy = QAction("新增-Py代码任务-自定义视觉检测的任务", self)self.action_addtaskpy.triggered.connect(self.hotkey_addtaskpy)self.menu_file.addAction(self.action_addtaskpy)# 创建一个动作self.action_qiejue = QAction("新增-切换角色任务", self)self.action_qiejue.triggered.connect(self.hotkey_qiejue)self.menu_file.addAction(self.action_qiejue)# 创建一个动作self.action_qiehuanlianzhao = QAction("新增-切换连招任务", self)self.action_qiehuanlianzhao.triggered.connect(self.hotkey_qiehuanlianzhao)self.menu_file.addAction(self.action_qiehuanlianzhao)# 创建一个动作self.action_importtask = QAction("导入单个任务", self)self.action_importtask.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_4))self.action_importtask.triggered.connect(self.hotkey_importtask)self.menu_file.addAction(self.action_importtask)self.action_opentaskdir = QAction("打开任务文件夹", self)self.action_opentaskdir.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_5))self.action_opentaskdir.triggered.connect(self.hotkey_opentaskdir)self.menu_file.addAction(self.action_opentaskdir)self.action_selecttaskdir = QAction("导入任务包", self)self.action_selecttaskdir.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_6))self.action_selecttaskdir.triggered.connect(self.hotkey_selecttaskdir)self.menu_file.addAction(self.action_selecttaskdir)self.action_setlianzhao = QAction("选择连招脚本", self)self.action_setlianzhao.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_7))self.action_setlianzhao.triggered.connect(self.hotkey_setlianzhao)self.menu_file.addAction(self.action_setlianzhao)self.action_addlianzhao = QAction("录制/编辑连招", self)self.action_addlianzhao.triggered.connect(self.hotkey_addlianzhao)self.menu_file.addAction(self.action_addlianzhao)# 创建一个顶级菜单self.menu_ck = self.menu.addMenu("选择")# 创建一个动作self.action_all_ck = QAction("全部选中", self)self.action_all_ck.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_8))self.action_all_ck.triggered.connect(self.hotkey_all_ck)self.menu_ck.addAction(self.action_all_ck)self.action_all_not_ck = QAction("全部不选", self)self.action_all_not_ck.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_9))self.action_all_not_ck.triggered.connect(self.hotkey_all_not_ck)self.menu_ck.addAction(self.action_all_not_ck)self.action_all_fan_ck = QAction("全部反选", self)self.action_all_fan_ck.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_0))self.action_all_fan_ck.triggered.connect(self.hotkey_all_fan_ck)self.menu_ck.addAction(self.action_all_fan_ck)self.action_keys_ack = QAction("选中包含某个关键词的", self)self.action_keys_ack.triggered.connect(self.hotkey_keys_ack)self.menu_ck.addAction(self.action_keys_ack)self.action_num_ck = QAction("选中包含某个区间数字的", self)self.action_num_ck.triggered.connect(self.hotkey_num_ck)self.menu_ck.addAction(self.action_num_ck)self.action_find = QAction("查找并定位到包含某个关键字的任务", self)self.action_find.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F))self.action_find.triggered.connect(self.hotkey_find)self.menu_ck.addAction(self.action_find)# 创建一个顶级菜单self.menu_run = self.menu.addMenu("操作")# 创建一个动作self.action_runall = QAction("启动选中任务", self)self.action_runall.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F1))self.action_runall.triggered.connect(self.hotkey_runall)self.menu_run.addAction(self.action_runall)self.action_deltask = QAction("删除选中任务", self)self.action_deltask.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F2))self.action_deltask.triggered.connect(self.hotkey_deltask)self.menu_run.addAction(self.action_deltask)self.action_refresh = QAction("保存任务并刷新顺序", self)self.action_refresh.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_S))self.action_refresh.triggered.connect(self.save)self.menu_run.addAction(self.action_refresh)# 创建一个动作self.action_kuang = QAction("选中任务-是否勾选-矿", self)self.action_kuang.setCheckable(True)self.action_kuang.setChecked(False)self.action_kuang.triggered.connect(self.hotkey_kuang)self.action_kuang.setChecked(True)self.menu_run.addAction(self.action_kuang)# 创建一个动作self.action_hua = QAction("选中任务-是否勾选-花", self)self.action_hua.setCheckable(True)self.action_hua.setChecked(False)self.action_hua.triggered.connect(self.hotkey_hua)self.action_hua.setChecked(True)self.menu_run.addAction(self.action_hua)# 创建一个动作self.action_guai = QAction("选中任务-是否勾选-怪", self)self.action_guai.setCheckable(True)self.action_guai.setChecked(False)self.action_guai.triggered.connect(self.hotkey_guai)self.action_guai.setChecked(True)self.menu_run.addAction(self.action_guai)# 创建一个动作self.action_run_times = QAction(f"设置:当前任务包 执行次数:{self.run_times}", self)self.action_run_times.triggered.connect(self.hotkey_run_times)self.menu_run.addAction(self.action_run_times)# 创建一个顶级菜单self.menu_view = self.menu.addMenu("视图")# 创建一个动作self.action_isShow = QAction("显示检测结果窗口", self)self.action_isShow.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F11))self.action_isShow.triggered.connect(self.hotkey_isShow)self.action_isShow.setCheckable(True)self.action_isShow.setChecked(True)self.menu_view.addAction(self.action_isShow)self.hotkey_isShow()self.action_isShowCmd = QAction("是否显示控制台", self)self.action_isShowCmd.triggered.connect(self.hotkey_isShowCmd)self.action_isShowCmd.setCheckable(True)self.action_isShowCmd.setChecked(True)self.menu_view.addAction(self.action_isShowCmd)# 创建一个顶级菜单self.menu_yun = self.menu.addMenu("云端")# 创建一个动作self.action_yunduanlist = QAction("懒人群友云端资源", self)self.action_yunduanlist.triggered.connect(self.hotkey_yunduanlist)self.menu_yun.addAction(self.action_yunduanlist)# 创建一个动作self.action_yunduanup1 = QAction("分享-副本打怪任务", self)self.action_yunduanup1.triggered.connect(lambda: webbrowser.open("https://nas.qizhiqiang.com:5001/sharing/viwvNEP8c"))self.menu_yun.addAction(self.action_yunduanup1)self.action_yunduanup2 = QAction("分享-打怪锄地任务", self)self.action_yunduanup2.triggered.connect(lambda: webbrowser.open("https://nas.qizhiqiang.com:5001/sharing/GjM0zwWAw"))self.menu_yun.addAction(self.action_yunduanup2)self.action_yunduanup3 = QAction("分享-回放脚本任务", self)self.action_yunduanup3.triggered.connect(lambda: webbrowser.open("https://nas.qizhiqiang.com:5001/sharing/9eGN71WCG"))self.menu_yun.addAction(self.action_yunduanup3)self.action_yunduanup4 = QAction("分享-收集材料任务", self)self.action_yunduanup4.triggered.connect(lambda: webbrowser.open("https://nas.qizhiqiang.com:5001/sharing/vWDkt4QRB"))self.menu_yun.addAction(self.action_yunduanup4)self.action_yunduanup5 = QAction("分享-连招脚本任务", self)self.action_yunduanup5.triggered.connect(lambda: webbrowser.open("https://nas.qizhiqiang.com:5001/sharing/DVa5G18rL"))self.menu_yun.addAction(self.action_yunduanup5)self.action_yunduanup6 = QAction("分享-其它资源分享", self)self.action_yunduanup6.triggered.connect(lambda: webbrowser.open("https://nas.qizhiqiang.com:5001/sharing/3ucsnfSr5"))self.menu_yun.addAction(self.action_yunduanup6)# 创建一个顶级菜单self.menu_tools = self.menu.addMenu("工具")# 创建一个动作self.action_stitchimg = QAction("合成全景大图", self)self.action_stitchimg.triggered.connect(self.hotkey_stitchimg)self.menu_tools.addAction(self.action_stitchimg)# 创建一个顶级菜单self.menu_setting = self.menu.addMenu("设置")# 创建一个动作self.action_runstartwith = QAction("启动改为从这开始", self)self.action_runstartwith.setCheckable(True)self.action_runstartwith.setChecked(False)self.action_runstartwith.triggered.connect(self.hotkey_runstartwith)if state.ON_STARTWITH == 0:self.action_runstartwith.setChecked(False)else:self.action_runstartwith.setChecked(True)self.menu_setting.addAction(self.action_runstartwith)# 创建一个动作self.action_nextpack = QAction("是否自动继续下一个任务包", self)self.action_nextpack.setCheckable(True)self.action_nextpack.setChecked(False)self.action_nextpack.triggered.connect(self.hotkey_nextpack)if state.ON_NEXTPACK == 0:self.action_nextpack.setChecked(False)else:self.action_nextpack.setChecked(True)self.menu_setting.addAction(self.action_nextpack)# 创建一个动作self.action_jixing = QAction("是否任务完成后领取纪行奖励", self)self.action_jixing.triggered.connect(self.hotkey_jixing)self.action_jixing.setCheckable(True)if state.ON_JIXING == 0:self.action_jixing.setChecked(False)else:self.action_jixing.setChecked(True)self.menu_setting.addAction(self.action_jixing)# 创建一个动作self.action_shutdown = QAction("是否任务完成后关机", self)self.action_shutdown.triggered.connect(self.hotkey_shutdown)self.action_shutdown.setCheckable(True)if state.ON_SHUTDOWN == 0:self.action_shutdown.setChecked(False)else:self.action_shutdown.setChecked(True)self.menu_setting.addAction(self.action_shutdown)self.action_lianzhaobujiance = QAction("是否强制把连招搓完", self)self.action_lianzhaobujiance.triggered.connect(self.hotkey_lianzhaobujiance)self.action_lianzhaobujiance.setCheckable(True)if state.ON_LIANZHAOBUJIANCE == 0:self.action_lianzhaobujiance.setChecked(False)else:self.action_lianzhaobujiance.setChecked(True)self.menu_setting.addAction(self.action_lianzhaobujiance)# 创建一个动作self.action_weights = QAction(f"设置AI模型 当前: {state.WEIGHTS.split('/')[-1].split('.')[0]}", self)self.action_weights.triggered.connect(self.hotkey_weights)self.menu_setting.addAction(self.action_weights)# 创建一个动作self.action_timeout = QAction(f"设置打怪超时 阈值:{state.TIMEOUT_DAGUAI}秒", self)self.action_timeout.triggered.connect(self.hotkey_timeout)self.menu_setting.addAction(self.action_timeout)# 创建一个顶级菜单self.menu_help = self.menu.addMenu("帮助")# 创建一个动作self.action_about = QAction("关于", self)self.action_about.triggered.connect(lambda: QMessageBox.information(self, "作者", "python懒人智能 仅供技术研究!请勿用于非法用途否则后果自负!"))self.menu_help.addAction(self.action_about)# 创建一个动作self.action_kaiyuan = QAction("开源地址", self)self.action_kaiyuan.triggered.connect(lambda: webbrowser.open("https://gitee.com/LanRenZhiNeng/lanren-genshin-impact-ai"))self.menu_help.addAction(self.action_kaiyuan)# 创建一个动作self.action_zanzhu = QAction("赞助入群", self)self.action_zanzhu.triggered.connect(lambda: webbrowser.open("http://w.kami.vip/s/FSUtd45z"))self.menu_help.addAction(self.action_zanzhu)# 创建一个动作self.action_jiaocheng = QAction("教程合集", self)self.action_jiaocheng.triggered.connect(lambda: webbrowser.open("https://www.bilibili.com/video/BV1aS421w7i1"))self.menu_help.addAction(self.action_jiaocheng)# 创建右键弹出菜单menu = QMenu(self)menu.addAction(self.action_selecttaskdir)# 将菜单关联到工具栏上self.toolBar.setContextMenuPolicy(Qt.CustomContextMenu)self.toolBar.customContextMenuRequested.connect(lambda pos: menu.exec_(self.toolBar.mapToGlobal(pos)))def next_pack(self):self.show_tool_item(state.PATH_TASK)self.hotkey_runall()def add_tool_item(self, dir_):action_item = QWidgetAction(self)dir_ = dir_.replace("/", "\\")if dir_[-1] == "\\":dir_ = dir_[:-1]bt_item = QPushButton(dir_.split("\\")[-1].strip())bt_item.setMaximumWidth(int(80 * ratio))try:with open(dir_ + "/" + "使用说明.txt", "r", encoding="utf-8") as f:txt = f.read()except:try:with open(dir_ + "/" + "使用说明.txt", "r", encoding="utf-8") as f:txt = f.read()except:txt = "无  \n(可以在任务包文件夹下创建一个 使用说明.txt 文件 来添加说明)"bt_item.setToolTip(dir_ + "\n使用说明:" + txt + "\n")bt_item.setStyleSheet("border: none; padding: 3px;")bt_item.clicked.connect(functools.partial(self.show_tool_item, dir_))action_item.setDefaultWidget(bt_item)self.toolBar.addAction(action_item)menu = QMenu(self)action_menu_down = QAction('顺序 ↓', self)action_menu_down.triggered.connect(functools.partial(self.down_tool_item, len(self.toolBar.actions())))menu.addAction(action_menu_down)action_menu_up = QAction('顺序 ↑', self)action_menu_up.triggered.connect(functools.partial(self.up_tool_item, len(self.toolBar.actions())))menu.addAction(action_menu_up)action_menu_del = QAction('删除任务包', self)action_menu_del.triggered.connect(functools.partial(self.del_tool_item, action_item, bt_item, dir_))menu.addAction(action_menu_del)# 将菜单关联到工具栏上bt_item.setContextMenuPolicy(Qt.CustomContextMenu)bt_item.customContextMenuRequested.connect(lambda pos: menu.exec_(bt_item.mapToGlobal(pos)))self.change_tool_show_style(dir_)def show_tool_item(self, dir_):self.save()state.PATH_TASK = dir_self.save_ini_seting()self.update_tasks()self.change_tool_show_style(dir_)logger.info(f"成功设置{state.PATH_TASK}为当前任务文件夹")def del_tool_item(self, action_item, bt_item, dir_):self.toolBar.removeAction(action_item)if state.PATH_TASK.replace("/", "\\") == dir_:self.datas = []self.row = 0self.column = -1# 清空当前布局for i in reversed(range(self.g_box.count())):self.g_box.itemAt(i).widget().setParent(None)del bt_item, action_item  # 删除动作对象和bt对象txt_ = ""packs = state.PACKS_TASK.split("#@@#")if len(packs) >= 1:for pack in packs:if os.path.realpath(dir_) != os.path.realpath(pack) and pack != "":txt_ = txt_ + pack + "#@@#"state.PACKS_TASK = txt_logger.info(f"成功移除{dir_}任务包")self.sg.mysig_tishi.emit(f"成功移除{dir_}任务包")def down_tool_item(self, idex):task_list = state.PACKS_TASK.split("#@@#")if idex < len(task_list) - 1:# 将指定索引位置的成员与其前一个成员交换位置task_list[idex], task_list[idex + 1] = task_list[idex + 1], task_list[idex]state.PACKS_TASK = ""for item in task_list:if item != "":state.PACKS_TASK += "#@@#" + itemself.load_task_packs()def up_tool_item(self, idex):task_list = state.PACKS_TASK.split("#@@#")if idex > 0:# 将指定索引位置的成员与其后一个成员交换位置task_list[idex], task_list[idex - 1] = task_list[idex - 1], task_list[idex]state.PACKS_TASK = ""for item in task_list:if item != "":state.PACKS_TASK += "#@@#" + itemself.load_task_packs()def change_tool_show_style(self, dir_):# 获取工具栏上的所有动作actions_list = self.toolBar.actions()# 遍历处理每个动作for action in actions_list:# 在这里对每个动作进行处理bt_item = action.defaultWidget()if dir_ == bt_item.toolTip().replace("/", "\\").split("\n")[0]:bt_item.setStyleSheet("border-width: 1px; padding: 3px;")else:bt_item.setStyleSheet("border: none; padding: 3px;")def get_next_task(self):# 获取工具栏上的所有动作actions_list = self.toolBar.actions()length = len(actions_list)if length <= 0:return None# 遍历处理每个动作idex = 0for i, action in enumerate(actions_list):# 在这里对每个动作进行处理bt_item = action.defaultWidget()if state.PATH_TASK == bt_item.toolTip().replace("/", "\\").split("\n")[0]:idex = ibreak# 如果if idex < length - 1:bt_item = actions_list[idex + 1].defaultWidget()return bt_item.toolTip().replace("/", "\\").split("\n")[0]else:return Nonedef set_tishi(self, txt):self.statusbar.showMessage(txt)if state.开关_是否展预测结果:self.fromshow.setWindowTitle(txt)def show_xunlu(self):if state.开关_是否展预测结果:if type(state.图片_找图) == bool:return# 加载大图big_img_bk = state.图片_找图# 将OpenCV图像转换为Qt中的QImageheight, width, channel = big_img_bk.shapebytesPerLine = 3 * widthqImg = QImage(big_img_bk.data, width, height, bytesPerLine, QImage.Format_BGR888)pixmap = QPixmap.fromImage(qImg)self.fromshow.lb_xunlu.setPixmap(pixmap)# 设置宽度固定,高度自适应self.fromshow.window_width = int(self.fromshow.window_height * pixmap.width() / pixmap.height())self.fromshow.lb_xunlu.setFixedHeight(self.fromshow.window_height)self.fromshow.lb_xunlu.setFixedWidth(self.fromshow.window_width)self.fromshow.lb_xunlu.setScaledContents(True)def show_yolov(self):if state.开关_是否展预测结果:if type(state.图片_YOLOV) == bool:returnimg1 = QImage(state.图片_YOLOV.data, state.图片_YOLOV.shape[1], state.图片_YOLOV.shape[0],QImage.Format_BGR888)pixmap1 = QPixmap.fromImage(img1)if self.fromshow.width() >= self.fromshow.lb_yolov.width() + self.fromshow.lb_xunlu.width():self.fromshow.lb_yolov.move(self.fromshow.lb_xunlu.width(), 0)else:self.fromshow.lb_yolov.move(0, self.fromshow.lb_xunlu.height())self.fromshow.lb_yolov.setPixmap(pixmap1)def dingwei(self, idex):try:# self.datas[idex]["f_item"].is_zd = False# self.datas[idex]["f_item"].mousePressEvent(None)self.v_scrollbar.setValue(self.datas[idex]["f_item"].y())except Exception as err:print("dingwei", err)passdef set_mouse_through(self, bool):set_mouse_through(int(self.winId()), bool)if bool:self.setWindowOpacity(0.9)else:self.setWindowOpacity(1)def show_shutdown_dig(self):self.dialog = ShutdownConfirmationDialog(self)self.dialog.show()def set_ui(self):# 设置主题样式为 Flatwhite# 创建 QtitanRibbon 实例from qt_material import apply_stylesheetapply_stylesheet(app, theme='dark_pink.xml')self.setStyleSheet("""QScrollBar::handle:horizontal {background-color: #A50F2C;  /* 设置滑块颜色 */}QScrollBar::handle:horizontal:hover{background-color: #FF1744;  /* 设置滑块颜色 */} QPushButton:hover{background-color: #DFC472;  /* 设置颜色 */}QPlainTextEdit{padding: 0px;margin: 0px;}QPushButton{padding: 0px;margin: 1px;}""" + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))def tanChu_img(self, imgpath):'''弹出图片:param imgpath::return:'''# ----------------------try:return f'''<img src='{imgpath}' > '''except Exception as err:return str(err)def add_task(self, dir_, config):'''添加任务:return:'''# 根据导入的文件# 获取主窗口的宽度width = self.centralWidget().width()# 计算每行可以容纳的组件数量num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1self.column += 1if self.column == num_per_row:self.column = 0self.row += 1# 加载ini配置文件f_item = FrameItem()f_item.setObjectName("frame_cont")f_item.raise_()f_item.setStyleSheet("""#frame_cont:hover {border: 1px solid red;}#frame_cont {background-color: rgba(0, 0, 0, 0);}""")d = {}dir_ = dir_.replace("/", "\\")if dir_[-1] == "\\":dir_ = dir_[:-1]d["type"] = "1"try:config.set('seting', 'name', dir_.split("\\")[-1].strip())except:# 添加一个名为 'seting' 的配置节config.add_section('seting')config.set('seting', 'name', dir_.split("\\")[-1].strip())d["name"] = config.get('seting', 'name', fallback=dir_.split("\\")[-1]).strip()d["map"] = config.get('seting', 'map', fallback='')d["lujing"] = config.get('seting', 'lujing', fallback='')d["chuansong"] = config.get('seting', 'chuansong', fallback='')d["chuansongmoban"] = config.get('seting', 'chuansongmoban', fallback='')d["maodianmoban"] = config.get('seting', 'maodianmoban', fallback='')d["cb_is_checked"] = config.get('seting', 'cb_is_checked', fallback='True')d["cbb_address"] = config.get('seting', 'cbb_address', fallback='手动录制')d["cb_wakuang"] = config.get('seting', 'cb_wakuang', fallback='False')d["cb_caiji"] = config.get('seting', 'cb_caiji', fallback='False')d["cb_daguai"] = config.get('seting', 'cb_daguai', fallback='True')f_item.bt_map.setProperty("OK_map", d["map"] != "")f_item.bt_lujing.setProperty("OK_lujing", d["lujing"] != "")f_item.bt_chuansong.setProperty("OK_chuansong", d["chuansong"] != "")f_item.bt_moban.setProperty("OK_chuansongmoban", d["chuansongmoban"] != "")f_item.bt_moban_maodian.setProperty("OK_maodianmoban", d["maodianmoban"] != "")f_item.bt_map.setObjectName("bt_map")f_item.bt_lujing.setObjectName("bt_lujing")f_item.bt_chuansong.setObjectName("bt_chuansong")f_item.bt_moban.setObjectName("bt_moban")f_item.bt_moban_maodian.setObjectName("bt_moban_maodian")f_item.led_name.setText(d["name"])f_item.bt_map.setStyleSheet("""#bt_map[OK_map="true"] {color: rgb(237,182,43);  /* 边框颜色为灰色 */border-color: rgb(237,182,43);  /* 边框颜色为灰色 */}""")f_item.bt_lujing.setStyleSheet("""#bt_lujing[OK_lujing="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")f_item.bt_chuansong.setStyleSheet("""#bt_chuansong[OK_chuansong="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")f_item.bt_moban.setStyleSheet("""#bt_moban[OK_chuansongmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")f_item.bt_moban_maodian.setStyleSheet("""#bt_moban_maodian[OK_maodianmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")if d["cb_is_checked"] == "True":f_item.cb_is_checked.setChecked(True)else:f_item.cb_is_checked.setChecked(False)if d["cb_wakuang"] == "True":f_item.cb_wakuang.setChecked(True)else:f_item.cb_wakuang.setChecked(False)if d["cb_caiji"] == "True":f_item.cb_caiji.setChecked(True)else:f_item.cb_caiji.setChecked(False)if d["cb_daguai"] == "True":f_item.cb_daguai.setChecked(True)else:f_item.cb_daguai.setChecked(False)idex = len(self.datas)# f_item.led_name.editingFinished.connect(self.save)f_item.bt_map.clicked.connect(functools.partial(self.clickd_bt_map, idex))f_item.bt_lujing.clicked.connect(functools.partial(self.clickd_bt_lujing, idex))f_item.bt_chuansong.clicked.connect(functools.partial(self.clickd_bt_chuansong, idex))f_item.bt_moban.clicked.connect(functools.partial(self.clickd_bt_moban, idex))f_item.bt_moban_maodian.clicked.connect(functools.partial(self.clickd_bt_moban_maodian, idex))f_item.bt_start.clicked.connect(functools.partial(self.clickd_bt_start, idex))f_item.bt_del.clicked.connect(functools.partial(self.clickd_bt_del, idex))f_item.bt_map.setVisible(False)f_item.bt_lujing.setVisible(False)f_item.bt_chuansong.setVisible(False)f_item.bt_moban.setVisible(False)f_item.bt_moban_maodian.setVisible(False)f_item.bt_start.setVisible(False)f_item.bt_del.setVisible(False)f_item.cb_wakuang.setVisible(False)f_item.cb_caiji.setVisible(False)f_item.cb_daguai.setVisible(False)f_item.bt_map.setToolTip(self.tanChu_img(dir_ + "/" + d["map"]))f_item.bt_lujing.setToolTip(self.tanChu_img(dir_ + "/" + d["lujing"]))f_item.bt_moban.setToolTip(self.tanChu_img(dir_ + "/" + d["chuansongmoban"]))f_item.bt_moban_maodian.setToolTip(self.tanChu_img(dir_ + "/" + d["maodianmoban"]))d["f_item"] = f_itemself.datas.append(d)self.g_box.addWidget(f_item, self.row, self.column)def add_taskpy(self, dir_, config):'''添加任务:return:'''# 根据导入的文件# 获取主窗口的宽度width = self.centralWidget().width()# 计算每行可以容纳的组件数量num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1self.column += 1if self.column == num_per_row:self.column = 0self.row += 1# 加载ini配置文件f_item = FramePY()f_item.setObjectName("frame_cont")f_item.raise_()f_item.setStyleSheet("""#frame_cont:hover {border: 1px solid red;}#frame_cont {background-color: rgba(0, 0, 0, 0);}""")d = {}dir_ = dir_.replace("/", "\\")if dir_[-1] == "\\":dir_ = dir_[:-1]d["type"] = "6"try:config.set('seting', 'name', dir_.split("\\")[-1].strip())except:# 添加一个名为 'seting' 的配置节config.add_section('seting')config.set('seting', 'name', dir_.split("\\")[-1].strip())d["name"] = config.get('seting', 'name', fallback=dir_.split("\\")[-1]).strip()d["arg"] = config.get('seting', 'arg', fallback=dir_ + "\\参数.ini")d["opendir"] = config.get('seting', 'opendir', fallback=dir_)d["chuansong"] = config.get('seting', 'chuansong', fallback='')d["chuansongmoban"] = config.get('seting', 'chuansongmoban', fallback='')d["maodianmoban"] = config.get('seting', 'maodianmoban', fallback='')d["cb_is_checked"] = config.get('seting', 'cb_is_checked', fallback='True')d["cbb_address"] = config.get('seting', 'cbb_address', fallback='手动录制')d["cb_wakuang"] = config.get('seting', 'cb_wakuang', fallback='False')d["cb_caiji"] = config.get('seting', 'cb_caiji', fallback='False')d["cb_daguai"] = config.get('seting', 'cb_daguai', fallback='True')f_item.bt_chuansong.setProperty("OK_chuansong", d["chuansong"] != "")f_item.bt_moban.setProperty("OK_chuansongmoban", d["chuansongmoban"] != "")f_item.bt_moban_maodian.setProperty("OK_maodianmoban", d["maodianmoban"] != "")f_item.bt_chuansong.setObjectName("bt_chuansong")f_item.bt_moban.setObjectName("bt_moban")f_item.bt_moban_maodian.setObjectName("bt_moban_maodian")f_item.led_name.setText(d["name"])f_item.bt_arg.setStyleSheet("""color: rgb(237,182,43);  border-color: rgb(237,182,43); """)f_item.bt_opendir.setStyleSheet("""color: rgb(237,182,43);  border-color: rgb(237,182,43); """)f_item.bt_chuansong.setStyleSheet("""#bt_chuansong[OK_chuansong="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")f_item.bt_moban.setStyleSheet("""#bt_moban[OK_chuansongmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")f_item.bt_moban_maodian.setStyleSheet("""#bt_moban_maodian[OK_maodianmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")if d["cb_is_checked"] == "True":f_item.cb_is_checked.setChecked(True)else:f_item.cb_is_checked.setChecked(False)idex = len(self.datas)# f_item.led_name.editingFinished.connect(self.save)f_item.bt_arg.clicked.connect(lambda: subprocess.Popen(['notepad.exe', d["arg"]]))f_item.bt_opendir.clicked.connect(lambda: subprocess.Popen(['explorer', d["opendir"]]))f_item.bt_chuansong.clicked.connect(functools.partial(self.clickd_bt_chuansong, idex))f_item.bt_moban.clicked.connect(functools.partial(self.clickd_bt_moban, idex))f_item.bt_moban_maodian.clicked.connect(functools.partial(self.clickd_bt_moban_maodian, idex))f_item.bt_start.clicked.connect(functools.partial(self.clickd_bt_start, idex))f_item.bt_del.clicked.connect(functools.partial(self.clickd_bt_del, idex))f_item.bt_arg.setVisible(False)f_item.bt_opendir.setVisible(False)f_item.bt_chuansong.setVisible(False)f_item.bt_moban.setVisible(False)f_item.bt_moban_maodian.setVisible(False)f_item.bt_start.setVisible(False)f_item.bt_del.setVisible(False)f_item.bt_moban.setToolTip(self.tanChu_img(dir_ + "/" + d["chuansongmoban"]))f_item.bt_moban_maodian.setToolTip(self.tanChu_img(dir_ + "/" + d["maodianmoban"]))d["f_item"] = f_itemself.datas.append(d)self.g_box.addWidget(f_item, self.row, self.column)# 将py模板文件复制一份dir_py = os.path.join(d['opendir'], 'main.py')dir_ini = os.path.join(d['opendir'], '参数.ini')try:if not os.path.exists(dir_py):shutil.copy('datas/pymode.py', dir_py)if not os.path.exists(dir_ini):shutil.copy('datas/pymode.ini', dir_ini)except:passdef add_taskfuben(self, dir_, config):'''添加任务:return:'''# 根据导入的文件# 获取主窗口的宽度width = self.centralWidget().width()# 计算每行可以容纳的组件数量num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1self.column += 1if self.column == num_per_row:self.column = 0self.row += 1f_item = FrameItemFuBen()f_item.setObjectName("frame_cont")f_item.raise_()f_item.setStyleSheet("""#frame_cont:hover {border: 1px solid red;}#frame_cont {background-color: rgba(0, 0, 0, 0);}""")d = {}d["type"] = "2"dir_ = dir_.replace("/", "\\")if dir_[-1] == "\\":dir_ = dir_[:-1]try:config.set('seting', 'name', dir_.split("\\")[-1].strip())except:# 添加一个名为 'seting' 的配置节config.add_section('seting')config.set('seting', 'name', dir_.split("\\")[-1].strip())d["name"] = config.get('seting', 'name', fallback=dir_.split("\\")[-1]).strip()d["cb_isfanxiang"] = config.get('seting', 'cb_isfanxiang', fallback='False')d["led_cishu"] = config.get('seting', 'led_cishu', fallback='99')d["chuansong"] = config.get('seting', 'chuansong', fallback='')d["cbb_address"] = config.get('seting', 'cbb_address', fallback='手动录制')d["chuansongmoban"] = config.get('seting', 'chuansongmoban', fallback='')d["maodianmoban"] = config.get('seting', 'maodianmoban', fallback='')d["cb_is_checked"] = config.get('seting', 'cb_is_checked', fallback='True')f_item.bt_chuansong.setProperty("OK_chuansong", d["chuansong"] != "")f_item.bt_moban.setProperty("OK_chuansongmoban", d["chuansongmoban"] != "")f_item.bt_moban_maodian.setProperty("OK_maodianmoban", d["maodianmoban"] != "")f_item.bt_chuansong.setObjectName("bt_chuansong")f_item.bt_moban.setObjectName("bt_moban")f_item.bt_moban_maodian.setObjectName("bt_moban_maodian")f_item.led_name.setText(d["name"])f_item.led_cishu.setText(d["led_cishu"])f_item.bt_chuansong.setStyleSheet("""#bt_chuansong[OK_chuansong="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")f_item.bt_moban.setStyleSheet("""#bt_moban[OK_chuansongmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")f_item.bt_moban_maodian.setStyleSheet("""#bt_moban_maodian[OK_maodianmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")if d["cb_is_checked"] == "True":f_item.cb_is_checked.setChecked(True)else:f_item.cb_is_checked.setChecked(False)if d["cb_isfanxiang"] == "True":f_item.cb_isfanxiang.setChecked(True)else:f_item.cb_isfanxiang.setChecked(False)idex = len(self.datas)# f_item.led_name.editingFinished .connect(self.save)f_item.bt_chuansong.clicked.connect(functools.partial(self.clickd_bt_chuansong, idex))f_item.bt_moban.clicked.connect(functools.partial(self.clickd_bt_moban, idex))f_item.bt_moban_maodian.clicked.connect(functools.partial(self.clickd_bt_moban_maodian, idex))f_item.bt_start.clicked.connect(functools.partial(self.clickd_bt_start, idex))f_item.bt_del.clicked.connect(functools.partial(self.clickd_bt_del, idex))f_item.bt_chuansong.setVisible(False)f_item.bt_moban.setVisible(False)f_item.bt_moban_maodian.setVisible(False)f_item.bt_start.setVisible(False)f_item.bt_del.setVisible(False)f_item.cb_isfanxiang.setVisible(False)f_item.led_cishu.setVisible(False)f_item.label.setVisible(False)f_item.bt_moban.setToolTip(self.tanChu_img(dir_ + "/" + d["chuansongmoban"]))f_item.bt_moban_maodian.setToolTip(self.tanChu_img(dir_ + "/" + d["maodianmoban"]))d["f_item"] = f_itemself.datas.append(d)self.g_box.addWidget(f_item, self.row, self.column)def add_taskjiaoben(self, dir_, config):'''添加脚本任务:return:'''# 根据导入的文件# 获取主窗口的宽度width = self.centralWidget().width()# 计算每行可以容纳的组件数量num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1self.column += 1if self.column == num_per_row:self.column = 0self.row += 1# 加载ini配置文件f_item = FrameItemJiaoBen()f_item.setObjectName("frame_cont")f_item.raise_()f_item.setStyleSheet("""#frame_cont:hover {border: 1px solid red;}#frame_cont {background-color: rgba(0, 0, 0, 0);}""")d = {}d["type"] = "3"dir_ = dir_.replace("/", "\\")if dir_[-1] == "\\":dir_ = dir_[:-1]try:config.set('seting', 'name', dir_.split("\\")[-1].strip())except:# 添加一个名为 'seting' 的配置节config.add_section('seting')config.set('seting', 'name', dir_.split("\\")[-1].strip())d["name"] = config.get('seting', 'name', fallback=dir_.split("\\")[-1]).strip()d["cb_auto_f"] = config.get('seting', 'cb_auto_f', fallback='True')d["chuansong"] = config.get('seting', 'chuansong', fallback='')d["cbb_address"] = config.get('seting', 'cbb_address', fallback='手动录制')d["jiaoben"] = config.get('seting', 'jiaoben', fallback='')d["chuansongmoban"] = config.get('seting', 'chuansongmoban', fallback='')d["maodianmoban"] = config.get('seting', 'maodianmoban', fallback='')d["cb_is_checked"] = config.get('seting', 'cb_is_checked', fallback='True')f_item.bt_chuansong.setProperty("OK_chuansong", d["chuansong"] != "")f_item.bt_jiaoben.setProperty("OK_jiaoben", d["jiaoben"] != "")f_item.bt_moban.setProperty("OK_chuansongmoban", d["chuansongmoban"] != "")f_item.bt_moban_maodian.setProperty("OK_maodianmoban", d["maodianmoban"] != "")f_item.bt_chuansong.setObjectName("bt_chuansong")f_item.bt_moban.setObjectName("bt_moban")f_item.bt_moban_maodian.setObjectName("bt_moban_maodian")f_item.led_name.setText(d["name"])f_item.bt_jiaoben.setStyleSheet("""#bt_jiaoben[OK_jiaoben="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")f_item.bt_chuansong.setStyleSheet("""#bt_chuansong[OK_chuansong="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")f_item.bt_moban.setStyleSheet("""#bt_moban[OK_chuansongmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")f_item.bt_moban_maodian.setStyleSheet("""#bt_moban_maodian[OK_maodianmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")if d["cb_is_checked"] == "True":f_item.cb_is_checked.setChecked(True)else:f_item.cb_is_checked.setChecked(False)if d["cb_auto_f"] == "True":f_item.cb_auto_f.setChecked(True)else:f_item.cb_auto_f.setChecked(False)idex = len(self.datas)f_item.bt_jiaoben.clicked.connect(functools.partial(self.clickd_bt_jiaoben, idex))f_item.bt_chuansong.clicked.connect(functools.partial(self.clickd_bt_chuansong, idex))f_item.bt_moban.clicked.connect(functools.partial(self.clickd_bt_moban, idex))f_item.bt_moban_maodian.clicked.connect(functools.partial(self.clickd_bt_moban_maodian, idex))f_item.bt_start.clicked.connect(functools.partial(self.clickd_bt_start, idex))f_item.bt_del.clicked.connect(functools.partial(self.clickd_bt_del, idex))d["f_item"] = f_itemf_item.bt_start.setVisible(False)f_item.bt_jiaoben.setVisible(False)f_item.bt_chuansong.setVisible(False)f_item.bt_moban_maodian.setVisible(False)f_item.bt_moban.setVisible(False)f_item.bt_start.setVisible(False)f_item.bt_del.setVisible(False)f_item.cb_auto_f.setVisible(False)f_item.bt_moban.setToolTip(self.tanChu_img(dir_ + "/" + d["chuansongmoban"]))f_item.bt_moban_maodian.setToolTip(self.tanChu_img(dir_ + "/" + d["maodianmoban"]))self.datas.append(d)self.g_box.addWidget(f_item, self.row, self.column)def add_xuanjue(self, dir_, config):'''添加脚本任务:return:'''# 根据导入的文件# 获取主窗口的宽度width = self.centralWidget().width()# 计算每行可以容纳的组件数量num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1if num_per_row < 1:num_per_row = 1self.column += 1if self.column == num_per_row:self.column = 0self.row += 1# 加载ini配置文件f_item = FrameItemXuanJue()f_item.setObjectName("frame_cont")f_item.raise_()f_item.setStyleSheet("""#frame_cont:hover {border: 1px solid red;}#frame_cont {background-color: rgba(0, 0, 0, 0);}""")d = {}d["type"] = "4"dir_ = dir_.replace("/", "\\")if dir_[-1] == "\\":dir_ = dir_[:-1]try:config.set('seting', 'name', dir_.split("\\")[-1].strip())except:# 添加一个名为 'seting' 的配置节config.add_section('seting')config.set('seting', 'name', dir_.split("\\")[-1].strip())d["name"] = config.get('seting', 'name', fallback=dir_.split("\\")[-1]).strip()d["chuansong"] = ''d["cb_is_checked"] = config.get('seting', 'cb_is_checked', fallback='True')d["cbb_1"] = config.get('seting', 'cbb_1', fallback='早柚')d["cbb_2"] = config.get('seting', 'cbb_2', fallback='班尼特')d["cbb_3"] = config.get('seting', 'cbb_3', fallback='钟离')d["cbb_4"] = config.get('seting', 'cbb_4', fallback='香菱')d["led_main"] = config.get('seting', 'led_main', fallback='4')if d["cb_is_checked"] == "True":f_item.cb_is_checked.setChecked(True)else:f_item.cb_is_checked.setChecked(False)idex = len(self.datas)f_item.bt_start.clicked.connect(functools.partial(self.clickd_bt_start, idex))f_item.bt_del.clicked.connect(functools.partial(self.clickd_bt_del, idex))f_item.led_main.setText(d["led_main"])f_item.led_name.setText(d["name"])self.set_cbb_items(f_item.cbb_1)self.set_cbb_items(f_item.cbb_2)self.set_cbb_items(f_item.cbb_3)self.set_cbb_items(f_item.cbb_4)self.set_cbb_item(f_item.cbb_1, d["cbb_1"])self.set_cbb_item(f_item.cbb_2, d["cbb_2"])self.set_cbb_item(f_item.cbb_3, d["cbb_3"])self.set_cbb_item(f_item.cbb_4, d["cbb_4"])f_item.cbb_1.setVisible(False)f_item.cbb_2.setVisible(False)f_item.cbb_3.setVisible(False)f_item.cbb_4.setVisible(False)f_item.lb_zhanchang.setVisible(False)f_item.led_main.setVisible(False)f_item.bt_del.setVisible(False)f_item.bt_start.setVisible(False)d["f_item"] = f_itemself.datas.append(d)self.g_box.addWidget(f_item, self.row, self.column)def add_xuanlianzhao(self, dir_, config):'''添加脚本任务:return:'''# 根据导入的文件# 获取主窗口的宽度width = self.centralWidget().width()# 计算每行可以容纳的组件数量num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1if num_per_row < 1:num_per_row = 1self.column += 1if self.column == num_per_row:self.column = 0self.row += 1# 加载ini配置文件f_item = FrameItemLianZhao()f_item.setObjectName("frame_cont")f_item.raise_()f_item.setStyleSheet("""#frame_cont:hover {border: 1px solid red;}#frame_cont {background-color: rgba(0, 0, 0, 0);}""")d = {}d["type"] = "5"dir_ = dir_.replace("/", "\\")if dir_[-1] == "\\":dir_ = dir_[:-1]try:config.set('seting', 'name', dir_.split("\\")[-1].strip())except:# 添加一个名为 'seting' 的配置节config.add_section('seting')config.set('seting', 'name', dir_.split("\\")[-1].strip())d["name"] = config.get('seting', 'name', fallback=dir_.split("\\")[-1]).strip()d["chuansong"] = ''d["cb_is_checked"] = config.get('seting', 'cb_is_checked', fallback='True')d["cbb_lianzhao"] = config.get('seting', 'cbb_lianzhao', fallback='')if d["cb_is_checked"] == "True":f_item.cb_is_checked.setChecked(True)else:f_item.cb_is_checked.setChecked(False)idex = len(self.datas)f_item.bt_start.clicked.connect(functools.partial(self.clickd_bt_start, idex))f_item.bt_del.clicked.connect(functools.partial(self.clickd_bt_del, idex))folder_path = state.PATH_JIAOBENf_item.led_name.setText(d["name"])# 遍历文件夹及其子文件夹中的所有文件for root, dirs, files in os.walk(folder_path):for file in files:# 检查文件扩展名是否为.pngif file.endswith('.txt'):# 打印PNG文件的完整路径file_name = os.path.splitext(file)[0]f_item.cbb_lianzhao.addItem(file_name)f_item.cbb_lianzhao.setCurrentText(d["cbb_lianzhao"])f_item.bt_start.setVisible(False)f_item.cbb_lianzhao.setVisible(False)f_item.bt_del.setVisible(False)d["f_item"] = f_itemself.datas.append(d)self.g_box.addWidget(f_item, self.row, self.column)def returnPressed_name(self, idex):try:if self.datas[idex]["f_item"].led_name.text() == self.datas[idex]["name"]:returndir_ = os.path.join(state.PATH_TASK, self.datas[idex]["f_item"].led_name.text()).strip()if self.datas[idex]["name"] != "":dir_old = os.path.join(state.PATH_TASK, self.datas[idex]["name"])if not os.path.exists(dir_old):dir_old = Noneelse:dir_old = Noneif not os.path.exists(dir_):if dir_old != None:try:os.rename(dir_old, dir_)self.datas[idex]["name"] = self.datas[idex]["f_item"].led_name.text()logger.info(f'重命名成功{self.datas[idex]["name"]}')except:QMessageBox.information(self, "提示", "重命名失败!请检查是不是有特殊符号或者文件夹已经存在了")self.datas[idex]["f_item"].led_name.setText(self.datas[idex]["name"])else:try:os.makedirs(dir_)self.datas[idex]["name"] = self.datas[idex]["f_item"].led_name.text()logger.info(f'重命名成功{self.datas[idex]["name"]}')except:QMessageBox.information(self, "提示", "重命名失败!请检查是不是有特殊符号或者文件夹已经存在了")self.datas[idex]["f_item"].led_name.setText(self.datas[idex]["name"])except Exception as err:QMessageBox.information(self, "提示", "重命名失败!" + str(err))self.datas[idex]["f_item"].led_name.setText(self.datas[idex]["name"])def clickd_bt_map(self, idex):temp_path, ok = QFileDialog.getOpenFileName(self, "选择地图", "", "图片文件 (*.png)")if ok:dir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成# 将图片复制到指定目录path = dir_ + "/地图.png"shutil.copy(temp_path, path)self.datas[idex]["map"] = "地图.png"self.datas[idex]["f_item"].bt_map.setProperty("OK_map", True)self.datas[idex]["f_item"].bt_map.setStyleSheet("""#bt_map[OK_map="true"] {color: rgb(237,182,43);  /* 边框颜色为灰色 */border-color: rgb(237,182,43);  /* 边框颜色为灰色 */}""")logger.info(f"导入地图成功:{path}")self.save_ini(dir_, self.datas[idex])def clickd_bt_jiaoben(self, idex):# 弹出一个选择弹窗 选项为  录制还是文件中选择msgBox = QMessageBox(self)msgBox.setWindowTitle("请选择一个配置方式")  # 设置消息框标题msgBox.setIcon(QMessageBox.Information)msgBox.setText("技巧:尽量少用鼠标转动镜头\n可以用键盘方向键配合鼠标中键进行转向")msgBox.addButton("录制", QMessageBox.AcceptRole)msgBox.addButton("回放", QMessageBox.ApplyRole)msgBox.addButton("文件中选择", QMessageBox.RejectRole)result = msgBox.exec_()if result == QMessageBox.AcceptRole:logger.info("可以开始录制了,按F8开始/停止")self.sg.mysig_tishi.emit("可以开始录制了,按F8开始/停止")state.状态_是否禁止录制 = Falsestate.状态_是否开始录制 = Falsestate.录制_当前任务索引 = idexstate.录制_脚本文本 = ""state.录制_当前脚本名 = self.datas[idex]["name"]tangbaowss.send_msg("是否禁止录制#@@#假")tangbaowss.send_msg("是否开始录制#@@#假")tangbaowss.send_msg(f"全局脚本名#@@#{state.录制_当前脚本名}")hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄tangbaowss.send_msg(f"全局hwnd#@@#{hwnd}")self.timer_luzhi.start(200)elif result == QMessageBox.RejectRole:if state.状态_是否回放中 == True:returndir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])if not os.path.exists(dir_):os.makedirs(dir_)state.状态_是否回放中 = Truestate.状态_循环开关 = Truejiaoben = os.path.abspath(os.path.join(dir_, self.datas[idex]["jiaoben"]))message = f"解析脚本#@@#{jiaoben}"tangbaowss.send_msg(message)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄set_window_activate(hwnd)tangbaowss.send_msg("脚本执行#@@#1")self.timer_huifang.start(200)elif result == QMessageBox.Warning:# 弹出一个有分组框的窗口temp_path, ok = QFileDialog.getOpenFileName(self, "脚本", "", "脚本文件 (*.txt)")if ok:dir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成path = dir_ + "/脚本.txt"shutil.copy(temp_path, path)self.datas[idex]["jiaoben"] = "脚本.txt"self.datas[idex]["f_item"].bt_jiaoben.setProperty("OK_jiaoben", True)logger.info(f"导入脚本成功:{path}")self.sg.mysig_tishi.emit(f"导入脚本成功:{path}")self.datas[idex]["f_item"].bt_jiaoben.setStyleSheet("""#bt_jiaoben[OK_jiaoben="true"] {color: rgb(237,182,43);  border-color: rgb(237,182,43); }""")self.save_ini(dir_, self.datas[idex])def clickd_bt_chuansong(self, idex):dl_chuansong = DialogChuansong(self, idex)dl_chuansong.cbb_address.setCurrentText(self.datas[idex]['cbb_address'])dl_chuansong.exec_()def clickd_bt_moban(self, idex):temp_path, ok = QFileDialog.getOpenFileName(self, "传送模板图片", "", "图片文件 (*.png)")if ok:dir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成# 将图片复制到指定目录path = dir_ + "/传送模板.png"shutil.copy(temp_path, path)self.datas[idex]["chuansongmoban"] = "传送模板.png"self.datas[idex]["f_item"].bt_moban.setProperty("OK_chuansongmoban", True)self.datas[idex]["f_item"].bt_moban.setStyleSheet("""#bt_moban[OK_chuansongmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")self.save_ini(dir_, self.datas[idex])self.sg.mysig_tishi.emit(f"导入传送模板成功:{path}")logger.info(f"导入传送模板成功:{path}")def clickd_bt_moban_maodian(self, idex):temp_path, ok = QFileDialog.getOpenFileName(self, "锚点模板图片", "", "图片文件 (*.png)")if ok:dir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成# 将图片复制到指定目录path = dir_ + "/锚点模板.png"shutil.copy(temp_path, path)self.datas[idex]["maodianmoban"] = "锚点模板.png"self.datas[idex]["f_item"].bt_moban_maodian.setProperty("OK_maodianmoban", True)self.datas[idex]["f_item"].bt_moban_maodian.setStyleSheet("""#bt_moban_maodian[OK_maodianmoban="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")self.save_ini(dir_, self.datas[idex])logger.info(f"导入锚点模板成功:{path}")self.sg.mysig_tishi.emit(f"导入锚点模板成功:{path}")def clickd_bt_start(self, idex):global ysylhwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄if hwnd == 0:logger.info("错误:请先开游戏!")self.sg.mysig_tishi.emit("错误:请先开游戏!")returnleft, top, right, bottom = win32gui.GetClientRect(hwnd)width = right - leftheight = bottom - topif width != 1920 or height != 1080:logger.info("错误:游戏分辨率不对!请确保游戏分辨率是1920x1080  建议重新设置分辨率")self.sg.mysig_tishi.emit("错误:游戏分辨率不对!请确保游戏分辨率是1920x1080  建议重新设置分辨率")returnself.save()def run(idex):ret = Falseself.sg.mysig_mouse_through.emit(True)state.计次_传送重试次数 = 0state.状态_全局暂停 = Falseself.datas[idex]['f_item'].cb_is_checked.setChecked(True)for rt in range(self.run_times):if self.action_runstartwith.isChecked():logger.info(f"任务包:{state.PATH_TASK} {rt + 1}/{self.run_times}")while idex < len(self.datas):if state.状态_检测中:time.sleep(1)continueif self.datas[idex]['f_item'].cb_is_checked.isChecked():ret, arg = self.run(idex)if arg is None:arg = "0"if arg != "0":idex = self.arg_jisuan(arg, idex)if state.状态_循环开关 == False:breakif ret == False:if state.状态_需重新传送 == True:state.计次_传送重试次数 += 1if state.计次_传送重试次数 >= 5:state.计次_传送重试次数 = 0logger.info("传送重试次数过多,放弃该任务!")else:logger.info(f"传送重试{state.计次_传送重试次数}")time.sleep(2)continueelse:breakif self.action_runstartwith.isChecked() == False:breakstate.计次_传送重试次数 = 0idex += 1if self.action_runstartwith.isChecked() == False:breakif state.状态_循环开关 == False:breakidex = 0if state.状态_循环开关 != False:if self.action_runstartwith.isChecked():# 切下一个任务包 继续next_tas = self.get_next_task()if state.ON_NEXTPACK == 1 and next_tas != None:logger.info("切下一个任务包!")state.PATH_TASK = next_tasself.sg.mysig_mouse_through.emit(False)self.sg.mysig_next_pack.emit()returnif ret == True and state.ON_JIXING == 1:ysyl.run_jixing()if ret == True and state.ON_SHUTDOWN == 1:self.sg.mysig_shutdown.emit()self.sg.mysig_mouse_through.emit(False)state.状态_循环开关 = Falset = threading.Thread(target=run, args=(idex,))if state.python_var > 9:t.daemon = Trueelse:t.setDaemon(True)t.start()def arg_jisuan(self, arg, idex):# 解析 argprint(arg)if arg.startswith('+'):idex += int(arg[1:])  # 添加elif arg.startswith('-'):idex -= int(arg[1:])  # 移除return idexdef run(self, idex):global ysyl, ysamif not state.状态_YOLOV:logger.info("还在启动相关服务中..请稍等")return False, "0"dir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])txt = "执行:" + self.datas[idex]["name"] + "任务"logger.info(txt)self.sg.mysig_tishi.emit(txt)self.sg.mysig_dingwei.emit(idex)if not os.path.exists(dir_):logger.info("没有找到任务文件夹,请先设定任务")self.sg.mysig_tishi.emit("没有找到任务文件夹,请先设定任务")return False, "0"if state.状态_已经有寻路了:logger.info("请勿重复启动!已经有任务在运行了")self.sg.mysig_tishi.emit("请勿重复启动!已经有任务在运行了")# 弹出提示,不要重复开return False, "0"state.计数_没找到任何目标 = 0state.计数_没找到怪物 = 0state.状态_在爬墙 = Falsestate.状态_需重新传送 = Falsestate.状态_循环开关 = Truestate.状态_传送中 = Truehwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄message = f"全局hwnd#@@#{hwnd}"tangbaowss.send_msg(message)if self.datas[idex]["chuansong"] != "":  # 如果没有录传送,那就不传送了if ctypes.windll.user32.GetForegroundWindow() != hwnd:# 激活hwndhwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄set_window_activate(hwnd)time.sleep(0.1)# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)left, top, right, bottom = 1, 979, 120, 1074  # 替换成你实际的区域坐标rect = win32gui.GetWindowRect(hwnd)w_p, h_p = (rect[2] - rect[0]) - 1920, (rect[3] - rect[1]) - 1080p_left = rect[0] + w_pp_top = rect[1] + h_pdituchilun_img = cv2.imdecode(np.fromfile(file="./datas/地图齿轮.png", dtype=np.uint8),cv2.IMREAD_UNCHANGED)big_img = screenshot(hwnd, left, top, right, bottom, None)res = template_matching(big_img, dituchilun_img, mask=None)if res == []:kkk = ysyl.处理异常情况(hwnd, 0, 0, 1920, 1080, p_left, p_top)if kkk == 0:logger.info("在意外界面 超时!")time.sleep(3)state.状态_需重新传送 = Falsestate.状态_已经有寻路了 = Falsereturn False, "0"elif kkk == -1:logger.info("全军覆没了!")time.sleep(3)state.状态_需重新传送 = Truestate.状态_已经有寻路了 = Falsereturn False, "0"if self.datas[idex]['cbb_address'] != "手动录制":pyautogui.keyDown("M")time.sleep(0.2)pyautogui.keyUp("M")time.sleep(2)logger.info("按下M 打开地图")if self.datas[idex]['cbb_address'] != "手动录制":logger.info("正在自动选择区域...")if not self.autoSelectAddress(self.datas[idex]['cbb_address'], isrun=True):logger.info("选择区域失败在意外界面!")state.状态_需重新传送 = Falsestate.状态_已经有寻路了 = Falsereturn False, "0"# 运行传送脚本动作jiaoben = os.path.abspath(os.path.join(dir_, self.datas[idex]["chuansong"]))ret = ysyl.run_chuansongjiaoben(jiaoben, self.datas[idex]['cbb_address'])if ret == False:logger.info("执行传送脚本!失败")return False, "0"# 传送模板 点击chuansong_path = os.path.join(dir_, self.datas[idex]['chuansongmoban'])maodian_path = os.path.join(dir_, self.datas[idex]['maodianmoban'])ret = ysam.run_chuansong(chuansong_path, maodian_path)if ret == False:logger.info("识别传送点击!失败")return False, "0"else:logger.info("没发现传送脚本,不传送")state.状态_传送中 = Falsestate.计数_没找到任何目标 = 0state.计数_没找到怪物 = 0state.计数_连招次数 = 0state.状态_已经有寻路了 = Trueif self.datas[idex]["type"] == "2":return ysyl.run_fuben(int(self.datas[idex]['f_item'].led_cishu.text()),self.datas[idex]['f_item'].cb_isfanxiang.isChecked()), "0"elif self.datas[idex]["type"] == "3":return ysyl.run_jiaoben(os.path.abspath(os.path.join(dir_, self.datas[idex]["jiaoben"])),self.datas[idex]['f_item'].cb_auto_f.isChecked()), "0"elif self.datas[idex]["type"] == "4":names = [f"{state.PATH_JUESE}/{self.datas[idex]['f_item'].cbb_1.itemData(self.datas[idex]['f_item'].cbb_1.currentIndex())}.png",f"{state.PATH_JUESE}/{self.datas[idex]['f_item'].cbb_2.itemData(self.datas[idex]['f_item'].cbb_2.currentIndex())}.png",f"{state.PATH_JUESE}/{self.datas[idex]['f_item'].cbb_3.itemData(self.datas[idex]['f_item'].cbb_3.currentIndex())}.png",f"{state.PATH_JUESE}/{self.datas[idex]['f_item'].cbb_4.itemData(self.datas[idex]['f_item'].cbb_4.currentIndex())}.png"]return ysyl.run_huanjue(names, self.datas[idex]['f_item'].led_main.text()), "0"elif self.datas[idex]["type"] == "5":lianzhao_path = self.datas[idex]['f_item'].cbb_lianzhao.currentText() + ".txt"state.状态_需重新传送 = Falsestate.状态_已经有寻路了 = Falseif lianzhao_path != "":state.LIANZHAO = lianzhao_pathlogger.info(f"切换连招脚本: {lianzhao_path}  成功")return True, "0"else:return False, "0"elif self.datas[idex]["type"] == "6":try:with open(f"{self.datas[idex]['opendir']}/main.py", "r",encoding="utf-8") as f:a = "lanrenpy = LanRenPY(name,arg,opendir,yolov)\nresult['py_ret'],result['next']=lanrenpy.run()"pycode = f.read() + aresult = {'py_ret': 0, 'next': "0"}# 将需要传递的变量组织成一个字典globals_dict = {'name': self.datas[idex]["name"],'arg': self.datas[idex]["arg"],'opendir': self.datas[idex]["opendir"],'yolov': ysyl.yolov,'result': result}globals_dict = {**globals(), **globals_dict}exec(pycode, globals_dict)state.状态_寻路中 = Falsestate.状态_检测中 = Falsestate.状态_已经有寻路了 = Falsestate.计数_没找到任何目标 = 0state.计时_未寻路 = 0return result['py_ret'], result['next']except:logger.error(f"{self.datas[idex]['name']} py执行错误: {traceback.format_exc()}")state.状态_需重新传送 = Falsestate.状态_寻路中 = Falsestate.状态_检测中 = Falsestate.状态_已经有寻路了 = Falsestate.计数_没找到任何目标 = 0state.计时_未寻路 = 0return False, "0"else:t2 = threading.Thread(target=ysyl.run_fight, args=(self.datas[idex]['f_item'].cb_wakuang.isChecked(), self.datas[idex]['f_item'].cb_caiji.isChecked(),self.datas[idex]['f_item'].cb_daguai.isChecked()))if state.python_var > 9:t2.daemon = Trueelse:t2.setDaemon(True)t2.start()try:image_path = os.path.join(dir_, self.datas[idex]['map'])image_path_barrier = os.path.join(dir_, self.datas[idex]['lujing'])return ysam.run_playback(image_path_barrier, image_path,self.datas[idex]['f_item'].cb_wakuang.isChecked(),self.datas[idex]['f_item'].cb_caiji.isChecked()), "0"except:state.状态_需重新传送 = Falsestate.状态_已经有寻路了 = Falsereturn False, "0"def clickd_bt_del(self, idex):dir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])try:# 删除整个文件夹shutil.rmtree(dir_)logger.info(f"文件夹 {dir_} 已被删除")self.update_tasks()except Exception as e:self.update_tasks()logger.info(f"删除文件夹时出现错误:{e}")def save(self):for idex in range(len(self.datas)):self.returnPressed_name(idex)# 重写closeEvent方法,在窗口关闭时调用quit()退出应用程序for i, data in enumerate(self.datas):dir_ = os.path.join(state.PATH_TASK, data["name"])self.save_ini(dir_, data)self.update_tasks()self.save_ini_seting()def closeEvent(self, event):self.save()app.quit()def clickd_bt_lujing(self, idex):dir_ = os.path.join(state.PATH_TASK, self.datas[idex]["name"])if not os.path.exists(dir_):state.状态_全局暂停 = TrueQMessageBox.information(self, "提示", "没有找到任务文件夹,请先设定任务")return Falseif state.状态_已经有寻路了:# 弹出提示,不要重复开QMessageBox.information(self, "提示", "已经有在运行的AI了,请先关闭!")return Falsestate.状态_全局暂停 = Truestate.状态_循环开关 = TrueQMessageBox.information(self, "开始录制了", "请控制角色去你的目的地,它会自己记录路线")self.datas[idex]['lujing'] = "路径.png"image_path = os.path.join(dir_, self.datas[idex]['map'])image_path_lujing = os.path.join(dir_, self.datas[idex]['lujing'])self.datas[idex]["f_item"].bt_lujing.setProperty("OK_lujing", True)self.datas[idex]["f_item"].bt_lujing.setStyleSheet("""#bt_lujing[OK_lujing="true"] {color: rgb(237,182,43); border-color: rgb(237,182,43); }""")t = threading.Thread(target=ysam.run_rec, args=(image_path, image_path_lujing))if state.python_var > 9:t.daemon = Trueelse:t.setDaemon(True)t.start()self.save_ini(dir_, self.datas[idex])return Truedef save_ini(self, dir_, d):try:# 创建 ConfigParser 对象config = configparser.ConfigParser()# 添加节和键-值对if d["type"] == "2":config['seting'] = {'type': d["type"],'name': d["name"],'cb_isfanxiang': d["f_item"].cb_isfanxiang.isChecked(),'led_cishu': d["f_item"].led_cishu.text(),'chuansong': d["chuansong"],'cbb_address': d['cbb_address'],'chuansongmoban': d["chuansongmoban"],'maodianmoban': d["maodianmoban"],'cb_is_checked': d["f_item"].cb_is_checked.isChecked()}elif d["type"] == "3":config['seting'] = {'type': d["type"],'name': d["name"],'cb_auto_f': d["f_item"].cb_auto_f.isChecked(),'jiaoben': d["jiaoben"],'chuansong': d["chuansong"],'cbb_address': d['cbb_address'],'chuansongmoban': d["chuansongmoban"],'maodianmoban': d["maodianmoban"],'cb_is_checked': d["f_item"].cb_is_checked.isChecked()}elif d["type"] == "4":config['seting'] = {'type': d["type"],'name': d["name"],'chuansong': d["chuansong"],'cb_is_checked': d["f_item"].cb_is_checked.isChecked(),'cbb_1': d["f_item"].cbb_1.itemData(d["f_item"].cbb_1.currentIndex()),'cbb_2': d["f_item"].cbb_2.itemData(d["f_item"].cbb_2.currentIndex()),'cbb_3': d["f_item"].cbb_3.itemData(d["f_item"].cbb_3.currentIndex()),'cbb_4': d["f_item"].cbb_4.itemData(d["f_item"].cbb_4.currentIndex()),"led_main": d["f_item"].led_main.text()}elif d["type"] == "5":config['seting'] = {'type': d["type"],'name': d["name"],'chuansong': d["chuansong"],'cb_is_checked': d["f_item"].cb_is_checked.isChecked(),'cbb_lianzhao': d["f_item"].cbb_lianzhao.currentText(),}elif d["type"] == "6":config['seting'] = {'type': d["type"],'name': d["name"],'arg': os.path.join(os.path.dirname(d["opendir"]), d["name"], '参数.ini'),'opendir': os.path.join(os.path.dirname(d["opendir"]), d["name"]),'chuansong': d["chuansong"],'cbb_address': d['cbb_address'],'chuansongmoban': d["chuansongmoban"],'maodianmoban': d["maodianmoban"],'cb_is_checked': d["f_item"].cb_is_checked.isChecked(),}else:config['seting'] = {'type': d["type"],'name': d["name"],'map': d["map"],'lujing': d["lujing"],'chuansong': d["chuansong"],'cbb_address': d['cbb_address'],'chuansongmoban': d["chuansongmoban"],'maodianmoban': d["maodianmoban"],'cb_is_checked': d["f_item"].cb_is_checked.isChecked(),'cb_wakuang': d["f_item"].cb_wakuang.isChecked(),'cb_caiji': d["f_item"].cb_caiji.isChecked(),'cb_daguai': d["f_item"].cb_daguai.isChecked()}# 写入配置到 INI 文件with open(os.path.join(dir_, "jiaoben.ini"), 'w') as configfile:config.write(configfile)except:passdef hotkey_importtask(self):# 弹出通用对话框选择文件夹source_folder = QFileDialog.getExistingDirectory(self, "选择文件夹")if source_folder == "":returndestination_folder = os.path.join(state.PATH_TASK, source_folder.split('/')[-1])if not os.path.exists(destination_folder):os.makedirs(destination_folder)else:QMessageBox.information(self, "提示", "已经有这个名字的任务了,请重命名后再试")returnlogger.info("导入任务 " + destination_folder)# 将整个文件夹的内容全部复制到test文件夹# 获取源文件夹中所有项的列表items = os.listdir(source_folder)# 循环处理列表中的每个项for item in items:# 构建源文件/文件夹的完整路径source = os.path.join(source_folder, item)# 构建目标文件/文件夹的完整路径destination = os.path.join(destination_folder, item)# 如果该项为文件,则使用shutil.copy()函数复制文件if os.path.isfile(source):shutil.copy(source, destination)# 如果该项为文件夹,则递归调用该函数复制文件夹elif os.path.isdir(source):shutil.copytree(source, destination)self.update_tasks()def hotkey_addtask(self):try:dir_ = os.path.join(state.PATH_TASK, "锄地任务" + str(int(time.time())) + str(random.randint(10, 100)))if not os.path.exists(dir_):os.makedirs(dir_)# 创建 ConfigParser 对象config = configparser.ConfigParser()# 加载 INI 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_task(dir_, config)self.save_ini(dir_, self.datas[-1])except:passdef hotkey_addtaskpy(self):try:dir_ = os.path.join(state.PATH_TASK, "Py任务" + str(int(time.time())) + str(random.randint(10, 100)))if not os.path.exists(dir_):os.makedirs(dir_)# 创建 ConfigParser 对象config = configparser.ConfigParser()# 加载 INI 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_taskpy(dir_, config)self.save_ini(dir_, self.datas[-1])except:passdef hotkey_addtaskjiaoben(self):dir_ = os.path.join(state.PATH_TASK, "脚本任务" + str(int(time.time())) + str(random.randint(10, 100)))if not os.path.exists(dir_):os.makedirs(dir_)# 创建 ConfigParser 对象config = configparser.ConfigParser()# 加载 INI 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_taskjiaoben(dir_, config)self.save_ini(dir_, self.datas[-1])def hotkey_qiejue(self):dir_ = os.path.join(state.PATH_TASK, "切换角色" + str(int(time.time())) + str(random.randint(10, 100)))if not os.path.exists(dir_):os.makedirs(dir_)# 创建 ConfigParser 对象config = configparser.ConfigParser()# 加载 INI 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_xuanjue(dir_, config)self.save_ini(dir_, self.datas[-1])def hotkey_qiehuanlianzhao(self):dir_ = os.path.join(state.PATH_TASK, "切换连招" + str(int(time.time())) + str(random.randint(10, 100)))if not os.path.exists(dir_):os.makedirs(dir_)# 创建 ConfigParser 对象config = configparser.ConfigParser()# 加载 INI 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_xuanlianzhao(dir_, config)self.save_ini(dir_, self.datas[-1])def hotkey_addtaskfuben(self):dir_ = os.path.join(state.PATH_TASK, "副本任务" + str(int(time.time())) + str(random.randint(10, 100)))if not os.path.exists(dir_):os.makedirs(dir_)# 创建 ConfigParser 对象config = configparser.ConfigParser()# 加载 INI 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_taskfuben(dir_, config)self.save_ini(dir_, self.datas[-1])def hotkey_opentaskdir(self):os.startfile(os.path.abspath(state.PATH_TASK))  # 使用startfile方法打开文件夹def hotkey_selecttaskdir(self):# 弹出通用对话框选择文件夹source_folder = QFileDialog.getExistingDirectory(self, "选择任务文件夹", state.PATH_TASK)if source_folder == "":returnstate.PATH_TASK = source_folderself.add_tool_item(state.PATH_TASK)state.PACKS_TASK += "#@@#" + state.PATH_TASKself.save_ini_seting()self.update_tasks()logger.info(f"成功设置{state.PATH_TASK}为当前任务文件夹")def hotkey_setlianzhao(self):# 弹出一个有分组框的窗口temp_path, ok = QFileDialog.getOpenFileName(self, "连招脚本", state.PATH_JIAOBEN, "脚本文件 (*.txt)")if ok:_, state.LIANZHAO = os.path.split(temp_path)dir_ = os.path.join(state.PATH_JIAOBEN, state.LIANZHAO)try:shutil.copy(temp_path, dir_)except:passlogger.info("选择连招脚本成功!")self.save_ini_seting()def hotkey_addlianzhao(self):# 弹出一个选择弹窗 选项为  录制还是文件中选择msgBox = QMessageBox(self)msgBox.setWindowTitle("配置连招")  # 设置消息框标题msgBox.setIcon(QMessageBox.Information)msgBox.setText("当前连招:" + state.LIANZHAO + "\n请选择一个配置方式:")msgBox.addButton("录制", QMessageBox.AcceptRole)msgBox.addButton("回放", QMessageBox.ApplyRole)msgBox.addButton("文件中选择", QMessageBox.RejectRole)result = msgBox.exec_()if result == QMessageBox.AcceptRole:try:text, ok = QInputDialog.getText(self, '提示', '请输入脚本名:', text=state.LIANZHAO)if not ok:returnif text == "":returnelif text[-4:] != ".txt":state.LIANZHAO = text + ".txt"else:state.LIANZHAO = textlogger.info("可以开始录制了,按F8开始/停止")self.sg.mysig_tishi.emit("可以开始录制了,按F8开始/停止")state.状态_是否禁止录制 = Falsestate.状态_是否开始录制 = Falsestate.录制_脚本文本 = ""tangbaowss.send_msg("是否禁止录制#@@#假")tangbaowss.send_msg("是否开始录制#@@#假")tangbaowss.send_msg(f"全局脚本名#@@#{state.LIANZHAO.replace('.txt', '')}")hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄tangbaowss.send_msg(f"全局hwnd#@@#{hwnd}")self.timer_luzhi_lianzhao.start(200)except:passelif result == QMessageBox.RejectRole:if state.状态_是否回放中 == True:returnif not os.path.exists(state.PATH_JIAOBEN):os.makedirs(state.PATH_JIAOBEN)state.状态_是否回放中 = Truestate.状态_循环开关 = Truejiaoben = os.path.abspath(os.path.join(state.PATH_JIAOBEN, state.LIANZHAO))message = f"解析脚本#@@#{jiaoben}"tangbaowss.send_msg(message)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄set_window_activate(hwnd)tangbaowss.send_msg("脚本执行#@@#1")self.timer_huifang.start(200)elif result == QMessageBox.Warning:self.hotkey_setlianzhao()def save_ini_seting(self):try:hwnd = ctypes.windll.kernel32.GetConsoleWindow()if hwnd:rect = win32gui.GetWindowRect(hwnd)x, y, w, h = rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]else:x, y, w, h = state.CMD_LEFT, state.CMD_TOP, state.CMD_WIDTH, state.CMD_HEIGHT# 创建 ConfigParser 对象config = configparser.ConfigParser()# 添加节和键-值对config['seting'] = {"GAME_TITLE": state.GAME_TITLE,'LIANZHAO': state.LIANZHAO,'LIANZHAOFUWU': state.LIANZHAOFUWU,'DUANGKOUHAO': state.DUANGKOUHAO,'PATH_TASK': state.PATH_TASK,'PATH_JIAOBEN': state.PATH_JIAOBEN,'PACKS_TASK': state.PACKS_TASK,'WEIGHTS': state.WEIGHTS,'PROVIDERS': state.PROVIDERS,'IMGSIZE_WIDTH': str(state.IMGSIZE_WIDTH),'IMGSIZE_HEIGHT': str(state.IMGSIZE_HEIGHT),'WINDOW_WIDTH': str(self.width()),'WINDOW_HEIGHT': str(self.height()),'WINDOW_LEFT': str(self.x()),'WINDOW_TOP': str(self.y()),'CMD_WIDTH': str(w),'CMD_HEIGHT': str(h),'CMD_LEFT': str(x),'CMD_TOP': str(y),'ON_SHUTDOWN': str(state.ON_SHUTDOWN),'ON_JIXING': str(state.ON_JIXING),'ON_NEXTPACK': str(state.ON_NEXTPACK),'ON_STARTWITH': str(state.ON_STARTWITH),'ON_LIANZHAOBUJIANCE': str(state.ON_LIANZHAOBUJIANCE),'TIMEOUT_DAGUAI': str(state.TIMEOUT_DAGUAI)}# 写入配置到 INI 文件with open("./datas/setting.ini", 'w') as configfile:config.write(configfile)except:passdef hotkey_all_ck(self):for item in self.datas:item['f_item'].cb_is_checked.setChecked(True)def hotkey_all_not_ck(self):for item in self.datas:item['f_item'].cb_is_checked.setChecked(False)def hotkey_all_fan_ck(self):for item in self.datas:item['f_item'].cb_is_checked.setChecked(not item['f_item'].cb_is_checked.isChecked())def hotkey_runall(self):global ysylhwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄if hwnd == 0:logger.info("错误:请先开游戏!")returnleft, top, right, bottom = win32gui.GetClientRect(hwnd)width = right - leftheight = bottom - topif width != 1920 or height != 1080:logger.info("错误:游戏分辨率不对!请确保游戏分辨率是1920x1080  建议重新设置分辨率")returnself.save()def run():self.sg.mysig_mouse_through.emit(True)# 运行 N 次ret = Falsefor rt in range(self.run_times):logger.info(f"任务包:{state.PATH_TASK} {rt + 1}/{self.run_times}")idex = 0state.计次_传送重试次数 = 0state.状态_全局暂停 = Falsewhile idex < len(self.datas):if state.状态_检测中:time.sleep(1)continueif self.datas[idex]['f_item'].cb_is_checked.isChecked():ret, arg = self.run(idex)if arg is None:arg = "0"if arg != "0":idex = self.arg_jisuan(arg, idex)if state.状态_循环开关 == False:breakif ret == False:if state.状态_需重新传送 == True:state.计次_传送重试次数 += 1if state.计次_传送重试次数 >= 5:state.计次_传送重试次数 = 0logger.info("传送重试次数过多,放弃该任务!")else:logger.info(f"传送重试{state.计次_传送重试次数}")time.sleep(2)continueelse:breakstate.计次_传送重试次数 = 0idex += 1if state.状态_循环开关 == False:breakif state.状态_循环开关 != False:# 切下一个任务包 继续next_tas = self.get_next_task()if state.ON_NEXTPACK == 1 and next_tas != None:state.PATH_TASK = next_taslogger.info("切下一个任务包!")self.sg.mysig_next_pack.emit()self.sg.mysig_mouse_through.emit(False)returnif ret == True and state.ON_JIXING == 1:ysyl.run_jixing()if ret == True and state.ON_SHUTDOWN == 1:self.sg.mysig_shutdown.emit()self.sg.mysig_mouse_through.emit(False)state.状态_循环开关 = Falset = threading.Thread(target=run)if state.python_var > 9:t.daemon = Trueelse:t.setDaemon(True)t.start()def hotkey_keys_ack(self):text, ok = QInputDialog.getText(self, '提示', '请输入关键字:', text="狗粮")if not ok:returnif text == "":returnfor item in self.datas:if text in item['f_item'].led_name.text():item['f_item'].cb_is_checked.setChecked(True)def hotkey_num_ck(self):text, ok = QInputDialog.getText(self, '提示', '请输入包含某数字的区间:', text="0-100")if not ok:returnif text == "":returntry:min_, main_ = list(map(int, text.split("-")))except:returnfor item in self.datas:if main_ >= extract_number(item['f_item'].led_name.text()) >= min_:item['f_item'].cb_is_checked.setChecked(True)def hotkey_find(self):text, ok = QInputDialog.getText(self, '提示', '请输入要定位的任务关键字:', text="绝缘")if not ok:returnif text == "":returnfor idex, item in enumerate(self.datas):if text in item['f_item'].led_name.text():self.dingwei(idex)def hotkey_deltask(self):for idex, item in enumerate(self.datas):if item['f_item'].cb_is_checked.isChecked():self.clickd_bt_del(idex)def hotkey_isShow(self):state.开关_是否展预测结果 = self.action_isShow.isChecked()if self.action_isShow.isChecked():# 判断窗口是否存在if not hasattr(self, "fromshow"):self.fromshow = FormShow(self)self.addDockWidget(Qt.TopDockWidgetArea, self.fromshow)self.fromshow.show()else:if hasattr(self, "fromshow"):self.fromshow.close()def hotkey_isShowCmd(self):show_hide_window(hwnd_cmd, self.action_isShowCmd.isChecked())def hotkey_yunduanlist(self):self.formyunfilelist = FormYunFileList()threading.Thread(target=self.formyunfilelist.update).start()self.formyunfilelist.show()self.formyunfilelist.lb_ing.show()self.formyunfilelist.lb_ing.move(self.formyunfilelist.width() - self.formyunfilelist.lb_ing.width(),self.formyunfilelist.height() - self.formyunfilelist.lb_ing.height())def hotkey_shutdown(self):if self.action_shutdown.isChecked():state.ON_SHUTDOWN = 1else:state.ON_SHUTDOWN = 0self.save_ini_seting()def hotkey_timeout(self):try:text, ok = QInputDialog.getText(self, '超时阈值', '请输入打怪超时阈值 单位秒:\n注意最低不能小于60秒',text=str(state.TIMEOUT_DAGUAI))if not ok:returnif text == "":returnif int(text) < 60:state.TIMEOUT_DAGUAI = 60else:state.TIMEOUT_DAGUAI = int(text)self.action_timeout.setText(f"设置打怪超时 阈值:{state.TIMEOUT_DAGUAI}秒")logger.info("设置打怪超时阈值为:" + str(state.TIMEOUT_DAGUAI))self.save_ini_seting()except:passdef hotkey_weights(self):try:# 创建一个窗口 里面有两个单选框self.fm_m = FormM(self)self.fm_m.show()# self.action_timeout.setText(f"设置打怪超时 阈值:{state.TIMEOUT_DAGUAI}秒")# logger.info("设置打怪超时阈值为:"+str(state.TIMEOUT_DAGUAI))# self.save_ini_seting()except:passdef hotkey_run_times(self):try:text, ok = QInputDialog.getText(self, '执行次数', f'当前任务包:{state.PATH_TASK}\n请输入执行次数:',text=str(self.run_times))if not ok:returnif text == "":returnif int(text) < 1:self.run_times = 1else:self.run_times = int(text)self.action_run_times.setText(f"设置:当前任务包 执行次数:{self.run_times}")logger.info(f"设置:当前任务包 执行次数:{self.run_times}")# 创建 ConfigParser 对象config_main = configparser.ConfigParser()# 添加节和键-值对config_main['seting'] = {"run_times": str(self.run_times),}# 写入配置到 INI 文件with open(os.path.join(state.PATH_TASK, "细节参数.ini"), 'w') as configfile:config_main.write(configfile)except:passdef hotkey_lianzhaobujiance(self):if self.action_lianzhaobujiance.isChecked():state.ON_LIANZHAOBUJIANCE = 1else:state.ON_LIANZHAOBUJIANCE = 0self.save_ini_seting()def hotkey_jixing(self):if self.action_jixing.isChecked():state.ON_JIXING = 1else:state.ON_JIXING = 0self.save_ini_seting()def hotkey_nextpack(self):if self.action_nextpack.isChecked():state.ON_NEXTPACK = 1else:state.ON_NEXTPACK = 0self.save_ini_seting()def hotkey_runstartwith(self):if self.action_runstartwith.isChecked():state.ON_STARTWITH = 1else:state.ON_STARTWITH = 0self.save_ini_seting()def hotkey_stitchimg(self):# 弹出通用对话框选择文件夹source_folder = QFileDialog.getExistingDirectory(self, "选择文件夹", "./datas/img")if source_folder == "":returnsi = StitchImages()image_paths = si.get_image_paths(source_folder)ret = si.stitch_images(image_paths, "./datas/max_map/max_map.png", True)if not ret:QMessageBox.information(self, "提示", "合成全景图失败,检查一下是不是每张图都有相交的地方")def hotkey_guai(self):for item in self.datas:if item['f_item'].cb_is_checked.isChecked():if item["type"] == "1":item['f_item'].cb_daguai.setChecked(self.action_guai.isChecked())def hotkey_kuang(self):for item in self.datas:if item['f_item'].cb_is_checked.isChecked():if item["type"] == "1":item['f_item'].cb_wakuang.setChecked(self.action_kuang.isChecked())def hotkey_hua(self):for item in self.datas:if item['f_item'].cb_is_checked.isChecked():if item["type"] == "1":item['f_item'].cb_caiji.setChecked(self.action_hua.isChecked())def set_cbb_items(self, cbb):cbb.clear()# 遍历文件夹下的所有png文件# 定义要遍历的文件夹路径folder_path = state.PATH_JUESE# 遍历文件夹及其子文件夹中的所有文件for root, dirs, files in os.walk(folder_path):for file in files:# 检查文件扩展名是否为.pngif file.endswith('.png'):# 打印PNG文件的完整路径file_name = os.path.splitext(file)[0]cbb.addItem("", file_name)# 获取下拉列表的视图部件view = cbb.view()# 设置特定子项的工具提示和相应的图片for index in range(cbb.count()):file_name = cbb.itemData(index)image_path = f"{folder_path}/{file_name}.png"if image_path:item = view.model().item(index, 0)pixmap = QPixmap(image_path)item.setIcon(QIcon(pixmap))# item.setToolTip(image_path)cbb.setIconSize(QSize(int(40 * ratio), int(50 * ratio)))  # 设置图标大小为40x40像素def set_cbb_item(self, cbb, name):# 设置特定子项的工具提示和相应的图片for index in range(cbb.count()):file_name = cbb.itemData(index)if file_name == name:cbb.setCurrentIndex(index)def autoSelectAddress(self, address_name="蒙德", isrun=False):img_filens = [cv2.imdecode(np.fromfile(file=state.PATH_ADDRESS + address_name + ".png", dtype=np.uint8),cv2.IMREAD_UNCHANGED),cv2.imdecode(np.fromfile(file=state.PATH_ADDRESS + address_name + "2.png", dtype=np.uint8),cv2.IMREAD_UNCHANGED)]# 获取窗口句柄hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄rect = win32gui.GetWindowRect(hwnd)w_p, h_p = (rect[2] - rect[0]) - 1920, (rect[3] - rect[1]) - 1080# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)# 点左下角的星星mouse_move(rect[0] + w_p + 1840, rect[1] + w_p + 1020)time.sleep(0.1)mouse_left_down()time.sleep(0.2)mouse_left_up()left, top, right, bottom = 1285, 75, 1916, 1043  # 替换成你实际的区域坐标p_left = rect[0] + w_p + leftp_top = rect[1] + h_p + topmax_confidence_value = 0max_res = {}for i in range(4):time.sleep(0.5)big_img = screenshot(hwnd, left, top, right, bottom, None)for item_img in img_filens:res = template_matching(big_img, item_img, mask=None)if res != []:max_confidence_dict = max(res, key=lambda x: x["confidence"])if max_confidence_dict["confidence"] > max_confidence_value:max_res = max_confidence_dictmax_confidence_value = max_confidence_dict["confidence"]if max_res != {}:breakif max_res == {}:logger.info("没找到对应地址的按钮,注意不要乱动鼠标!")if not isrun:self.sg.mysig_tishi.emit("没找到对应地址的按钮,注意不要乱动鼠标!")return Falsemouse_move(p_left + max_res['result'][0], p_top + max_res['result'][1])time.sleep(0.1)mouse_left_down()time.sleep(0.2)mouse_left_up()return True

2、添加自定义信号

vi main.py

class MySignal(QObject):mySignal = pyqtSignal(int, str)  # 定义自定义信号,并指定信号参数类型mysig_shutdown = pyqtSignal()mysig_mouse_through = pyqtSignal(bool)mysig_tishi = pyqtSignal(str)mysig_show_xunlu = pyqtSignal()mysig_show_yolov = pyqtSignal()mysig_dingwei=pyqtSignal(int)mysig_next_pack=pyqtSignal()

3、根据文本自动调整大小

class WrappedTextToolButton(QToolButton):def __init__(self, text, parent=None):super().__init__(parent)self.setText(text)def sizeHint(self):size_hint = super().sizeHint()font_metrics = self.fontMetrics()width = max(font_metrics.width(self.text()), 100)  # 最小宽度为 100 像素height = font_metrics.heightForWidth(width)size_hint.setWidth(width)size_hint.setHeight(height)return size_hint

4、提取文本数字

def extract_number(folder_name):numbers = re.findall(r'\d+', folder_name)return int(numbers[0]) if numbers else float('inf')

5、各个页面调用窗口添加

我们可以在主窗口 MainWindow中通过这些类调用其他的ui页面

class DialogChuansong(QDialog, Ui_dialogchuansong):def __init__(self, parent=None,idex=-1):super(QDialog, self).__init__(parent)self.idex=idexself.setupUi(self)self.set_ui()# 移除标题栏的问号按钮self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)# 过滤滚轮事件 防止误触self.cbb_address.installEventFilter(self)self.set_cbb_items()self.bt_luzhi.clicked.connect(self.onn_bt_luzhi)self.bt_huifang.clicked.connect(self.onn_bt_huifang)self.bt_wenjianxuan.clicked.connect(self.onn_bt_wenjianxuan)self.cbb_address.currentIndexChanged.connect(self.onn_cbb_address)self.clb_jiaocheng.clicked.connect(lambda: webbrowser.open("https://www.bilibili.com/video/BV124421U7GN/"))# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)def set_ui(self):passdef eventFilter(self,obj, event):if isinstance(obj, QComboBox) and event.type() == QEvent.Wheel and not obj.view().isVisible():return True  # 拦截鼠标滚轮事件return Falsedef set_cbb_items(self):#self.cbb_address .clear()#遍历文件夹下的所有png文件# 定义要遍历的文件夹路径folder_path =state.PATH_ADDRESS# 遍历文件夹及其子文件夹中的所有文件for root, dirs, files in os.walk(folder_path):for file in files:# 检查文件扩展名是否为.pngif file.endswith('.png'):# 打印PNG文件的完整路径file_name = os.path.splitext(file)[0]if file_name[-1]!="2":self.cbb_address.addItem(file_name)def onn_bt_luzhi(self):# 获取窗口句柄hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄rect = win32gui.GetWindowRect(hwnd)# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)left, top, right, bottom = 1,979,120,1074  # 替换成你实际的区域坐标dituchilun_img = cv2.imdecode(np.fromfile(file="./datas/地图齿轮.png", dtype=np.uint8), cv2.IMREAD_UNCHANGED)if self.cbb_address.currentIndex() != 0:big_img = screenshot(hwnd, left, top, right, bottom, None)res = template_matching(big_img, dituchilun_img, mask=None)if res==[]:QMessageBox.information(self, "提示", "请先打开地图 后再操作")#弹出信息框 提示先打开地图returnif ctypes.windll.user32.GetForegroundWindow() != hwnd:# 激活hwndhwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄set_window_activate(hwnd)time.sleep(0.1)if self.cbb_address.currentIndex()!=0:logger.info("稍等 正在自动选择区域...")self.parent().sg.mysig_tishi.emit("稍等 正在自动选择区域...")if not self.parent().autoSelectAddress(self.cbb_address.currentText()):returnlogger.info("可以开始录制拖动地图过程了,按F8开始/停止")self.parent().sg.mysig_tishi.emit("可以开始录制拖动地图过程了,按F8开始/停止")state.状态_是否禁止录制 = Falsestate.状态_是否开始录制 = Falsestate.录制_当前任务索引 = self.idexstate.录制_脚本文本 = ""state.录制_当前脚本名 = self.parent().datas[self.idex]["name"]tangbaowss.send_msg("是否开始录制#@@#假")tangbaowss.send_msg("是否禁止录制#@@#假")tangbaowss.send_msg(f"全局脚本名#@@#传送-{state.录制_当前脚本名}")hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄tangbaowss.send_msg(f"全局hwnd#@@#{hwnd}")self.parent().timer_luzhi_chuansong.start(200)self.close()def onn_bt_huifang(self):if state.状态_是否回放中 == True:returndir_ = os.path.join(state.PATH_TASK, self.parent().datas[self.idex]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 获取窗口句柄hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄rect = win32gui.GetWindowRect(hwnd)# 设定截图区域的左上角坐标 (x, y) 和右下角坐标 (x, y)left, top, right, bottom = 1, 979, 120, 1074  # 替换成你实际的区域坐标dituchilun_img = cv2.imdecode(np.fromfile(file="./datas/地图齿轮.png", dtype=np.uint8),cv2.IMREAD_UNCHANGED)big_img = screenshot(hwnd, left, top, right, bottom, None)res = template_matching(big_img, dituchilun_img, mask=None)if res == []:QMessageBox.information(self, "提示", "请先打开地图 后再操作")# 弹出信息框 提示先打开地图returnif ctypes.windll.user32.GetForegroundWindow() != hwnd:# 激活hwndhwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄set_window_activate(hwnd)time.sleep(0.1)if self.cbb_address.currentIndex() != 0:logger.info("正在自动选择区域...")self.parent().sg.mysig_tishi.emit("正在自动选择区域...")if not self.parent().autoSelectAddress(self.cbb_address.currentText()):returnlogger.info("回放脚本中! 按F9停止")self.parent().sg.mysig_tishi.emit("回放脚本中! 按F9停止")state.状态_循环开关 = Truestate.状态_是否回放中 = Truejiaoben = os.path.abspath(os.path.join(dir_, self.parent().datas[self.idex]["chuansong"]))message = f"解析脚本#@@#{jiaoben}"tangbaowss.send_msg(message)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE)  # 替换成你实际的窗口句柄set_window_activate(hwnd)tangbaowss.send_msg("脚本执行#@@#1")self.parent().timer_huifang.start(200)self.close()def onn_bt_wenjianxuan(self):# 弹出一个有分组框的窗口temp_path, ok = QFileDialog.getOpenFileName(self, "传送脚本", "", "脚本文件 (*.txt)")if ok:dir_ = os.path.join(state.PATH_TASK, self.parent().datas[self.idex]["name"])if not os.path.exists(dir_):os.makedirs(dir_)# 并且将jiaoben.ini文件也填入数据然后生成# 将图片复制到指定目录path = dir_ + "/传送脚本.txt"shutil.copy(temp_path, path)self.parent().datas[self.idex]["chuansong"] = "传送脚本.txt"self.parent().datas[self.idex]["f_item"].bt_chuansong.setProperty("OK_chuansong", True)logger.info(f"导入传送脚本成功:{path}")self.parent().sg.mysig_tishi.emit(f"导入传送脚本成功:{path}")self.parent().datas[self.idex]["f_item"].bt_chuansong.setStyleSheet("""#bt_chuansong[OK_chuansong="true"] {color: rgb(237,182,43);border-color: rgb(237,182,43);}""")self.parent().save_ini(dir_, self.parent().datas[self.idex])self.close()def onn_cbb_address(self,index):self.parent().datas[self.idex]['cbb_address']=self.cbb_address.currentText()
class FrameItem(QFrame, Ui_formitem):def __init__(self, parent=None):super(QFrame, self).__init__(parent)self.setupUi(self)self.set_ui()self.is_zd=Falsew = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1 * ratio), h)self.setMaximumSize(w, h)# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)def set_ui(self):passdef mousePressEvent(self, event):if not self.is_zd:self.is_zd=not self.is_zdw = int(item_width * ratio)h = int(item_height * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_map.setVisible(True)self.bt_lujing.setVisible(True)self.bt_chuansong.setVisible(True)self.bt_moban.setVisible(True)self.bt_moban_maodian.setVisible(True)self.bt_start.setVisible(True)self.cb_wakuang.setVisible(True)self.cb_caiji.setVisible(True)self.cb_daguai.setVisible(True)self.bt_del.setVisible(True)else:self.is_zd = not self.is_zdw = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_map.setVisible(False)self.bt_lujing.setVisible(False)self.bt_chuansong.setVisible(False)self.bt_moban.setVisible(False)self.bt_moban_maodian.setVisible(False)self.bt_start.setVisible(False)self.cb_wakuang.setVisible(False)self.cb_caiji.setVisible(False)self.cb_daguai.setVisible(False)self.bt_del.setVisible(False)
class FramePY(QFrame, Ui_formpy):def __init__(self, parent=None):super(QFrame, self).__init__(parent)self.setupUi(self)self.set_ui()self.is_zd=Falsew = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1 * ratio), h)self.setMaximumSize(w, h)# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)def set_ui(self):passdef mousePressEvent(self, event):if not self.is_zd:self.is_zd=not self.is_zdw = int(item_width * ratio)h = int(item_height * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_arg.setVisible(True)self.bt_opendir.setVisible(True)self.bt_chuansong.setVisible(True)self.bt_moban.setVisible(True)self.bt_moban_maodian.setVisible(True)self.bt_start.setVisible(True)self.bt_del.setVisible(True)else:self.is_zd = not self.is_zdw = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_arg.setVisible(False)self.bt_opendir.setVisible(False)self.bt_chuansong.setVisible(False)self.bt_moban.setVisible(False)self.bt_moban_maodian.setVisible(False)self.bt_start.setVisible(False)self.bt_del.setVisible(False)
class FrameItemFuBen(QFrame, Ui_formitemfuben):def __init__(self, parent=None):super(QFrame, self).__init__(parent)self.setupUi(self)self.set_ui()self.is_zd=Falsew = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1 * ratio), h)self.setMaximumSize(w, h)# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)def set_ui(self):passdef mousePressEvent(self, event):if not self.is_zd:self.is_zd=not self.is_zd# 在这里添加鼠标进入时的逻辑w = int(item_width * ratio)h = int(item_height * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_chuansong.setVisible(True)self.bt_moban.setVisible(True)self.bt_moban_maodian.setVisible(True)self.bt_start.setVisible(True)self.bt_del.setVisible(True)self.cb_isfanxiang.setVisible(True)self.led_cishu.setVisible(True)self.label.setVisible(True)else:self.is_zd = not self.is_zdw = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1 * ratio), h)self.setMaximumSize(w, h)self.bt_chuansong.setVisible(False)self.bt_moban.setVisible(False)self.bt_moban_maodian.setVisible(False)self.bt_start.setVisible(False)self.bt_del.setVisible(False)self.cb_isfanxiang.setVisible(False)self.led_cishu.setVisible(False)self.label.setVisible(False)
class FrameItemJiaoBen(QFrame, Ui_formitemjiaoben):def __init__(self, parent=None):super(QFrame, self).__init__(parent)self.setupUi(self)self.set_ui()self.is_zd=Falsew = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1 * ratio), h)self.setMaximumSize(w, h)# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)def set_ui(self):passdef mousePressEvent(self, event):if not self.is_zd:self.is_zd=not self.is_zd# 在这里添加鼠标进入时的逻辑w = int(item_width* ratio)h = int(item_height* ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_start.setVisible(True)self.bt_jiaoben.setVisible(True)self.bt_chuansong.setVisible(True)self.bt_moban_maodian.setVisible(True)self.bt_moban.setVisible(True)self.bt_start.setVisible(True)self.bt_del.setVisible(True)self.cb_auto_f.setVisible(True)else:self.is_zd = not self.is_zdw = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_start.setVisible(False)self.bt_jiaoben.setVisible(False)self.bt_chuansong.setVisible(False)self.bt_moban_maodian.setVisible(False)self.bt_moban.setVisible(False)self.bt_start.setVisible(False)self.bt_del.setVisible(False)self.cb_auto_f.setVisible(False)
class FrameItemXuanJue(QFrame, Ui_formitemxuanjue):def __init__(self, parent=None):super(QFrame, self).__init__(parent)self.setupUi(self)self.set_ui()self.is_zd=Falsew = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1 * ratio), h)self.setMaximumSize(w, h)# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)#过滤滚轮事件 防止误触self.cbb_1.installEventFilter(self)self.cbb_2.installEventFilter(self)self.cbb_3.installEventFilter(self)self.cbb_4.installEventFilter(self)def eventFilter(self,obj, event):if isinstance(obj, QComboBox) and event.type() == QEvent.Wheel and not obj.view().isVisible():return True  # 拦截鼠标滚轮事件return Falsedef set_ui(self):passdef mousePressEvent(self, event):if not self.is_zd:self.is_zd=not self.is_zd# 在这里添加鼠标进入时的逻辑w = int(item_width * ratio)h = int(item_height * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_start.setVisible(True)self.cbb_1.setVisible(True)self.cbb_2.setVisible(True)self.cbb_3.setVisible(True)self.cbb_4.setVisible(True)self.lb_zhanchang.setVisible(True)self.led_main.setVisible(True)self.bt_del.setVisible(True)else:self.is_zd = not self.is_zdw = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_start.setVisible(False)self.cbb_1.setVisible(False)self.cbb_2.setVisible(False)self.cbb_3.setVisible(False)self.cbb_4.setVisible(False)self.lb_zhanchang.setVisible(False)self.led_main.setVisible(False)self.bt_del.setVisible(False)
class FrameItemLianZhao(QFrame, Ui_formitemlianzhao):def __init__(self, parent=None):super(QFrame, self).__init__(parent)self.setupUi(self)self.set_ui()self.is_zd=Falsew = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1 * ratio), h)self.setMaximumSize(w, h)# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)#过滤滚轮事件 防止误触self.cbb_lianzhao.installEventFilter(self)def eventFilter(self,obj, event):if isinstance(obj, QComboBox) and event.type() == QEvent.Wheel and not obj.view().isVisible():return True  # 拦截鼠标滚轮事件return Falsedef set_ui(self):passdef mousePressEvent(self, event):if not self.is_zd:self.is_zd=not self.is_zd# 在这里添加鼠标进入时的逻辑w = int(item_width * ratio)h = int(item_height * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_start.setVisible(True)self.cbb_lianzhao.setVisible(True)self.bt_del.setVisible(True)else:self.is_zd = not self.is_zdw = int(item_width * ratio)h = int(item_height_min * ratio)self.setMinimumSize(w + int(1* ratio), h)self.setMaximumSize(w, h)self.bt_start.setVisible(False)self.cbb_lianzhao.setVisible(False)self.bt_del.setVisible(False)
class FormShow(QDockWidget, Ui_DockWidget):def __init__(self, parent=None):super(QDockWidget, self).__init__(parent)self.parent=parentself.setParent(parent)self.setupUi(self)self.set_ui()#self.timer = QTimer()self.setWindowTitle("检测预览")self.lb_yolov.setScaledContents(True)self.lb_yolov.setAlignment(Qt.AlignCenter)self.lb_xunlu.setAlignment(Qt.AlignCenter)self.move(0, 0)self.setWindowFlags(Qt.WindowStaysOnTopHint)self.window_height=int(270* ratio)self.window_width=int(480* ratio)self.setMinimumSize(self.window_width,self.window_height*2)self.bt_jia.clicked.connect(self.clicked_jia)self.bt_jian.clicked.connect(self.clicked_jian)def set_ui(self):passdef clicked_jia(self):if self.window_height+108* ratio>1080* ratio:returnself.window_height += int(108* ratio)self.window_width += int(190* ratio)self.lb_xunlu.setFixedHeight(self.window_height)if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():self.lb_yolov.move(self.lb_xunlu.width(), 0)else:self.lb_yolov.move(0, self.lb_xunlu.height())self.lb_yolov.setFixedHeight(self.window_height)self.lb_yolov.setFixedWidth(self.window_width)def clicked_jian(self):if self.window_height-108* ratio < 270* ratio:returnself.window_height -= int(108* ratio)self.window_width -= int(190* ratio)self.lb_xunlu.setFixedHeight(self.window_height)if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():self.lb_yolov.move(self.lb_xunlu.width(), 0)else:self.lb_yolov.move(0, self.lb_xunlu.height())self.lb_yolov.setFixedHeight(self.window_height)self.lb_yolov.setFixedWidth(self.window_width)def closeEvent(self, event):state.开关_是否展预测结果 = Falseself.parent.action_isShow.setChecked(state.开关_是否展预测结果)def resizeEvent(self, event):if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():self.lb_yolov.move(self.lb_xunlu.width(), 0)else:self.lb_yolov.move(0, self.lb_xunlu.height())
class FormItemYun(QFrame, Ui_formitemyun):def __init__(self, parent=None):super(QFrame, self).__init__(parent)self.setupUi(self)self.set_ui()# self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)def set_ui(self):pass
class FormYunFileList(QFrame, Ui_form_yunfilelist,YunPan):def __init__(self):super().__init__()YunPan.__init__(self)self.set_ui()self.setupUi(self)self.setWindowIcon(QIcon("datas/logo.png"))self.setWindowTitle('懒人群友云端资源 感谢零度可乐提供云端支持')  # 标题self.setWindowFlags(Qt.WindowStaysOnTopHint)self.resize(int(910*ratio), int(700*ratio))self.g_box = QGridLayout()self.container_widget = QWidget()  # 创建一个中间部件  为了可以让g_布局超过窗口大小self.container_widget.setLayout(self.g_box)  # 将网格布局设置给中间部件self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft)  # 布局 左上对齐self.g_box.setContentsMargins(0, 0, 0, 0)  # 边距self.g_box.setAlignment(Qt.AlignTop)self.sa_main.setWidget(self.container_widget)  # 将中间部件设置为QScrollArea的子部件# 获取纵向滚动条控件vertical_scrollbar = self.findChild(QScrollArea)self.v_scrollbar = vertical_scrollbar.verticalScrollBar()self.row = 0self.column = -1# 所有数据self.datas = []self.login()# 创建一个计时器,用于延迟布局self.timer = QTimer(self)self.timer.setSingleShot(True)  # 设置为单次触发self.timer.timeout.connect(self.update_layout)self.connect_set()self.ing=True# 创建一个计时器,用于延迟布局self.timer1 = QTimer(self)self.timer1.timeout.connect(self.update_init)self.timer1.start(200)self.lb_ing=QLabel("加载中请稍等...",self)self.lb_ing.setStyleSheet("""font: 75 50pt "微软雅黑";color: rgb(255, 0, 0);""")self.lb_ing.resize(500,100)def update_init(self):if not self.ing:self.updatefilelist()self.lb_ing.close()self.timer1.stop()def set_ui(self):self.setStyleSheet("""QScrollBar::handle:horizontal {background-color: #A50F2C;  /* 设置滑块颜色 */}QScrollBar::handle:horizontal:hover{background-color: #FF1744;  /* 设置滑块颜色 */} QPushButton:hover{background-color: #DFC472;  /* 设置颜色 */}QPlainTextEdit{padding: 0px;margin: 0px;}QPushButton{padding: 0px;margin: 1px;}""" + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))def resizeEvent(self, event):super().resizeEvent(event)# 每当用户调整窗口大小时,启动计时器self.timer.start(300)  # 500毫秒后触发timeout信号def connect_set(self):self.tabWidget.currentChanged.connect(self.currentChanged_tabWidget)def currentChanged_tabWidget(self,index):self.updatefilelist(keys=self.tabWidget.tabText(index))def update_layout(self):try:# 获取主窗口的宽度width = self.width()# 计算每行可以容纳的组件数量num_per_row = (width ) // (280 * ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1# 清空当前布局for i in reversed(range(self.g_box.count())):self.g_box.itemAt(i).widget().setParent(None)# 重新添加组件到网格布局for i, data in enumerate(self.datas):self.row = int(i // num_per_row)self.column =int( i % num_per_row)self.g_box.addWidget(data["f_item"], self.row, self.column)except:passdef update(self):self.ing=Trueself.file_all=[]self.file_all = self.get_file_all(isclose=True)self.file_all = list(map(lambda x: {"name": x['name'], "sign": x['sign'], "dir": x['dir'],"url": x['raw_url'], "modified": x['modified']}, self.file_all))self.file_all = sorted(self.file_all, key=lambda x: datetime.strptime(x['modified'].split("+")[0].split(".")[0],"%Y-%m-%dT%H:%M:%S"),reverse=True)self.ing = Falsedef updatefilelist(self,keys=""):try:if keys=="全部":keys=""self.datas = []self.row = 0self.column = -1# 清空当前布局for i in reversed(range(self.g_box.count())):self.g_box.itemAt(i).widget().setParent(None)for item in self.file_all:if keys in item[ "dir"].split("/")[-3] or keys=="":self.add_yun_file(data=item)except:passdef add_yun_file(self,data={}):'''添加云文件显示:return:'''# 根据导入的文件# 获取主窗口的宽度# 获取主窗口的宽度width = self.width()# 计算每行可以容纳的组件数量num_per_row = (width )  // (280* ratio)  # 假设每个组件的宽度为200if num_per_row < 1:num_per_row = 1self.column += 1if self.column == num_per_row:self.column = 0self.row += 1f_item = FormItemYun()w = int(300* ratio)h = int(180* ratio)f_item.setMinimumSize(int((w + 13)* ratio), h)f_item.setMinimumSize(w, h)f_item.setMaximumSize(w, h)f_item.setObjectName("frame_cont")f_item.raise_()f_item.setStyleSheet("""#frame_cont:hover {border: 1px solid red;}#frame_cont {background-color: rgba(0, 0, 0, 0);}""")f_item.bt_down.clicked.connect(lambda: webbrowser.open(data["url"]))f_item.led_name.setText(data["name"])f_item.led_author.setText(data["dir"].split("/")[-2][:-6])f_item.led_time.setText(data["modified"].split(".")[0].replace("T", " "))data["f_item"] = f_itemself.datas.append(data)self.g_box.addWidget(f_item, self.row, self.column)
class FormM(QFrame, Ui_form_m):def __init__(self, parent=None):super(QFrame, self).__init__()self.parent=parentself.setupUi(self)self.set_ui()self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint | Qt.WindowStaysOnTopHint)self.setWindowIcon(QIcon("datas/logo.png"))self.setWindowTitle('选择模型')  # 标题self.bt_save.clicked.connect(self.onn_bt_save)onnx_file_names = []# 遍历文件夹中所有文件和子文件夹for root, dirs, files in os.walk(".\\datas"):for file in files:# 检查文件是否以 .onnx 结尾if file.endswith('.onnx'):# 如果是 .onnx 文件,则将其路径加入列表file_name = os.path.splitext(file)[0]onnx_file_names.append(file_name)self.cbb_m.addItems(onnx_file_names)self.cbb_m.setCurrentText(state.WEIGHTS.split('/')[-1].split('.')[0])print("1111",state.WEIGHTS.split('/')[-1].split('.')[0])def set_ui(self):passdef onn_bt_save(self):state.WEIGHTS='./datas/'+self.cbb_m.currentText()+".onnx"state.IMGSIZE_WIDTH=int(self.cbb_m.currentText().split("_")[-1])state.IMGSIZE_HEIGHT = int(self.cbb_m.currentText().split("_")[-1])self.parent.close()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144771.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

centos 安装VNC,实现远程连接

centos 安装VNC&#xff0c;实现远程连接 VNC(Virtual Network Computing)是一种远程控制软件&#xff0c;可以实现通过网络远程连接计算机的图形界面。 服务器安装VNC服务 yum install -y tigervnc-server*启动VNC服务&#xff0c;过程中需要输入连接密码 vncserver :1查看…

全国网安众测招募计划启动啦,欢迎加入~

在数字化时代&#xff0c;网络安全已成为维护社会稳定、促进经济发展的基石。为了积极响应国家关于加强网络安全工作的号召&#xff0c;确保某区域关键信息系统的稳固运行&#xff0c;我们特此启动一项网络安全众测活动。该活动旨在通过汇聚业界有经验的网络安全攻防人才&#…

RetrievalAttention——提高 LLM 处理长上下文的效率

概述 论文地址&#xff1a;https://arxiv.org/abs/2409.10516 本文的研究背景主要是为了解决 "具有长语境的大型语言模型&#xff08;LLM&#xff09;"问题。基于变换器的 LLM 被广泛应用于各个领域&#xff0c;但在处理长上下文时&#xff0c;其计算成本非常高。特…

电脑USB端口禁止软件有哪些?什么软件能指定USB端口禁用?分享四款好用软件!

想象一下&#xff0c;你正准备在办公桌上插入U盘&#xff0c;打算快速拷贝文件&#xff0c;突然系统蹦出一个警告&#xff1a;“这个USB端口已被禁用&#xff01;” 是不是感觉好像被一双隐形的手制止了&#xff1f; 其实&#xff0c;这双“隐形的手”就是专门为企业安全设计…

visionpro脚本

visionproToolBlock的脚本的优先级优于工具连线的优先级&#xff0c;一般是照着脚本的执行顺序进行执行对应的工具&#xff0c;最常用的是C#的高级脚本&#xff0c;C#的脚本如下分为5部分。 第一部分&#xff1a;主要是一些库的引用&#xff0c;对于有些类型不知道库的时候&…

vue2中字符串动态拼接字段给到接口

【设计初衷是用户可根据给定的字段进行准确描述】 实现功能&#xff1a; 1. 文本域内容串动态配置字段&#xff0c;以$ {英文}拼接格式给到接口。 &#xff08;传参如&#xff1a;$ {heat_status_code}正常&#xff0c;$ {wdy_temp}也正常&#xff01;&#xff09; 2. 编辑时根…

Instagram全面升级“青少年账号”保护措施,除了信息分类过滤,还应从根源加强内容审核

在持续多年的监管和诉讼压力下&#xff0c;作为社交网站的巨头&#xff0c;Instagram落实了“最严格的青少年用户保护法”。 Instagram 上所有未满 18 岁的用户都将被归为“青少年用户”&#xff0c;默认把账号设置为私密状态&#xff0c;自动实施多项防护措施&#xff0c;很多…

Vue3实战:使用 errorHandler 捕获全局错误

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 在 Vue3 中&#xff0c;app.config.errorHandler 是一个错误处理器&#xff0c;用于为应用内抛出的未捕获错误指定一个全局处理函数&#xff0c;它接收三个参数&#xff1a;错误对象、触发该错误的组件…

什么品牌超声波清洗机质量好?四大绝佳超声波清洗机品牌推荐!

在快节奏的现代生活中&#xff0c;个人物品的清洁卫生显得至关重要。眼镜、珠宝饰品、手表乃至日常餐厨用具&#xff0c;这些频繁接触的物品极易累积污渍与细菌。拿眼镜为例&#xff0c;缺乏定期清洁会让油渍与尘埃积累&#xff0c;进而成为细菌的温床&#xff0c;靠近眼睛使用…

人脸识别系统+电插锁安装配置过程

一、适用场景 1、各住宅小区内&#xff0c;一个单元涉及多户&#xff0c;一楼安装公共的人脸识别门禁进行身份的认证。 2、某企业的职工住宅区&#xff0c;企业统一安装人脸识别门禁认证身份。 3、自建楼栋&#xff0c;分多间出租给住户时&#xff0c;每个住户配备电子钥匙存在…

GEE使用require函数调用自己的Js库

新建了一个repository&#xff0c;名为Lib 把我的地形校正的函数放了进去 在自己的代码中调用就用到这个路径&#xff0c;主要Lib后面用冒号

观《中国数据库前世今生》有感:从历史到未来的技术变迁

观《中国数据库前世今生》有感&#xff1a;从历史到未来的技术变迁 在数字化浪潮中&#xff0c;数据库技术作为信息化建设的核心&#xff0c;承载了时代发展的脉搏。观看了纪录片《中国数据库前世今生》后&#xff0c;我深深感受到了中国数据库技术从无到有、从追赶到引领的艰…

深度残差网络ResNet简介

【图书推荐】《PyTorch深度学习与企业级项目实战》-CSDN博客 《PyTorch深度学习与企业级项目实战&#xff08;人工智能技术丛书&#xff09;》(宋立桓&#xff0c;宋立林)【摘要 书评 试读】- 京东图书 (jd.com) 卷积神经网络经典模型架构简介-CSDN博客 深度残差网络&#xf…

10分钟搞清楚为什么Transformer中使用LayerNorm而不是BatchNorm

1. Norm(Normalization) 首先&#xff0c;LayerNorm和BatchNorm的Norm是Normalization的缩写,不是Norm-范数。 Normalization在统计学中一般翻译为归一化&#xff0c;还有类似的是Standardization&#xff0c;一般翻译成标准化。这两个概念有什么区别呢&#xff1f; 归一化是…

vue2 + moment 实现日历,并带有上个月和下个月日期的日历

在 Vue 2 中使用 moment 库绘制一个带有上个月和下个月日期的日历&#xff0c;可以通过以下步骤实现。这个日历将显示当前月份的天数&#xff0c;以及前一个月和下一个月的部分日期&#xff08;通常为了让日历对齐为6行&#xff0c;每行7天&#xff09;。 主要步骤&#xff1a…

海睿思ABI——不只是BI,更多的是数据和智能

在当今这个数据洪流席卷各行各业的数字化时代&#xff0c;企业BI的建设已不再是可选项&#xff0c;而是驱动企业转型升级、实现精细化运营的必由之路。传统BI通过临时数据集直连业务系统&#xff0c;仅能展示预设报表和仪表盘&#xff0c;难以集成异构数据源&#xff0c;适应业…

【数学二】函数概念、常用函数、函数四大性质

考试要求 1、理解函数的概念&#xff0c;掌握函数的表示法&#xff0c;并会建立应用问题的函数关系. 2、了解函数的有界性、单调性、周期性和奇偶性. 3、理解复合函数及分段函数的概念、了解反函数及隐函数的概念。 4、掌握基本初等函数的性质及其图形、了解初等函数的概念。…

SpringCloud从零开始简单搭建 - JDK17

文章目录 SpringCloud Nacos从零开始简单搭建 - JDK17一、创建父项目二、创建子项目三、集成Nacos四、集成nacos配置中心 SpringCloud Nacos从零开始简单搭建 - JDK17 环境要求&#xff1a;JDK17、Spring Boot3、maven。 那么&#xff0c;如何从零开始搭建一个 SpringCloud …

PyQGIS开发 3 基础功能开发

PyQGIS开发 3 基础功能开发 1 添加图层树与地图视图 1.1 添加控件 1.2 Python代码 from PyQt5.QtCore import QMimeData from qgis.PyQt.QtWidgets import QMainWindow from qgis._core import QgsMapLayer, QgsRasterLayer, QgsVectorLayer from qgis.core import QgsProje…

美联储降息引爆股市,标普500指数逼近历史新高

在美联储宣布大幅降息后&#xff0c;股市迎来了强劲反弹。投资者信心大增&#xff0c;此前他们就预期美联储会降息0.5个百分点。周四的股市涨幅让标普500指数接近历史收盘最高点。 周四&#xff0c;标普500指数有望刷新历史纪录&#xff0c;此前美联储的大幅降息为市场注入了活…