yolo自动化项目实例解析(二)ui页面整理 1.78
我们在上一章整理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"))
二、 ui窗口布局代码解析
1、main.py添加调用主窗口 及窗口属性
ysam = YunShenAutoMap() # 启动寻路类print(ysam)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_()) # 监听消息不关闭
1、新增主窗口ui文件
vi ui/main.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>mainWindow</class><widget class="QMainWindow" name="mainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>800</width><height>600</height></rect></property><property name="windowTitle"><string>原神锄地AI v1.4 F8暂停 F9停止 F10标记</string></property><widget class="QWidget" name="centralwidget"><layout class="QHBoxLayout" name="horizontalLayout"><item><widget class="QScrollArea" name="sa_main"><property name="widgetResizable"><bool>true</bool></property><widget class="QWidget" name="scrollAreaWidgetContents"><property name="geometry"><rect><x>0</x><y>0</y><width>768</width><height>558</height></rect></property></widget></widget></item></layout></widget><widget class="QStatusBar" name="sb_main"/><widget class="QToolBar" name="toolBar"><property name="windowTitle"><string>toolBar</string></property><attribute name="toolBarArea"><enum>LeftToolBarArea</enum></attribute><attribute name="toolBarBreak"><bool>false</bool></attribute></widget><action name="actionSave_All"><property name="text"><string>Save All</string></property></action><action name="actionAdd_Mode"><property name="text"><string>Add Task</string></property></action><action name="actionAdd_Script"><property name="text"><string>Add Script</string></property></action></widget><resources/><connections/>
</ui>
转换py
pyuic5 -o ./main.py ./main.ui
2、新增主窗口函数
from PyQt5.QtGui import QFont, QIcon
from ui.main import Ui_mainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow
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)#调整整个页面为灰色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()))
3、运行测试
4、main当前代码整理
import ctypes
import os
import subprocess
import sys
import time
import tracebackfrom PyQt5.QtWidgets import QApplication, QMainWindowimport state
from auto import main
from wayfinding import *
from logger_module import logger
from jianchaupdate import get_var_data, get_updatetxt
from lanrentools.moni import find_child_window_handle, screen_widthfrom PyQt5.QtGui import QFont, QIcon
from ui.main import Ui_mainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow
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)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()))if __name__ == '__main__':try:if ctypes.windll.shell32.IsUserAnAdmin():hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "YuanShenAi")if hwnd_cmd == 0:hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "懒人原神")vardata = get_var_data()if vardata != False:updatetxt = get_updatetxt()print(updatetxt)print("当前版本号:" + state.版本号)if float(vardata[1]) > float(state.版本号):print("如果更新失败手动下更新包手动覆盖: https://gitee.com/LanRenZhiNeng/lanren-genshin-impact-ai/releases")var = input(f"发现更新的版本 v{vardata[1]} 是否需要更新? (输入yes or no 默认更新)\n")if var == "":var = "yes"if var.lower() != "no":update_process = subprocess.Popen(f'update.exe "{vardata[0]}.exe" "{vardata[2]}"',creationflags=subprocess.CREATE_NEW_CONSOLE)time.sleep(1)sys.exit()# 运行需要管理员权限的代码kernel32 = ctypes.windll.kernel32kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), 128)os.environ['PNG_IGNORE_WARNINGS'] = '1'# 在事件循环中创建一个任务对象并加入事件循环aty = main() # 启动yolov服务ysam = YunShenAutoMap() # 启动寻路类print(ysam)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_()) # 监听消息不关闭else:# 如果不是管理员,则请求以管理员权限重新运行程序ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)except Exception as err:if str(err).find("sys.exit")==-1:logger.error(traceback.format_exc())
2、 main动态布局、计时器触发
这些都是在main.py的MainWindow类的 __init__初始化函数下添加
1、一些变量和布局
vi main.py
from PyQt5.QtCore import Qtfrom PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QWidgetself.g_box = QGridLayout() #创建布局 这是一种可以将控件放置在网格单元格中的布局管理器self.container_widget = QWidget() # 创建了一个 QWidget 对象,这个部件将用于容纳你想要添加到滚动区域的所有控件self.container_widget.setLayout(self.g_box) # 将网格布局设置给中间部件,之前创建的 QGridLayout 设置为 QWidget 的布局#self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 布局 左上对齐self.g_box.setContentsMargins(0, 0, 0, 0) # 边距 为0则紧贴边缘#self.g_box.setAlignment(Qt.AlignTop)self.sa_main.setWidget(self.container_widget) # 将中间部件设置为QScrollArea的子部件#始终置顶窗口,除非删除或最小化self.setWindowFlags(Qt.WindowStaysOnTopHint)#一些基础变量self.row = 0self.column = -1self.run_times=1self.column_step=310# 所有数据self.datas = []
3、添加计时器
在class MainWindow(QMainWindow, Ui_mainWindow): 的init下面添加
from PyQt5.QtCore import Qt, QTimer# 创建一个计时器,用于延迟布局self.timer = QTimer(self)self.timer.setSingleShot(True) # 设置为单次触发self.timer.timeout.connect(self.update_layout)#根据窗口宽度动态调整布局#主要目的是动态调整布局,以适应窗口大小的变化# 通过计算每行可以容纳的组件数量# 并重新排列这些组件,可以使界面看起来更加整洁和美观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:passimport webbrowserdef 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_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.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)))
4、当前全量代码main.py
import ctypes
import os
import subprocess
import sys
import time
import traceback
import webbrowserfrom PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QWidget, QAction, QMessageBox, QMenu
import state
from auto import main
from wayfinding import *
from logger_module import logger
from jianchaupdate import get_var_data, get_updatetxt
from lanrentools.moni import find_child_window_handle, screen_widthfrom PyQt5.QtCore import QObject, pyqtSignal, Qtclass 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()from PyQt5.QtGui import QFont, QIcon, QKeySequence
from ui.main import Ui_mainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow
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)from PyQt5.QtCore import Qtfrom PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QWidgetself.g_box = QGridLayout() #创建布局 这是一种可以将控件放置在网格单元格中的布局管理器self.container_widget = QWidget() # 创建了一个 QWidget 对象,这个部件将用于容纳你想要添加到滚动区域的所有控件self.container_widget.setLayout(self.g_box) # 将网格布局设置给中间部件,之前创建的 QGridLayout 设置为 QWidget 的布局#self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 布局 左上对齐self.g_box.setContentsMargins(0, 0, 0, 0) # 边距 为0则紧贴边缘#self.g_box.setAlignment(Qt.AlignTop)self.sa_main.setWidget(self.container_widget) # 将中间部件设置为QScrollArea的子部件#始终置顶窗口,除非删除或最小化self.setWindowFlags(Qt.WindowStaysOnTopHint)#一些基础变量self.row = 0self.column = -1self.run_times=1self.column_step=310# 所有数据self.datas = []from PyQt5.QtCore import Qt, QTimer# 创建一个计时器,用于延迟布局self.timer = QTimer(self)self.timer.setSingleShot(True) # 设置为单次触发self.timer.timeout.connect(self.update_layout)#根据窗口宽度动态调整布局#主要目的是动态调整布局,以适应窗口大小的变化# 通过计算每行可以容纳的组件数量# 并重新排列这些组件,可以使界面看起来更加整洁和美观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 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()))if __name__ == '__main__':try:if ctypes.windll.shell32.IsUserAnAdmin():hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "YuanShenAi")if hwnd_cmd == 0:hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "懒人原神")# vardata = get_var_data()# if vardata != False:# updatetxt = get_updatetxt()# print(updatetxt)# print("当前版本号:" + state.版本号)## if float(vardata[1]) > float(state.版本号):# print(# "如果更新失败手动下更新包手动覆盖: https://gitee.com/LanRenZhiNeng/lanren-genshin-impact-ai/releases")# var = input(f"发现更新的版本 v{vardata[1]} 是否需要更新? (输入yes or no 默认更新)\n")# if var == "":# var = "yes"# if var.lower() != "no":# update_process = subprocess.Popen(f'update.exe "{vardata[0]}.exe" "{vardata[2]}"',# creationflags=subprocess.CREATE_NEW_CONSOLE)# time.sleep(1)# sys.exit()# 运行需要管理员权限的代码kernel32 = ctypes.windll.kernel32kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), 128)os.environ['PNG_IGNORE_WARNINGS'] = '1'# 在事件循环中创建一个任务对象并加入事件循环aty = main() # 启动yolov服务ysam = YunShenAutoMap() # 启动寻路类print(ysam)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_()) # 监听消息不关闭else:# 如果不是管理员,则请求以管理员权限重新运行程序ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)except Exception as err:if str(err).find("sys.exit")==-1:logger.error(traceback.format_exc())
三、ui窗口信号解析
设置信号链接及菜单(main)
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)from PyQt5.QtCore import Qtfrom PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QWidgetself.g_box = QGridLayout() #创建布局 这是一种可以将控件放置在网格单元格中的布局管理器self.container_widget = QWidget() # 创建了一个 QWidget 对象,这个部件将用于容纳你想要添加到滚动区域的所有控件self.container_widget.setLayout(self.g_box) # 将网格布局设置给中间部件,之前创建的 QGridLayout 设置为 QWidget 的布局#self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 布局 左上对齐self.g_box.setContentsMargins(0, 0, 0, 0) # 边距 为0则紧贴边缘#self.g_box.setAlignment(Qt.AlignTop)self.sa_main.setWidget(self.container_widget) # 将中间部件设置为QScrollArea的子部件#始终置顶窗口,除非删除或最小化self.setWindowFlags(Qt.WindowStaysOnTopHint)#一些基础变量self.row = 0self.column = -1self.run_times=1self.column_step=310# 所有数据self.datas = []from PyQt5.QtCore import Qt, QTimer# 创建一个计时器,用于延迟布局self.timer = QTimer(self)self.timer.setSingleShot(True) # 设置为单次触发self.timer.timeout.connect(self.update_layout)# 布局self.connect_set()def 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_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.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 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 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()))
上面添加了self.connect_set() 以及函数def connect_set(self):
设置信号槽
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)
1、添加自定义信号
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()
2、添加关机提示
guanjitishi.py
import os
import sys
from PyQt5.Qt import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *class ShutdownConfirmationDialog(QDialog):def __init__(self, parent=None):super().__init__(parent,Qt.Dialog | Qt.WindowStaysOnTopHint)self.initUI()def initUI(self):self.resize(300, 100)self.setWindowTitle('关机确认')self.confirmButton = QPushButton('确定', self)self.confirmButton.clicked.connect(self.shutdown)self.confirmButton.setGeometry(50, 50, 75, 30)self.cancelButton = QPushButton('取消', self)self.cancelButton.clicked.connect(self.cancelShutdown)self.cancelButton.setGeometry(150, 50, 75, 30)self.timerLabel = QLabel('倒计时:20', self)self.timerLabel.setGeometry(220, 10, 100, 30)self.timer = QTimer(self)self.timer.timeout.connect(self.countdown)self.secondsLeft = 20self.timer.start(1000)def countdown(self):if self.secondsLeft < 0:returnself.secondsLeft -= 1self.timerLabel.setText(f'倒计时:{self.secondsLeft}')if self.secondsLeft == 0:self.shutdown()def shutdown(self):os.system('shutdown -s -t 10')qApp.quit()# 调用关机命令def cancelShutdown(self):self.timer.stop()self.close()# if __name__ == '__main__':
# app = QApplication(sys.argv)
# dialog = ShutdownConfirmationDialog()
# dialog.show()
# sys.exit(app.exec_())
3、关机对话框、鼠标穿透、更新窗口标题、yolo
检测结果
#显示关机确认对话框def show_shutdown_dig(self):"""显示关机确认对话框。这个方法会从 `demo.ui.guanjitishi` 模块导入 `ShutdownConfirmationDialog` 类,创建一个对话框实例,并显示出来。使用方法:调用 `self.show_shutdown_dig()` 即可显示关机确认对话框。"""from demo.ui.guanjitishi import ShutdownConfirmationDialogself.dialog = ShutdownConfirmationDialog(self)self.dialog.show()#设置窗口的鼠标穿透属性,并调整窗口的透明度。def set_mouse_through(self, bool):"""设置窗口的鼠标穿透属性,并调整窗口的透明度。参数:- bool (bool): 如果为 True,则启用鼠标穿透;否则禁用。使用方法:调用 `self.set_mouse_through(True)` 启用鼠标穿透,并将窗口透明度设置为 0.9;调用 `self.set_mouse_through(False)` 禁用鼠标穿透,并将窗口透明度设置为 1。"""# 调用底层函数设置鼠标穿透set_mouse_through(int(self.winId()), bool)# 根据传入的布尔值调整窗口透明度if bool:self.setWindowOpacity(0.9)else:self.setWindowOpacity(1)#在状态栏显示提示信息,并根据全局状态更新窗口标题def set_tishi(self, txt):"""在状态栏显示提示信息,并根据全局状态更新窗口标题。参数:- txt (str): 要显示的提示信息。使用方法:调用 `self.set_tishi("提示信息")` 可以在状态栏显示提示信息,如果全局状态 `state.开关_是否展预测结果` 为 True,则更新窗口标题。"""# 在状态栏显示提示信息self.statusbar.showMessage(txt)# 如果全局状态允许显示预测结果,则更新窗口标题if state.开关_是否展预测结果:self.fromshow.setWindowTitle(txt)#显示工具项并执行快捷键操作。def next_pack(self):"""显示工具项并执行快捷键操作。使用方法:调用 `self.next_pack()` 可以显示 `state.PATH_TASK` 对应的工具项,并执行 `hotkey_runall` 方法。"""# 显示工具项self.show_tool_item(state.PATH_TASK)# 执行快捷键操作self.hotkey_runall()#显示路径图像def show_xunlu(self):"""显示路径图像。使用方法:调用 `self.show_xunlu()` 可以显示路径图像。如果全局状态 `state.开关_是否展预测结果` 为 True,并且 `state.图片_找图` 不为布尔值,则加载图像并显示在 `self.fromshow.lb_xunlu` 控件中。"""from PyQt5.QtGui import QFont, QIcon, QKeySequence, QImage, QPixmap# 检查是否需要显示预测结果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)#显示 YOLOv 检测结果图像def show_yolov(self):"""显示 YOLOv 检测结果图像。使用方法:调用 `self.show_yolov()` 可以显示 YOLOv 检测结果图像。如果全局状态 `state.开关_是否展预测结果` 为 True,并且 `state.图片_YOLOV` 不为布尔值,则加载图像并显示在 `self.fromshow.lb_yolov` 控件中。"""from PyQt5.QtGui import QFont, QIcon, QKeySequence, QImage, QPixmap# 检查是否需要显示预测结果if state.开关_是否展预测结果:if type(state.图片_YOLOV) == bool:return# 加载图像img1 = 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_xunlu.width() + self.fromshow.lb_yolov.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):"""定位滚动条到指定位置。参数:- idex (int): 要定位的数据索引。使用方法:调用 `self.dingwei(idex)` 可以将滚动条定位到指定位置。如果 `self.datas[idex]["f_item"]` 存在,则将其标记为非重点项,并调整滚动条位置。"""try:# 设置焦点项为非重点项,并清除鼠标按下事件self.datas[idex]["f_item"].is_zd = Falseself.datas[idex]["f_item"].mousePressEvent(None)# 调整滚动条位置self.v_scrollbar.setValue(self.datas[idex]["f_item"].y())except Exception as err:print("dingwei", err)pass
存量代码
import ctypes
import os
import subprocess
import sys
import time
import traceback
import webbrowserfrom PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QWidget, QAction, QMessageBox, QMenu
import state
from auto import mainfrom wayfinding import *
from logger_module import logger
from jianchaupdate import get_var_data, get_updatetxt
from lanrentools.moni import find_child_window_handle, screen_widthfrom PyQt5.QtCore import QObject, pyqtSignal, Qtclass 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()from PyQt5.QtGui import QFont, QIcon, QKeySequence, QImage, QPixmap
from ui.main import Ui_mainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow
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)from PyQt5.QtCore import Qtfrom PyQt5.QtWidgets import QApplication, QMainWindow, QGridLayout, QWidgetself.g_box = QGridLayout() #创建布局 这是一种可以将控件放置在网格单元格中的布局管理器self.container_widget = QWidget() # 创建了一个 QWidget 对象,这个部件将用于容纳你想要添加到滚动区域的所有控件self.container_widget.setLayout(self.g_box) # 将网格布局设置给中间部件,之前创建的 QGridLayout 设置为 QWidget 的布局#self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 布局 左上对齐self.g_box.setContentsMargins(0, 0, 0, 0) # 边距 为0则紧贴边缘#self.g_box.setAlignment(Qt.AlignTop)self.sa_main.setWidget(self.container_widget) # 将中间部件设置为QScrollArea的子部件#始终置顶窗口,除非删除或最小化self.setWindowFlags(Qt.WindowStaysOnTopHint)#一些基础变量self.row = 0self.column = -1self.run_times=1self.column_step=310# 所有数据self.datas = []from PyQt5.QtCore import Qt, QTimer# 创建一个计时器,用于延迟布局self.timer = QTimer(self)self.timer.setSingleShot(True) # 设置为单次触发self.timer.timeout.connect(self.update_layout)# 布局self.connect_set()#设置信号及菜单def 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_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.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 show_shutdown_dig(self):"""显示关机确认对话框。这个方法会从 `demo.ui.guanjitishi` 模块导入 `ShutdownConfirmationDialog` 类,创建一个对话框实例,并显示出来。使用方法:调用 `self.show_shutdown_dig()` 即可显示关机确认对话框。"""from demo.ui.guanjitishi import ShutdownConfirmationDialogself.dialog = ShutdownConfirmationDialog(self)self.dialog.show()#设置窗口的鼠标穿透属性,并调整窗口的透明度。def set_mouse_through(self, bool):"""设置窗口的鼠标穿透属性,并调整窗口的透明度。参数:- bool (bool): 如果为 True,则启用鼠标穿透;否则禁用。使用方法:调用 `self.set_mouse_through(True)` 启用鼠标穿透,并将窗口透明度设置为 0.9;调用 `self.set_mouse_through(False)` 禁用鼠标穿透,并将窗口透明度设置为 1。"""# 调用底层函数设置鼠标穿透set_mouse_through(int(self.winId()), bool)# 根据传入的布尔值调整窗口透明度if bool:self.setWindowOpacity(0.9)else:self.setWindowOpacity(1)#在状态栏显示提示信息,并根据全局状态更新窗口标题def set_tishi(self, txt):"""在状态栏显示提示信息,并根据全局状态更新窗口标题。参数:- txt (str): 要显示的提示信息。使用方法:调用 `self.set_tishi("提示信息")` 可以在状态栏显示提示信息,如果全局状态 `state.开关_是否展预测结果` 为 True,则更新窗口标题。"""# 在状态栏显示提示信息self.statusbar.showMessage(txt)# 如果全局状态允许显示预测结果,则更新窗口标题if state.开关_是否展预测结果:self.fromshow.setWindowTitle(txt)#显示工具项并执行快捷键操作。def next_pack(self):"""显示工具项并执行快捷键操作。使用方法:调用 `self.next_pack()` 可以显示 `state.PATH_TASK` 对应的工具项,并执行 `hotkey_runall` 方法。"""# 显示工具项self.show_tool_item(state.PATH_TASK)# 执行快捷键操作self.hotkey_runall()#显示路径图像def show_xunlu(self):"""显示路径图像。使用方法:调用 `self.show_xunlu()` 可以显示路径图像。如果全局状态 `state.开关_是否展预测结果` 为 True,并且 `state.图片_找图` 不为布尔值,则加载图像并显示在 `self.fromshow.lb_xunlu` 控件中。"""from PyQt5.QtGui import QFont, QIcon, QKeySequence, QImage, QPixmap# 检查是否需要显示预测结果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)#显示 YOLOv 检测结果图像def show_yolov(self):"""显示 YOLOv 检测结果图像。使用方法:调用 `self.show_yolov()` 可以显示 YOLOv 检测结果图像。如果全局状态 `state.开关_是否展预测结果` 为 True,并且 `state.图片_YOLOV` 不为布尔值,则加载图像并显示在 `self.fromshow.lb_yolov` 控件中。"""from PyQt5.QtGui import QFont, QIcon, QKeySequence, QImage, QPixmap# 检查是否需要显示预测结果if state.开关_是否展预测结果:if type(state.图片_YOLOV) == bool:return# 加载图像img1 = 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_xunlu.width() + self.fromshow.lb_yolov.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):"""定位滚动条到指定位置。参数:- idex (int): 要定位的数据索引。使用方法:调用 `self.dingwei(idex)` 可以将滚动条定位到指定位置。如果 `self.datas[idex]["f_item"]` 存在,则将其标记为非重点项,并调整滚动条位置。"""try:# 设置焦点项为非重点项,并清除鼠标按下事件self.datas[idex]["f_item"].is_zd = Falseself.datas[idex]["f_item"].mousePressEvent(None)# 调整滚动条位置self.v_scrollbar.setValue(self.datas[idex]["f_item"].y())except Exception as err:print("dingwei", err)pass#根据窗口宽度动态调整布局#主要目的是动态调整布局,以适应窗口大小的变化# 通过计算每行可以容纳的组件数量# 并重新排列这些组件,可以使界面看起来更加整洁和美观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 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()))if __name__ == '__main__':try:if ctypes.windll.shell32.IsUserAnAdmin():hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "YuanShenAi")if hwnd_cmd == 0:hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "懒人原神")# vardata = get_var_data()# if vardata != False:# updatetxt = get_updatetxt()# print(updatetxt)# print("当前版本号:" + state.版本号)## if float(vardata[1]) > float(state.版本号):# print(# "如果更新失败手动下更新包手动覆盖: https://gitee.com/LanRenZhiNeng/lanren-genshin-impact-ai/releases")# var = input(f"发现更新的版本 v{vardata[1]} 是否需要更新? (输入yes or no 默认更新)\n")# if var == "":# var = "yes"# if var.lower() != "no":# update_process = subprocess.Popen(f'update.exe "{vardata[0]}.exe" "{vardata[2]}"',# creationflags=subprocess.CREATE_NEW_CONSOLE)# time.sleep(1)# sys.exit()# 运行需要管理员权限的代码kernel32 = ctypes.windll.kernel32kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), 128)os.environ['PNG_IGNORE_WARNINGS'] = '1'# 在事件循环中创建一个任务对象并加入事件循环aty = main() # 启动yolov服务ysam = YunShenAutoMap() # 启动寻路类print(ysam)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_()) # 监听消息不关闭else:# 如果不是管理员,则请求以管理员权限重新运行程序ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)except Exception as err:if str(err).find("sys.exit")==-1:logger.error(traceback.format_exc())
4、主窗口所需
# hotkey_addtask 方法用于创建一个新的任务目录,并尝试加载该目录下的 jiaoben.ini 文件。
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()# 尝试读取新创建的任务目录中的 jiaoben.ini 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_task(dir_, config) # 添加任务到系统self.save_ini(dir_, self.datas[-1]) # 保存数据到 ini 文件except Exception as e:# 捕获异常并忽略pass# hotkey_addtaskjiaoben 方法用于添加一个脚本任务到指定目录。
def 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()# 尝试读取新创建的任务目录中的 jiaoben.ini 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_taskjiaoben(dir_, config) # 添加脚本任务到系统self.save_ini(dir_, self.datas[-1]) # 保存数据到 ini 文件# hotkey_qiejue 方法用于切换角色,并保存更改。
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()# 尝试读取新创建的任务目录中的 jiaoben.ini 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_xuanjue(dir_, config) # 添加角色选择到系统self.save_ini(dir_, self.datas[-1]) # 保存数据到 ini 文件# hotkey_qiehuanlianzhao 方法用于切换连招,并保存更改。
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()# 尝试读取新创建的任务目录中的 jiaoben.ini 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_xuanlianzhao(dir_, config) # 添加连招选择到系统self.save_ini(dir_, self.datas[-1]) # 保存数据到 ini 文件# hotkey_addtaskfuben 方法用于添加副本任务到指定目录。
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()# 尝试读取新创建的任务目录中的 jiaoben.ini 文件config.read(os.path.join(dir_, "jiaoben.ini"))self.add_taskfuben(dir_, config) # 添加副本任务到系统self.save_ini(dir_, self.datas[-1]) # 保存数据到 ini 文件# hotkey_opentaskdir 方法用于打开任务目录。
def hotkey_opentaskdir(self):os.startfile(os.path.abspath(state.PATH_TASK)) # 使用startfile方法打开文件夹# hotkey_selecttaskdir 方法用于让用户选择一个任务目录,并更新状态。
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}为当前任务文件夹")# hotkey_setlianzhao 方法用于设置连招脚本。
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 Exception as e:passlogger.info("选择连招脚本成功!")self.save_ini_seting()# hotkey_addlianzhao 方法用于添加连招(通过录制或者从文件中选择)。
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 or text == "":returnif text[-4:] != ".txt":state.LIANZHAO = text + ".txt"else:state.LIANZHAO = textlogger.info("可以开始录制了,按F8开始/停止")self.sg.mysig_tishi.emit("可以开始录制了,按F8开始/停止")state.状态_是否禁止录制 = Falsestate.状态_是否开始录制 = Falsestate.录制_脚本文本 = ""asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否禁止录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否开始录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局脚本名#@@#{state.LIANZHAO.replace('.txt','')}"), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局hwnd#@@#{hwnd}"), auto.loop)self.timer_luzhi_lianzhao.start(200)except Exception as e: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}"asyncio.run_coroutine_threadsafe(send_to_client(-1, message), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄set_window_activate(hwnd)asyncio.run_coroutine_threadsafe(send_to_client(-1, "脚本执行#@@#1"), auto.loop)self.timer_huifang.start(200)elif result == QMessageBox.Warning:self.hotkey_setlianzhao() # 如果选择了警告按钮,则重新设置连招
额,太多了,后面我们执行到哪里写哪里吧
5、非主窗口函数和类
vi main.py
def extract_number(folder_name):numbers = re.findall(r'\d+', folder_name)return int(numbers[0]) if numbers else float('inf')
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 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(username="lanren",password="lanrenai2024")# 创建一个计时器,用于延迟布局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()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
这里开始包含了好几个ui文件,我们直接把ui目录覆盖成原项目的
6、stitchimages.py
lanrentools/stitchimages.py
# -*- coding: utf-8 -*-
import os
import cv2
import numpy as np
# pip install opencv-contrib-python
class StitchImages:def __init__(self,):'''全景图合成类'''passdef stitch_images(self,image_paths,out_path="",isShow=False):# 创建 Stitcher 对象stitcher = cv2.Stitcher_create()images = [cv2.imdecode(np.fromfile(file=path, dtype=np.uint8), cv2.IMREAD_COLOR) for path in image_paths]# 调用 Stitcher 进行拼接status, stitched_image = stitcher.stitch(images)# 检查拼接是否成功if status == cv2.Stitcher_OK:# 保存拼接后的全景图cv2.imwrite(out_path, stitched_image)print('全景图拼接成功,并已保存为 '+out_path)else:print('全景图拼接失败')return Falseif isShow:cv2.imshow('Panorama', stitched_image)cv2.waitKey(0)cv2.destroyAllWindows()return Truedef get_image_paths(self,dir="./"):image_paths=[]#遍历一个文件夹 ['.png','.jpg','.bmp']找出符合这个的文件加入到image_paths中for root, dirs, files in os.walk(dir):for file in files:if file.endswith('.png') or file.endswith('.jpg') or file.endswith('.bmp'):image_paths.append(os.path.join(root, file))return image_paths
if __name__ == '__main__':si=StitchImages()image_paths=si.get_image_paths("./datas/img")si.stitch_images(image_paths,"./datas/max_map/max_map.png")
7、yunpan
vi yunpan.py
import timeimport requests
import jsonclass YunPan():def __init__(self):self.token=""self.url=""def login(self,username="",password=""):return {}def get_file_list(self,dir_home="鸣潮AI"):return []return []def get_file_get(self,file_name=""):return {}def get_file_all(self,dir_="原神AI",file_data=[],isclose=False):'''递归遍历所有的文件:param dir_:目录:param file_data: 上一次的数据:param isclose:用来强制重置数据的 防止重复:return:'''file_data=[]
main全量代码
# -*- coding: utf-8 -*-
try:import asyncioimport functoolsimport os.pathfrom datetime import datetimeimport configparserimport reimport shutilimport timeimport threadingimport webbrowserimport pyautoguifrom qtpy import QtWidgetsfrom logger_module import loggerfrom lanrentools.moni import *import autoimport sysimport statefrom wayfinding import *from PyQt5.Qt import *from PyQt5.QtGui import *from PyQt5.QtCore import *from ui.formitemjiaoben import Ui_formitemjiaobenfrom ui.guanjitishi import ShutdownConfirmationDialogfrom ui.main import Ui_mainWindowfrom ui.formitem import Ui_formitemfrom ui.formitemfuben import Ui_formitemfubenfrom ui.formshow import Ui_DockWidgetfrom ui.yunfilelist import Ui_form_yunfilelistfrom ui.formitemyun import Ui_formitemyunfrom ui.formitemxuanjue import Ui_formitemxuanjuefrom ui.formitemlianzhao import Ui_formitemlianzhaofrom ui.dialogchuansong import Ui_dialogchuansongfrom ui.formm import Ui_form_mfrom PyQt5.QtWidgets import QMessageBoxfrom lanrentools.stitchimages import *from yunpan import YunPanfrom jianchaupdate import get_var_data, get_updatetxt
except:logger.error(traceback.format_exc())def extract_number(folder_name):numbers = re.findall(r'\d+', folder_name)return int(numbers[0]) if numbers else float('inf')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()
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
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"]asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否开始录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否禁止录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局脚本名#@@#传送-{state.录制_当前脚本名}"), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局hwnd#@@#{hwnd}"), auto.loop)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}"asyncio.run_coroutine_threadsafe(send_to_client(-1, message), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄set_window_activate(hwnd)asyncio.run_coroutine_threadsafe(send_to_client(-1, "脚本执行#@@#1"), auto.loop)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 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(username="lanren",password="lanrenai2024")# 创建一个计时器,用于延迟布局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()
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) if os.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)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.录制_脚本文本!="":asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否禁止录制#@@#真"), auto.loop)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.录制_脚本文本 != "":asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否禁止录制#@@#真"), auto.loop)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.录制_脚本文本!="":asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否禁止录制#@@#真"), auto.loop)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.状态_需重新传送 = Falseasyncio.run_coroutine_threadsafe(send_to_client(-1, "是否回放#@@#假"), auto.loop)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_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.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 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 show_shutdown_dig(self):self.dialog = ShutdownConfirmationDialog(self)self.dialog.show()def set_mouse_through(self, bool):set_mouse_through(int(self.winId()), bool)if bool:self.setWindowOpacity(0.9)else:self.setWindowOpacity(1)def set_tishi(self, txt):self.statusbar.showMessage(txt)if state.开关_是否展预测结果:self.fromshow.setWindowTitle(txt)def next_pack(self):self.show_tool_item(state.PATH_TASK)self.hotkey_runall()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 = Falseself.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_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_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"]asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否禁止录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否开始录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局脚本名#@@#{state.录制_当前脚本名}"), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局hwnd#@@#{hwnd}"), auto.loop)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}"asyncio.run_coroutine_threadsafe(send_to_client(-1, message), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄set_window_activate(hwnd)asyncio.run_coroutine_threadsafe(send_to_client(-1, "脚本执行#@@#1"), auto.loop)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 atyshwnd = 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 = self.run(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:aty.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 run(self, idex):global atyif not state.状态_YOLOV:logger.info("还在启动相关服务中..请稍等")return Falsedir_ = 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 Falseif state.状态_已经有寻路了:logger.info("请勿重复启动!已经有任务在运行了")self.sg.mysig_tishi.emit("请勿重复启动!已经有任务在运行了")# 弹出提示,不要重复开return Falsestate.计数_没找到任何目标 = 0state.计数_没找到怪物 = 0state.状态_在爬墙 = Falsestate.状态_需重新传送 = Falsestate.状态_循环开关 = Truestate.状态_传送中 = Truehwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄message = f"全局hwnd#@@#{hwnd}"asyncio.run_coroutine_threadsafe(send_to_client(-1, message), auto.loop)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 = aty.处理异常情况(hwnd,0,0,1920,1080,p_left,p_top)if kkk == 0:logger.info("在意外界面 超时!")time.sleep(3)state.状态_需重新传送 = Falsestate.状态_已经有寻路了 = Falsereturn Falseelif kkk == -1:logger.info("全军覆没了!")time.sleep(3)state.状态_需重新传送 = Truestate.状态_已经有寻路了 = Falsereturn Falseif 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# 运行传送脚本动作jiaoben = os.path.abspath(os.path.join(dir_, self.datas[idex]["chuansong"]))ret = auto.atys.run_chuansongjiaoben(jiaoben,self.datas[idex]['cbb_address'])if ret == False:logger.info("执行传送脚本!失败")return False# 传送模板 点击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 Falseelse:logger.info("没发现传送脚本,不传送")state.状态_传送中 = Falsestate.计数_没找到任何目标 = 0state.计数_没找到怪物 = 0state.计数_连招次数 = 0state.状态_已经有寻路了 = Trueif self.datas[idex]["type"] == "2":return aty.run_fuben(int(self.datas[idex]['f_item'].led_cishu.text()),self.datas[idex]['f_item'].cb_isfanxiang.isChecked())elif self.datas[idex]["type"] == "3":return aty.run_jiaoben(os.path.abspath(os.path.join(dir_, self.datas[idex]["jiaoben"])),self.datas[idex]['f_item'].cb_auto_f.isChecked())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 aty.run_huanjue(names,self.datas[idex]['f_item'].led_main.text())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 Trueelse:return Falseelse:t2 = threading.Thread(target=aty.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())except:state.状态_需重新传送 = Falsestate.状态_已经有寻路了 = Falsereturn Falsedef 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(),}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"))config.read(os.path.join(dir_, "jiaoben.ini"))self.add_task(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.录制_脚本文本 = ""asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否禁止录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, "是否开始录制#@@#假"), auto.loop)asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局脚本名#@@#{state.LIANZHAO.replace('.txt','')}"), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄asyncio.run_coroutine_threadsafe(send_to_client(-1, f"全局hwnd#@@#{hwnd}"), auto.loop)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}"asyncio.run_coroutine_threadsafe(send_to_client(-1, message), auto.loop)hwnd = win32gui.FindWindow("UnityWndClass", state.GAME_TITLE) # 替换成你实际的窗口句柄set_window_activate(hwnd)asyncio.run_coroutine_threadsafe(send_to_client(-1, "脚本执行#@@#1"), auto.loop)self.timer_huifang.start(200)elif result == QMessageBox.Warning:self.hotkey_setlianzhao()def save_ini_seting(self):try:# 创建 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()),'ON_SHUTDOWN': str(state.ON_SHUTDOWN),'ON_JIXING': str(state.ON_JIXING),'ON_NEXTPACK':str(state.ON_NEXTPACK),'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 atyshwnd = 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 = self.run(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:aty.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_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 Trueif __name__ == '__main__':try:if ctypes.windll.shell32.IsUserAnAdmin():hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "YuanShenAi")if hwnd_cmd == 0:hwnd_cmd = find_child_window_handle(0, "ConsoleWindowClass", "懒人原神")vardata = get_var_data()if vardata != False:updatetxt = get_updatetxt()print(updatetxt)print("当前版本号:" + state.版本号)if float(vardata[1]) > float(state.版本号):print("如果更新失败手动下更新包手动覆盖: https://gitee.com/LanRenZhiNeng/lanren-genshin-impact-ai/releases")var = input(f"发现更新的版本 v{vardata[1]} 是否需要更新? (输入yes or no 默认更新)\n")if var == "":var = "yes"if var.lower() != "no":update_process = subprocess.Popen(f'update.exe "{vardata[0]}.exe" "{vardata[2]}"',creationflags=subprocess.CREATE_NEW_CONSOLE)time.sleep(1)sys.exit()# 运行需要管理员权限的代码kernel32 = ctypes.windll.kernel32kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), 128)os.environ['PNG_IGNORE_WARNINGS'] = '1'# 在事件循环中创建一个任务对象并加入事件循环aty = main() # 启动yolov服务ysam = YunShenAutoMap() # 启动寻路类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_()) # 监听消息不关闭else:# 如果不是管理员,则请求以管理员权限重新运行程序ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)except Exception as err:if str(err).find("sys.exit")==-1:logger.error(traceback.format_exc())
未完待续
相关文章:

