|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import sys | 
					
						
							|  |  |  |  | import pandas as pd | 
					
						
							|  |  |  |  | from PyQt5 import QtWidgets | 
					
						
							|  |  |  |  | from PyQt5.QtCore import Qt | 
					
						
							|  |  |  |  | from PyQt5.Qt import * | 
					
						
							|  |  |  |  | from PyQt5.QtWidgets import QApplication, QMainWindow, QStackedWidget, QMessageBox, QStackedWidget, QTabWidget, QFileDialog, QPushButton, QGraphicsDropShadowEffect | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | from PyQt5.QtCore import QSize | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | from ctypes import POINTER, cast | 
					
						
							|  |  |  |  | from ctypes.wintypes import MSG | 
					
						
							|  |  |  |  | from win32 import win32api, win32gui | 
					
						
							|  |  |  |  | from win32.lib import win32con | 
					
						
							|  |  |  |  | from model.ProjectModel.VarManage import GlobalVarManager | 
					
						
							|  |  |  |  | from UI.Main.MainLeft import MainLeft | 
					
						
							|  |  |  |  | from UI.Main.MainTop import MainTop | 
					
						
							|  |  |  |  | from ..ProjectManages.ProjectWidget import ProjectWidgets | 
					
						
							|  |  |  |  | from ..VarManages.VarWidget import VarWidgets, HartWidgets, TcRtdWidgets, AnalogWidgets, HartSimulateWidgets | 
					
						
							|  |  |  |  | from UI.VarManages.VarTable import RpcVarTableView | 
					
						
							|  |  |  |  | from ..UserManage.UserWidget import UserWidgets | 
					
						
							|  |  |  |  | from ..TrendManage.TrendWidget import TrendWidgets | 
					
						
							|  |  |  |  | from ..Setting.Setting import SettingWidget | 
					
						
							|  |  |  |  | from model.ClientModel.Client import Client | 
					
						
							|  |  |  |  | from utils import Globals | 
					
						
							|  |  |  |  | from utils.DBModels.InitParameterDB import InitParameterDB | 
					
						
							|  |  |  |  | from UI.ProfibusWidgets.ProfibusWindow import ProfibusWidgets | 
					
						
							|  |  |  |  | from UI.ProcedureManager.ProcedureManager import ProcedureManager | 
					
						
							|  |  |  |  | from UI.ControlManage.ControlWidget import getControlWidget | 
					
						
							|  |  |  |  | import qtawesome | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | class CommonHelper: | 
					
						
							|  |  |  |  |     def __init__(self): | 
					
						
							|  |  |  |  |         pass | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     @staticmethod | 
					
						
							|  |  |  |  |     def readQss(style): | 
					
						
							|  |  |  |  |         with open(style, "r", encoding='utf-8') as f: | 
					
						
							|  |  |  |  |             return f.read() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | class MainWindow(QMainWindow): | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     BORDER_WIDTH = 5 #设圆角 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def __init__(self): | 
					
						
							|  |  |  |  |         super(MainWindow, self).__init__() | 
					
						
							|  |  |  |  |         InitParameterDB() | 
					
						
							|  |  |  |  |         self.setupUi() | 
					
						
							|  |  |  |  |         # self.setStyleSheet(CommonHelper.readQss('Static/main.qss')) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowSystemMenuHint) | 
					
						
							|  |  |  |  |         self.SHADOW_WIDTH = 0  #边框距离 | 
					
						
							|  |  |  |  |         self.isLeftPressDown = False #鼠标左键是否按下 | 
					
						
							|  |  |  |  |         self.dragPosition = 0   #拖动时坐标 | 
					
						
							|  |  |  |  |         self.padding = 4 | 
					
						
							|  |  |  |  |         self.Numbers = self.enum(UP=0, DOWN=1, LEFT=2, RIGHT=3, LEFTTOP=4, LEFTBOTTOM=5, RIGHTBOTTOM=6, RIGHTTOP=7, NONE=8) #枚举参数 | 
					
						
							|  |  |  |  |         self.setMinimumHeight(900) #窗体最小高度 | 
					
						
							|  |  |  |  |         self.setMinimumWidth(1600) #窗体最小宽度 | 
					
						
							|  |  |  |  |         self.dir = self.Numbers.NONE #初始鼠标状态 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #开启鼠标追踪 | 
					
						
							|  |  |  |  |         self.setMouseTracking(True) | 
					
						
							|  |  |  |  |         self.centralwidget.setMouseTracking(True) | 
					
						
							|  |  |  |  |         self.leftWidget.setMouseTracking(True) | 
					
						
							|  |  |  |  |         self.rightWidget.setMouseTracking(True) | 
					
						
							|  |  |  |  |         self.topWidget.setMouseTracking(True) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         Globals.setValue('MainWindows', self) #设置全局变量 | 
					
						
							|  |  |  |  |         #初始化接口 | 
					
						
							|  |  |  |  |         # self.windowEffect = WindowEffect() | 
					
						
							|  |  |  |  |         # # 添加DWM阴影效果 | 
					
						
							|  |  |  |  |         # self.windowEffect.addWindowAnimation(self.winId()) | 
					
						
							|  |  |  |  |         # self.windowEffect.addShadowEffect(self.winId()) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         # 解决报错 | 
					
						
							|  |  |  |  |         self.windowHandle().screenChanged.connect(self.__onScreenChanged) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def setupUi(self): | 
					
						
							|  |  |  |  |         self.showMaximized() | 
					
						
							|  |  |  |  |         self.centralwidget = QtWidgets.QWidget(self) | 
					
						
							|  |  |  |  |         self.centralwidget.setObjectName("centralwidget") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.leftWidget = MainLeft() | 
					
						
							|  |  |  |  |         self.leftWidget.setObjectName("leftWidget") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.projectWidget = ProjectWidgets() | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.rightWidget = QStackedWidget() | 
					
						
							|  |  |  |  |         self.rightWidget.setObjectName("rightWidget") | 
					
						
							|  |  |  |  |         self.rightWidget.addWidget(self.projectWidget) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         #添加导入变量按钮 | 
					
						
							|  |  |  |  |         self.importVarButton = QPushButton('导入变量') | 
					
						
							|  |  |  |  |         self.importVarButton.setIcon(qtawesome.icon('fa5s.file-import', color = '#059669')) | 
					
						
							|  |  |  |  |         self.importVarButton.setObjectName('importBtn') | 
					
						
							|  |  |  |  |         self.importVarButton.setIconSize(QSize(22, 22)) | 
					
						
							|  |  |  |  |         self.importVarButton.setFlat(True) | 
					
						
							|  |  |  |  |         self.importVarButton.clicked.connect(self.loadVar) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.createWidgets()       | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.setCentralWidget(self.centralwidget) | 
					
						
							|  |  |  |  |         self.setWindowOpacity(0.995) # 设置窗口透明度 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.topWidget = MainTop(self) | 
					
						
							|  |  |  |  |         self.topWidget.setObjectName('topWidget') | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         # 初始化搜索框状态(在topWidget创建后) | 
					
						
							|  |  |  |  |         self.topWidget.updateSearchPlaceholder() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) | 
					
						
							|  |  |  |  |         self.horizontalLayout = QtWidgets.QHBoxLayout() | 
					
						
							|  |  |  |  |         self.horizontalLayout.setObjectName("horizontalLayout") | 
					
						
							|  |  |  |  |         self.verticalLayout.setObjectName("verticalLayout") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.horizontalLayout.addWidget(self.leftWidget) | 
					
						
							|  |  |  |  |         self.horizontalLayout.addWidget(self.rightWidget) | 
					
						
							|  |  |  |  |         self.horizontalLayout.setStretch(0, 1) | 
					
						
							|  |  |  |  |         self.horizontalLayout.setStretch(1, 10) | 
					
						
							|  |  |  |  |         self.horizontalLayout.setContentsMargins(0, 0, 0, 0) | 
					
						
							|  |  |  |  |         self.horizontalLayout.setSpacing(1) | 
					
						
							|  |  |  |  |         self.verticalLayout.setContentsMargins(0, 0, 0, 0) | 
					
						
							|  |  |  |  |         self.verticalLayout.addWidget(self.topWidget) | 
					
						
							|  |  |  |  |         self.verticalLayout.addLayout(self.horizontalLayout) | 
					
						
							|  |  |  |  |         self.verticalLayout.setStretch(0, 1) | 
					
						
							|  |  |  |  |         self.verticalLayout.setStretch(1, 18) | 
					
						
							|  |  |  |  |         self.verticalLayout.setSpacing(0) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         # self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明 | 
					
						
							|  |  |  |  |         self.setWindowFlag(Qt.FramelessWindowHint) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         # 添加阴影效果(接近Windows原生) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         # 添加圆角(QSS) | 
					
						
							|  |  |  |  |         # self.centralwidget.setStyleSheet("") | 
					
						
							|  |  |  |  |     def createWidgets(self): | 
					
						
							|  |  |  |  |         self.ModbusTcpMasterWidget = VarWidgets('ModbusTcpMaster') | 
					
						
							|  |  |  |  |         self.ModbusTcpSlaveWidget = VarWidgets('ModbusTcpSlave') | 
					
						
							|  |  |  |  |         self.ModbusRtuMasterWidget = VarWidgets('ModbusRtuMaster') | 
					
						
							|  |  |  |  |         self.ModbusRtuSlaveWidget = VarWidgets('ModbusRtuSlave') | 
					
						
							|  |  |  |  |         self.userWidget = UserWidgets() | 
					
						
							|  |  |  |  |         self.procedureManagerWidget = ProcedureManager() | 
					
						
							|  |  |  |  |         self.controlWidget = getControlWidget() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         modbusWidgetList = [self.ModbusTcpMasterWidget, self.ModbusTcpSlaveWidget, self.ModbusRtuMasterWidget, self.ModbusRtuSlaveWidget] | 
					
						
							|  |  |  |  |         modbusNameList = ['MODBUSTCP主站', 'MODBUSTCP从站', 'MODBUSRTU主站', 'MODBUSRTU从站',] | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |              | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.profibusWidget = ProfibusWidgets() | 
					
						
							|  |  |  |  |         self.trendWidget = TrendWidgets() | 
					
						
							|  |  |  |  |         self.SettingWidget = SettingWidget() | 
					
						
							|  |  |  |  |         self.hartWidget = HartWidgets() | 
					
						
							|  |  |  |  |         self.tcrtdWidget = TcRtdWidgets() | 
					
						
							|  |  |  |  |         self.analogWidget = AnalogWidgets() | 
					
						
							|  |  |  |  |         self.hartsimulateWidget = HartSimulateWidgets() | 
					
						
							|  |  |  |  |         self.rpcVarTableWidget = RpcVarTableView() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.userWidget.setObjectName('userWidget') | 
					
						
							|  |  |  |  |         self.projectWidget.setObjectName('projectWidget') | 
					
						
							|  |  |  |  |         self.trendWidget.setObjectName('trendWidget') | 
					
						
							|  |  |  |  |         # self.ModBusWidget.setObjectName('varWidget') | 
					
						
							|  |  |  |  |         self.analogWidget.setObjectName('analogWidget') | 
					
						
							|  |  |  |  |         self.hartsimulateWidget.setObjectName('hartsimulateWidget') | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.varManageTabWidget = QTabWidget() | 
					
						
							|  |  |  |  |         self.varManageTabWidget.setObjectName("varManageTabWidget") | 
					
						
							|  |  |  |  |         self.varManageTabWidget.tabBar().setObjectName('varManageTabBar') | 
					
						
							|  |  |  |  |         for widget, name in zip(modbusWidgetList, modbusNameList): | 
					
						
							|  |  |  |  |             widget.setObjectName('varWidget') | 
					
						
							|  |  |  |  |             self.varManageTabWidget.addTab(widget, name) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.varManageTabWidget.addTab(self.analogWidget,'IO') | 
					
						
							|  |  |  |  |         self.varManageTabWidget.addTab(self.tcrtdWidget,'TCRTD') | 
					
						
							|  |  |  |  |         self.varManageTabWidget.addTab(self.hartWidget,'HART读取') | 
					
						
							|  |  |  |  |         self.varManageTabWidget.addTab(self.hartsimulateWidget,'HART模拟') | 
					
						
							|  |  |  |  |         self.varManageTabWidget.addTab(self.profibusWidget,'PROFIBUS') | 
					
						
							|  |  |  |  |         self.varManageTabWidget.addTab(self.rpcVarTableWidget, '远程通讯') | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.varManageTabWidget.setCornerWidget(self.importVarButton) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.rightWidget.addWidget(self.varManageTabWidget) | 
					
						
							|  |  |  |  |         self.rightWidget.addWidget(self.trendWidget) | 
					
						
							|  |  |  |  |         self.rightWidget.addWidget(self.userWidget) | 
					
						
							|  |  |  |  |         self.rightWidget.addWidget(self.SettingWidget) | 
					
						
							|  |  |  |  |         self.rightWidget.addWidget(self.procedureManagerWidget) | 
					
						
							|  |  |  |  |         self.rightWidget.addWidget(self.controlWidget) | 
					
						
							|  |  |  |  |         self.rightWidget.widget(1) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         self.leftWidget.createProject.clicked.connect(lambda: self.exButtonClicked(0)) | 
					
						
							|  |  |  |  |         self.leftWidget.varMag.clicked.connect(self.varShow) | 
					
						
							|  |  |  |  |         self.leftWidget.trendMag.clicked.connect(self.reFreshTrendWidget) | 
					
						
							|  |  |  |  |         self.leftWidget.userMag.clicked.connect(lambda: self.exButtonClicked(3)) | 
					
						
							|  |  |  |  |         self.leftWidget.protocolMag.clicked.connect(self.showSetting) | 
					
						
							|  |  |  |  |         self.leftWidget.procedureMag.clicked.connect(lambda: self.initProcedureDB()) | 
					
						
							|  |  |  |  |         self.leftWidget.controlMag.clicked.connect(lambda: self.showControlSystem()) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |     def delecteWidget(self): | 
					
						
							|  |  |  |  |         for i in reversed(range(1, self.rightWidget.count())): | 
					
						
							|  |  |  |  |             widget = self.rightWidget.widget(i) | 
					
						
							|  |  |  |  |             if widget: | 
					
						
							|  |  |  |  |                 self.rightWidget.removeWidget(widget) | 
					
						
							|  |  |  |  |                 widget.deleteLater() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def exButtonClicked(self, index): | 
					
						
							|  |  |  |  |         print(Globals.getValue('currentPro')) | 
					
						
							|  |  |  |  |         if Globals.getValue('currentPro') == -1 and index not in [0, 3]: | 
					
						
							|  |  |  |  |             return -1 | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         self.rightWidget.setCurrentIndex(index) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def showSetting(self): | 
					
						
							|  |  |  |  |         if Globals.getValue('currentPro') == -1: | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |         self.SettingWidget.setupUI() | 
					
						
							|  |  |  |  |         self.rightWidget.setCurrentIndex(4) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def varShow(self): | 
					
						
							|  |  |  |  |         self.exButtonClicked(1) | 
					
						
							|  |  |  |  |         Globals.setValue('SearchWidget', 1) | 
					
						
							|  |  |  |  |    | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     def reFreshTrendWidget(self): | 
					
						
							|  |  |  |  |         if Globals.getValue('currentPro') == -1: | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |         # self.trendWidget.getMems() | 
					
						
							|  |  |  |  |         self.exButtonClicked(2) | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     def initProcedureDB(self): | 
					
						
							|  |  |  |  |         if Globals.getValue('currentPro') == -1: | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |         self.procedureManagerWidget.initDB() | 
					
						
							|  |  |  |  |         self.procedureManagerWidget.initUI() | 
					
						
							|  |  |  |  |         self.exButtonClicked(5) | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     def showControlSystem(self): | 
					
						
							|  |  |  |  |         """显示控制系统界面""" | 
					
						
							|  |  |  |  |         if Globals.getValue('currentPro') == -1: | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |         # 重新加载控制系统(确保规则正确加载) | 
					
						
							|  |  |  |  |         self.controlWidget.reloadControlSystem() | 
					
						
							|  |  |  |  |         self.exButtonClicked(6) | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |     def loadVar(self): | 
					
						
							|  |  |  |  |         file_path, _ = QFileDialog.getOpenFileName(self, '选择Excel文件', '', 'Excel Files (*.xlsx *.xls)') | 
					
						
							|  |  |  |  |         if not file_path: | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         excelData = pd.read_excel(file_path, sheet_name=None) | 
					
						
							|  |  |  |  |         allVarNames = [] | 
					
						
							|  |  |  |  |         for sheet_name, data in excelData.items(): | 
					
						
							|  |  |  |  |             if '变量名' in data.columns: | 
					
						
							|  |  |  |  |                 # 确保所有变量名转换为字符串 | 
					
						
							|  |  |  |  |                 allVarNames.extend(data['变量名'].astype(str).tolist()) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         if len(allVarNames) != len(set(allVarNames)): | 
					
						
							|  |  |  |  |             # 确保重复名称列表中的元素都是字符串 | 
					
						
							|  |  |  |  |             repeated_names = [str(name) for name in set(allVarNames) if allVarNames.count(name) > 1] | 
					
						
							|  |  |  |  |             QMessageBox.warning(self, '警告', f'发现重复的变量名: {", ".join(repeated_names)}') | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |         allErrInfo = [] | 
					
						
							|  |  |  |  |         for sheet_name, data in excelData.items(): | 
					
						
							|  |  |  |  |             if '变量名' in data.columns: | 
					
						
							|  |  |  |  |                 importInfo = GlobalVarManager.importVar(sheet_name, data) | 
					
						
							|  |  |  |  |                 allErrInfo.append(importInfo)  | 
					
						
							|  |  |  |  |         if allErrInfo: | 
					
						
							|  |  |  |  |             # 过滤掉空字符串 | 
					
						
							|  |  |  |  |             allErrInfo = [info for info in allErrInfo if info] | 
					
						
							|  |  |  |  |             if not allErrInfo: | 
					
						
							|  |  |  |  |                 QMessageBox.information(self, '导入信息', '所有变量导入成功') | 
					
						
							|  |  |  |  |             else: | 
					
						
							|  |  |  |  |               | 
					
						
							|  |  |  |  |                 errorMessages = '\n'.join(allErrInfo)                | 
					
						
							|  |  |  |  |                 QMessageBox.information(self, '导入信息', errorMessages) | 
					
						
							|  |  |  |  |                  | 
					
						
							|  |  |  |  |              | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |     def enum(self,**enums):  | 
					
						
							|  |  |  |  |         return type('Enum', (), enums)  | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |     def region(self,cursorGlobalPoint):  | 
					
						
							|  |  |  |  |         #获取窗体在屏幕上的位置区域,tl为topleft点,rb为rightbottom点  | 
					
						
							|  |  |  |  |         rect = self.rect()  | 
					
						
							|  |  |  |  |         tl = self.mapToGlobal(rect.topLeft())  | 
					
						
							|  |  |  |  |         rb = self.mapToGlobal(rect.bottomRight())  | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |         x = cursorGlobalPoint.x()  | 
					
						
							|  |  |  |  |         y = cursorGlobalPoint.y()  | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         # 检查是否在标题栏区域,如果不在则不允许调整大小 | 
					
						
							|  |  |  |  |         if not self._isInTitleBar(cursorGlobalPoint): | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.NONE  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.ArrowCursor)) | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |         if(tl.x() + self.padding >= x and tl.x() <= x and tl.y() + self.padding >= y and tl.y() <= y):  | 
					
						
							|  |  |  |  |           #左上角  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.LEFTTOP  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeFDiagCursor))  #设置鼠标形状  | 
					
						
							|  |  |  |  |         elif(x >= rb.x() - self.padding and x <= rb.x() and y >= rb.y() - self.padding and y <= rb.y()):  | 
					
						
							|  |  |  |  |           #右下角  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.RIGHTBOTTOM  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeFDiagCursor))  | 
					
						
							|  |  |  |  |         elif(x <= tl.x() + self.padding and x >= tl.x() and y >= rb.y() - self.padding and y <= rb.y()):  | 
					
						
							|  |  |  |  |           #左下角  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.LEFTBOTTOM  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeBDiagCursor))  | 
					
						
							|  |  |  |  |         elif(x <= rb.x() and x >= rb.x() - self.padding and y >= tl.y() and y <= tl.y() + self.padding):  | 
					
						
							|  |  |  |  |           #右上角  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.RIGHTTOP  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeBDiagCursor))  | 
					
						
							|  |  |  |  |         elif(x <= tl.x() + self.padding and x >= tl.x()):  | 
					
						
							|  |  |  |  |           #左边  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.LEFT  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeHorCursor))  | 
					
						
							|  |  |  |  |         elif( x <= rb.x() and x >= rb.x() - self.padding):  | 
					
						
							|  |  |  |  |           #右边  | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.RIGHT  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeHorCursor))  | 
					
						
							|  |  |  |  |         elif(y >= tl.y() and y <= tl.y() + self.padding):  | 
					
						
							|  |  |  |  |           #上边  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.UP  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeVerCursor))  | 
					
						
							|  |  |  |  |         elif(y <= rb.y() and y >= rb.y() - self.padding):  | 
					
						
							|  |  |  |  |           #下边  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.DOWN  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.SizeVerCursor))  | 
					
						
							|  |  |  |  |         else:  | 
					
						
							|  |  |  |  |           #默认  | 
					
						
							|  |  |  |  |             self.dir = self.Numbers.NONE  | 
					
						
							|  |  |  |  |             self.setCursor(QCursor(Qt.ArrowCursor))  | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |     def mouseReleaseEvent(self,event):  | 
					
						
							|  |  |  |  |         if(event.button() == Qt.LeftButton):  | 
					
						
							|  |  |  |  |             self.isLeftPressDown = False  | 
					
						
							|  |  |  |  |             if(self.dir != self.Numbers.NONE):  | 
					
						
							|  |  |  |  |                 self.releaseMouse()  | 
					
						
							|  |  |  |  |                 self.setCursor(QCursor(Qt.ArrowCursor))  | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |     def mousePressEvent(self,event):  | 
					
						
							|  |  |  |  |         if(event.button()==Qt.LeftButton):  | 
					
						
							|  |  |  |  |             # 检查鼠标点击是否在标题栏区域 | 
					
						
							|  |  |  |  |             if self._isInTitleBar(event.globalPos()): | 
					
						
							|  |  |  |  |                 self.isLeftPressDown=True  | 
					
						
							|  |  |  |  |                 if(self.dir != self.Numbers.NONE):  | 
					
						
							|  |  |  |  |                     self.mouseGrabber()  | 
					
						
							|  |  |  |  |                 else:  | 
					
						
							|  |  |  |  |                     self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()  | 
					
						
							|  |  |  |  |             else: | 
					
						
							|  |  |  |  |                 # 不在标题栏区域,不处理拖拽 | 
					
						
							|  |  |  |  |                 self.isLeftPressDown = False | 
					
						
							|  |  |  |  |                 self.dir = self.Numbers.NONE | 
					
						
							|  |  |  |  |   | 
					
						
							|  |  |  |  |     def mouseMoveEvent(self,event):  | 
					
						
							|  |  |  |  |         gloPoint = event.globalPos()  | 
					
						
							|  |  |  |  |         rect = self.rect()  | 
					
						
							|  |  |  |  |         tl = self.mapToGlobal(rect.topLeft())  | 
					
						
							|  |  |  |  |         rb = self.mapToGlobal(rect.bottomRight())  | 
					
						
							|  |  |  |  |       | 
					
						
							|  |  |  |  |         if(not self.isLeftPressDown):  | 
					
						
							|  |  |  |  |           self.region(gloPoint)   | 
					
						
							|  |  |  |  |         else:  | 
					
						
							|  |  |  |  |             if(self.dir != self.Numbers.NONE):  | 
					
						
							|  |  |  |  |                 rmove=QRect(tl, rb)  | 
					
						
							|  |  |  |  |                 if(self.dir==self.Numbers.LEFT):  | 
					
						
							|  |  |  |  |                     if(rb.x() - gloPoint.x() <= self.minimumWidth()):  | 
					
						
							|  |  |  |  |                         rmove.setX(tl.x())  | 
					
						
							|  |  |  |  |                     else:  | 
					
						
							|  |  |  |  |                         rmove.setX(gloPoint.x())  | 
					
						
							|  |  |  |  |                 elif(self.dir==self.Numbers.RIGHT):  | 
					
						
							|  |  |  |  |                     rmove.setWidth(gloPoint.x() - tl.x())  | 
					
						
							|  |  |  |  |                 elif(self.dir==self.Numbers.UP):  | 
					
						
							|  |  |  |  |                     if(rb.y() - gloPoint.y() <= self.minimumHeight()):  | 
					
						
							|  |  |  |  |                         rmove.setY(tl.y())  | 
					
						
							|  |  |  |  |                     else:  | 
					
						
							|  |  |  |  |                         rmove.setY(gloPoint.y())  | 
					
						
							|  |  |  |  |                 elif(self.dir==self.Numbers.DOWN):  | 
					
						
							|  |  |  |  |                     rmove.setHeight(gloPoint.y() - tl.y())  | 
					
						
							|  |  |  |  |                 elif(self.dir==self.Numbers.LEFTTOP):  | 
					
						
							|  |  |  |  |                     if(rb.x() - gloPoint.x() <= self.minimumWidth()):  | 
					
						
							|  |  |  |  |                         rmove.setX(tl.x())  | 
					
						
							|  |  |  |  |                     else:  | 
					
						
							|  |  |  |  |                         rmove.setX(gloPoint.x())  | 
					
						
							|  |  |  |  |                     if(rb.y() - gloPoint.y() <= self.minimumHeight()):  | 
					
						
							|  |  |  |  |                         rmove.setY(tl.y())  | 
					
						
							|  |  |  |  |                     else:  | 
					
						
							|  |  |  |  |                         rmove.setY(gloPoint.y())  | 
					
						
							|  |  |  |  |                 elif(self.dir==self.Numbers.RIGHTTOP):  | 
					
						
							|  |  |  |  |                     rmove.setWidth(gloPoint.x() - tl.x())  | 
					
						
							|  |  |  |  |                     rmove.setY(gloPoint.y())  | 
					
						
							|  |  |  |  |                 elif(self.dir==self.Numbers.LEFTBOTTOM):  | 
					
						
							|  |  |  |  |                     rmove.setX(gloPoint.x())  | 
					
						
							|  |  |  |  |                     rmove.setHeight(gloPoint.y() - tl.y())  | 
					
						
							|  |  |  |  |                 elif(self.dir==self.Numbers.RIGHTBOTTOM):  | 
					
						
							|  |  |  |  |                     rmove.setWidth(gloPoint.x() - tl.x())  | 
					
						
							|  |  |  |  |                     rmove.setHeight(gloPoint.y() - tl.y())  | 
					
						
							|  |  |  |  |                 else:  | 
					
						
							|  |  |  |  |                     pass  | 
					
						
							|  |  |  |  |                 self.setGeometry(rmove)  | 
					
						
							|  |  |  |  |             else:  | 
					
						
							|  |  |  |  |                 # 只有在标题栏区域才能拖拽移动窗口 | 
					
						
							|  |  |  |  |                 if self._isInTitleBar(event.globalPos()): | 
					
						
							|  |  |  |  |                     self.move(event.globalPos() - self.dragPosition)  | 
					
						
							|  |  |  |  |                 event.accept() | 
					
						
							|  |  |  |  |      | 
					
						
							|  |  |  |  |     def _isInTitleBar(self, globalPos): | 
					
						
							|  |  |  |  |         """
 | 
					
						
							|  |  |  |  |         检查鼠标位置是否在标题栏区域 | 
					
						
							|  |  |  |  |         :param globalPos: 鼠标全局位置 | 
					
						
							|  |  |  |  |         :return: 是否在标题栏区域 | 
					
						
							|  |  |  |  |         """
 | 
					
						
							|  |  |  |  |         # 获取标题栏的全局位置 | 
					
						
							|  |  |  |  |         titleBarRect = self.topWidget.geometry() | 
					
						
							|  |  |  |  |         titleBarGlobalTopLeft = self.topWidget.mapToGlobal(titleBarRect.topLeft()) | 
					
						
							|  |  |  |  |         titleBarGlobalBottomRight = self.topWidget.mapToGlobal(titleBarRect.bottomRight()) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         # 创建全局矩形区域 | 
					
						
							|  |  |  |  |         titleBarGlobalRect = QRect(titleBarGlobalTopLeft, titleBarGlobalBottomRight) | 
					
						
							|  |  |  |  |          | 
					
						
							|  |  |  |  |         # 检查鼠标是否在标题栏区域内 | 
					
						
							|  |  |  |  |         return titleBarGlobalRect.contains(globalPos)  | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def __isWindowMaximized(self, hWnd) -> bool: | 
					
						
							|  |  |  |  |         """ Determine whether the window is maximized """ | 
					
						
							|  |  |  |  |         # GetWindowPlacement() returns the display state of the window and the restored, | 
					
						
							|  |  |  |  |         # maximized and minimized window position. The return value is tuple | 
					
						
							|  |  |  |  |         windowPlacement = win32gui.GetWindowPlacement(hWnd) | 
					
						
							|  |  |  |  |         if not windowPlacement: | 
					
						
							|  |  |  |  |             return False | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         return windowPlacement[1] == win32con.SW_MAXIMIZE | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def __monitorNCCALCSIZE(self, msg: MSG): | 
					
						
							|  |  |  |  |         """ 调整窗口大小 """ | 
					
						
							|  |  |  |  |         monitor = win32api.MonitorFromWindow(msg.hWnd) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         # If the display information is not saved, return directly | 
					
						
							|  |  |  |  |         if monitor is None and not self.__monitorInfo: | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |         elif monitor is not None: | 
					
						
							|  |  |  |  |             self.__monitorInfo = win32api.GetMonitorInfo(monitor) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         # adjust the size of window | 
					
						
							|  |  |  |  |         params = cast(msg.lParam, POINTER(NCCALCSIZE_PARAMS)).contents | 
					
						
							|  |  |  |  |         params.rgrc[0].left = self.__monitorInfo['Work'][0] | 
					
						
							|  |  |  |  |         params.rgrc[0].top = self.__monitorInfo['Work'][1] | 
					
						
							|  |  |  |  |         params.rgrc[0].right = self.__monitorInfo['Work'][2] | 
					
						
							|  |  |  |  |         params.rgrc[0].bottom = self.__monitorInfo['Work'][3] | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def __onScreenChanged(self): | 
					
						
							|  |  |  |  |         hWnd = int(self.windowHandle().winId()) | 
					
						
							|  |  |  |  |         win32gui.SetWindowPos(hWnd, None, 0, 0, 0, 0, win32con.SWP_NOMOVE | | 
					
						
							|  |  |  |  |                               win32con.SWP_NOSIZE | win32con.SWP_FRAMECHANGED) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     def closeEvent(self, event): | 
					
						
							|  |  |  |  |         reply = QMessageBox.question(self, | 
					
						
							|  |  |  |  |                                      'Quit', | 
					
						
							|  |  |  |  |                                      "是否要退出程序?", | 
					
						
							|  |  |  |  |                                      QMessageBox.Yes | QMessageBox.No, | 
					
						
							|  |  |  |  |                                      QMessageBox.No) | 
					
						
							|  |  |  |  |         if reply == QMessageBox.Yes: | 
					
						
							|  |  |  |  |             try: | 
					
						
							|  |  |  |  |                 # 保存控制系统配置 | 
					
						
							|  |  |  |  |                 if hasattr(self, 'controlWidget') and self.controlWidget: | 
					
						
							|  |  |  |  |                     self.controlWidget.controlManager.shutdown() | 
					
						
							|  |  |  |  |                 Client.close() | 
					
						
							|  |  |  |  |             except Exception as e: | 
					
						
							|  |  |  |  |                 print(f"关闭程序时出错: {e}") | 
					
						
							|  |  |  |  |             event.accept() | 
					
						
							|  |  |  |  |         else: | 
					
						
							|  |  |  |  |             event.ignore() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |  |     app = QApplication(sys.argv) | 
					
						
							|  |  |  |  |     app.setStyle(QtWidgets.QStyleFactory.create('Fusion')) | 
					
						
							|  |  |  |  |     app.setStyleSheet(CommonHelper.readQss('Static/main.qss')) | 
					
						
							|  |  |  |  |     # print(QtWidgets.QStyleFactory.keys()) | 
					
						
							|  |  |  |  |     ex = MainWindow() | 
					
						
							|  |  |  |  |     ex.show() | 
					
						
							|  |  |  |  |     sys.exit(app.exec_()) |