yolo自动化项目实例解析(二)ui页面整理 1.78
我们在上一章整理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 # 分辨率比例# 设…...

PyQt / PySide + Pywin32 + ctypes 自定义标题栏窗口 + 完全还原 Windows 原生窗口边框特效项目
项目地址: GitHub - github201014/PyQt-NativeWindow: A class of window include nativeEvent, use PySide or PyQt and Pywin32 and ctypesA class of window include nativeEvent, use PySide or PyQt and Pywin32 and ctypes - github201014/PyQt-NativeWindow…...
面试时遇见的项目问题
汽车在线销售平台项目 项目的甲方是谁? 甲方是一家汽车销售公司,他们希望通过互联网技术提升销售效率和服务质量 为什么要做这个项目? 很多消费者越来越倾向于在线上完成购车之前的大部分决策。所以甲方找到我们希望通过建立一个在线的销…...

在线骑行网站设计与实现
摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装在线骑行网站软件来发挥其高效地信息处理的作用,…...
大批量查询方案简记(Mybatis流式查询)
Mybatis的流式查询 摘要: 介绍使用mybatis流式查询解决大数据量查询问题. 1 业务背景 开发中遇到一个业务,说起来也很无奈:公司用的数据库MySQL,一张表里只保留了一个月的数据,但是数据量竟然高达2000W还要多,然后用户有个需求也很恶心,为了完成这个业务我需要定时任务每一个月…...

python - 子类为什么调用父类的方法
菜鸟教程 - 面向对象https://www.runoob.com/python3/python3-class.html为什么写这个呢 ,因为很多时候,事情很简单,但我往往记住了使用方式,忘记了使用原因,也因为自己看到super()时,也想问为什么要用supe…...

【JavaScript】数据结构之字典 哈希表
字典 键值对存储的,类似于js的对象,但在js对象中键[key]都是字符串类型或者会转换成字符串类型,因此后声明的键值会覆盖之前声明的值。字典以map表示,map的键不会转换类型。 let map new Map() map.set(a, 1) map.set(b, 2) ma…...

Adobe出现This unlicensed Photoshop app has been disabled
Adobe Acrobat或Photoshop软件突然出现This unlicensed Photoshop app has been disabled 症状 解决方法 删除软件安装目录下的AcroCEF和acrocef_1l两个子文件夹。主要是为了删除AcroCEF.exe。 如果存在复发,则删除xxxxxxx\AdobeGCClient\AdobeGCClient.exe。 不…...
elementui 单元格添加样式的两种方法
方法一 <el-table-column fixed prop"name" label"姓名" width"120"> <<template scope"scope"> <span :class"{red:scope.row.color1,yell:scope.row.color2,green:scope.row.col…...
如何有效管理技术债务:IT项目中的长期隐患
如何有效管理技术债务:IT项目中的长期隐患 在软件开发和IT项目管理中,技术债务(Technical Debt)是一个经常被忽视却又至关重要的概念。技术债务就像金融债务一样,当我们在项目开发中选择了某些“捷径”来快速交付&…...

2024 “华为杯” 中国研究生数学建模竞赛(D题)深度剖析|大数据驱动的地理综合问题|数学建模完整代码+建模过程全解全析
当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题! CS团队倾注了大量时间和心血,深入挖掘解…...
Linux 清空redis缓存及查询key值
1.登录redis redis-cli -h 127.0.0.1 -p 6379# 如果有密码需要下面这一步 auth 你的密码直接带密码登录 redis-cli -h 127.0.0.1 -p 6379 -a 密码出现ok表示登录成功 2.标题查看所有key keys *3.查看某个key 的值 get keyName4.清空整个Redis服务器的数据 flushall5.查看…...

MySql调优(三)Query SQL优化(2)explain优化
explain执行计划出现以下情况,均需要优化: 一、Using temporary 查询执行过程中出现Using temporary提示,通常意味着MySQL需要创建一个临时表来存储中间结果。这种情况多发生在数据库优化器无法通过现有的索引直接有效地执行查询时…...

Java【代码 18】处理Word文档里的Excel表格数据(源码分享)
处理Word文档里的Excel表格数据 1.原始数据2.处理程序2.1 识别替换表格表头2.2 处理多余的换行符2.3 处理后的结果 3.总结 1.原始数据 Word 文档里的 Excel 表格数据,以下仅为示例数据: 读取后的字符串数据为: "姓名\r\n身份证号\r\n手…...

21、Tomato
难度 低(个人认为中) 目标 root权限 一个flag 使用VMware启动 kali 192.168.152.56 靶机 192.168.152.66 信息收集 端口信息收集 可以看到有个ftp服务,2211实际是ssh协议端口,80、8888是一个web服务 web测试 80端口显示一个tomato 查看源码给了一些…...
代码随想录 八股文训练营40天总结
参加训练营的话也是给自己一定的约束力,让自己能够定期去对八股文进行一个背诵,虽然说中间有几天放假,没有进行打卡外,还是比较完整的坚持下来了。 从计算机网络--操作系统--MySQL--Redis--C基础,虽然这些知识都有看过…...

Debian 12上安装google chrome
当前系统:Debian 12.7 昨天在Debian 12.7上安装Google Chrome时,可能由于网络原因,导入公钥始终失败。 导致无法正常使用命令#apt install google-chrome-stable来安装google chrome; 解决办法: Step1.下载当前google chrome稳…...

Python | Leetcode Python题解之第405题数字转换为十六进制数
题目: 题解: CONV "0123456789abcdef" class Solution:def toHex(self, num: int) -> str:ans []# 32位2进制数,转换成16进制 -> 4个一组,一共八组for _ in range(8):ans.append(num%16)num // 16if not num:b…...
定位坐标系
定位坐标系是地理空间信息系统中用于确定物体位置的重要工具,它基于数学和物理原理,通过一系列参数来描述物体在地球或其他天体表面的位置。以下是对定位坐标系的详细解析: 一、定义与分类 定位坐标系是根据一定的规则和方法,将…...
安全通信网络等保
通用要求 1.网络架构 1)应保证网络设备的业务处理能力满足业务高峰期需要。 设备CPU和内存使用率的峰值不大于设备处理能力的70%。 在有监控环境的条件下,应通过监控平台查看主要设备在业务高峰期的资源(CPU、内存等)使用 情况;在无监控环境的情况下,在业务高峰期登录…...
硬件学习笔记--65 MCU的RAM及FLash简介
MCU(微控制器单元)内部的 RAM 和 Flash 是最关键的两种存储器,它们直接影响MCU的性能、功耗和编程方式。以下是它们的详细讲解及作用: 1. RAM(随机存取存储器) 1.1 特性 1)易失性:…...
【python爬虫】利用代理IP爬取filckr网站数据
亮数据官网链接:亮数据官网...

利用 Scrapy 构建高效网页爬虫:框架解析与实战流程
目录 前言1 Scrapy 框架概述1.1 Scrapy 的核心优势1.2 Scrapy 的典型应用场景 2 Scrapy 工作原理解析2.1 框架结构图2.2 Spider:定义数据采集策略2.3 Scheduler:调度请求与去重2.4 Downloader:网页下载器2.5 Item:结构化数据容器2…...

一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录——4. 配置服务器终端环境 zsh , oh my zsh, vim
前言 通过前面几篇文章,我们顺利的 安装了 ubuntu server 服务器,并且配置好了 ssh 免密登录服务器,也安装好了 服务器常用软件安装,接下来,我们要仔细的配置一下我们的终端环境,让服务器的终端更加好用。 一般情况下…...
python直方图
在Python中,绘制直方图(Histogram)是一项非常常见的任务,通常用于数据可视化,以展示数据的分布情况。Python中有多种库可以绘制直方图,其中最常用的两个库是Matplotlib和Seaborn。此外,Pandas库…...
day45 python预训练模型
目录 知识点回顾 1. 预训练的概念 2. 常见的分类预训练模型 3. 图像预训练模型的发展史 4. 预训练的策略 5. 预训练代码实战:ResNet18 作业:在 CIFAR-10 上对比 AlexNet 预训练模型 实验结果对比 在深度学习领域,预训练模型已经成为了…...

mac下通过anaconda安装Python
本次分享mac下通过anaconda安装Python、Jupyter Notebook、R。 anaconda安装 点击👉https://www.anaconda.com/download, 点击Mac系统安装包, 选择Mac芯片:苹果芯片 or intel芯片, 选择苹果芯片图形界面安装&#x…...

分布式锁优化:使用Lua脚本保证释放锁的原子性问题
分布式锁优化(二):使用Lua脚本保证释放锁的原子性问题 💻黑马视频链接:Lua脚本解决多条命令原子性问题 在上一章节视频实现了一个可用的Redis分布式锁,采用SET NX EX命令实现互斥和过期自动释放机制&…...

贪心算法应用:欧拉路径(Fleury算法)详解
Java中的贪心算法应用:欧拉路径(Fleury算法)详解 一、欧拉路径与欧拉回路基础 1.1 基本概念 欧拉路径(Eulerian Path)是指在一个图中,经过图中每一条边且每一条边只经过一次的路径。如果这条路径的起点和…...
基于多尺度卷积和扩张卷积-LSTM的多变量时间序列预测
时间序列预测是机器学习和数据分析中的重要领域,广泛应用于金融、气象、交通等领域。本文将介绍一种结合多尺度卷积、扩张卷积和LSTM的混合神经网络模型,用于多变量时间序列预测,并提供完整的代码实现和详细讲解。 1. 模型架构概述 我们提出的模型结合了三种强大的神经网络…...