# 主控界面子类 import time from PySide6.QtCore import Qt, QRect, QTimer, QPoint, Slot from PySide6.QtGui import QCloseEvent from PySide6.QtWidgets import QMainWindow, QStatusBar, QLabel, QVBoxLayout, QMessageBox, QApplication, QDialog from .pageDataQuery.sub_uiQuery import CSubPageQuery from .pageDevDebug.sub_uiDevDebug import CSubPageDevDebug from .pageParaSet.sub_uiParaSet import CSubPageParaSetting from .pageRecipeMgt.sub_uiRecipe import CSubPageRecipe from .pageUserMgt.sub_uiUser import CSubPageUser from .uiMain import Ui_dlgMain from .pageAutoPage.sub_uiAutoPage import CSubPageAutoProc from common.generalFunc import CCommon from common.allTypesEnum import EOSType, ESubPageType from .statusBarView.vwStatusBar import CStatusbarView from .funcBarView.vwFunctionBar import CFunctionBarView from .pagePasswdChange.sub_uiPasswdChange import CPasswdChange from .pagePasswdChange.uiPasswdChange import Ui_dlgChangePasswd from wndCtrl.stateCtrl.clsSysState_autoproc import CStateAutoProc from msg_dict import g_uiCtrlScript, g_uiGeometrySize, g_otherScripts, g_errMsgText # 根据系统平台类型,调整屏幕尺寸高宽比例 def getSizeRatio(osType: EOSType) -> list: if EOSType.MACOS == osType: lstRatio = [1.0, 0.88] elif EOSType.LINUX == osType: lstRatio = [0.9, 1.0] else: lstRatio = [1.0, 1.0] return lstRatio class CSubUiMain(QMainWindow): _m_nTimeCount = 0 #用作定时器,每秒计数 # public: def __init__(self, userId: str, userType: str, parent=None): super().__init__(parent) # 挂载UI界面:将当前业务类实例传入setupUi,UI组件成为实例属性 self.ui = Ui_dlgMain() self.ui.setupUi(self) # 获取屏幕分辨率 self._m_arrScreen = CCommon.fnGetScreenRate() # 按需声明对应的成员变量 self._m_status = None # 状态栏对象 self._m_bQuitType = True # 退出方式,True:完全退出系统 False:返回到登录窗口 self._m_currentUser = [userId, userType] pass # 界面初始化 def uiInit(self) -> None: self._createStatusLabels() # 创建状态栏显示标签 self._initStatusBar() # 创建并初始化状态栏 self._screenAdapter() # 界面自适应 # --------------------------- self._createSubPages((int(self.ui.stkMainContainer.width()), int(self.ui.stkMainContainer.height()))) # 创建功能子页面 self._add2StackWidget() # 添加到容器 self._adjustRdoButtons() # 调整功能框单选按钮布局 # 添加其他和界面或控件初始化相关的操作 self.setWindowTitle(g_uiCtrlScript['WND_TITLE_MAIN']) #设置窗口标题 self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True) # 设置当窗口close时,确保关闭即销毁窗口 self._changeWndStyle() # 修改窗体属性 # ---------------------------- self._createFuncBarView() # 初始化功能区更新视图 self._updateFuncBar(CStatusbarView.fnGetGridScript(self.lblMainVariableItems[2])) # 根据当前登录用户类别,刷新功能区状态 # ---------------------------- self._createTimer() # 创建定时器 # --------------------------------------------------------------- self._setupSignalSlotMapping() # 创建信号映射 self.m_timer.start() pass # private: #------------------------------------------------------------------------------------------------------------ # 界面自适应 def _screenAdapter(self) -> None: fRatio = getSizeRatio(EOSType.MACOS) # 屏幕尺寸高宽调整比例 realSize = (self._m_arrScreen[0] * fRatio[0], self._m_arrScreen[1] * fRatio[1]) self.setFixedSize(int(realSize[0]), int(realSize[1])) rctGroups = self._adjustGroupBox(realSize) # 调整主界面上面和左侧的组合框 self._adjustButtonAboutUser(rctGroups[2]) # 调整上面最右侧组合框中的按钮布局 self._adjustStackPage(rctGroups[3], rctGroups[2]) #调整右侧窗口容器空间 self._adjustCapacityStatisticsCtrl() # 调整产能统计相关控件的布局 pass # 组合框自适应 def _adjustGroupBox(self, screenSize: tuple[float, float]) -> list: nTopGroupBoxHeight = int(screenSize[1] / 8) # 设置上面第一个组合框大小 rctTemp: list[QRect] = [QRect(), QRect(), QRect(), QRect()] rctTemp[0].setTop(g_uiGeometrySize['WND_MARGIN_VERT']) rctTemp[0].setLeft(g_uiGeometrySize['WND_MARGIN_HORI']) rctTemp[0].setHeight(nTopGroupBoxHeight) rctTemp[0].setWidth(int(screenSize[0] / 3)) self.ui.grpMainSysInfo_0.setGeometry(rctTemp[0]) # --------------------------------- # 设置上面第二个组合框大小 rctTemp[1].setTop(g_uiGeometrySize['WND_MARGIN_VERT']) rctTemp[1].setLeft(rctTemp[0].right() + g_uiGeometrySize['WND_MARGIN_HORI']) rctTemp[1].setHeight(nTopGroupBoxHeight) rctTemp[1].setWidth(int(rctTemp[0].width() * 5 / 3)) self.ui.grpMainSysInfo_1.setGeometry(rctTemp[1]) # 设置上面第三个组合框大小 rctTemp[2].setTop(g_uiGeometrySize['WND_MARGIN_VERT']) rctTemp[2].setLeft(rctTemp[1].right() + g_uiGeometrySize['WND_MARGIN_HORI']) rctTemp[2].setHeight(nTopGroupBoxHeight) rctTemp[2].setWidth(screenSize[0] - rctTemp[0].width() - rctTemp[1].width() - g_uiGeometrySize['WND_MARGIN_HORI'] * 3) self.ui.grpMainForUser.setGeometry(rctTemp[2]) # 设置功能组合框位置大小 rctTemp[3] = self.ui.grpMainModule.geometry() rctTemp[3].setTop(rctTemp[0].bottom() + g_uiGeometrySize['WND_MARGIN_VERT']) rctTemp[3].setLeft(rctTemp[0].left()) rctTemp[3].setHeight(screenSize[1] - g_uiGeometrySize['WND_MARGIN_VERT'] * 2 - rctTemp[0].height() - self._m_status.height()) self.ui.grpMainModule.setGeometry(rctTemp[3]) return rctTemp # 用户切换和修改密码按钮自适应 def _adjustButtonAboutUser(self, rctSize: QRect) -> None: nBtnHeight: int = (rctSize.height() - g_uiGeometrySize['WND_MARGIN_VERT'] * 6) / 2 nBtnWidth: int = rctSize.width() - g_uiGeometrySize['WND_MARGIN_HORI'] * 4 rctBtn = QRect() rctBtn.setLeft(g_uiGeometrySize['WND_MARGIN_HORI'] * 2) rctBtn.setTop(g_uiGeometrySize['WND_MARGIN_VERT'] * 2) rctBtn.setWidth(nBtnWidth) rctBtn.setHeight(nBtnHeight) self.ui.btnMainSwitchUser.setGeometry(rctBtn) #--------------------------- nTempHeight = rctBtn.height() rctBtn.setTop(g_uiGeometrySize['WND_MARGIN_VERT'] * 4 + rctBtn.height()) rctBtn.setHeight(nTempHeight) self.ui.btnMainChangePasswd.setGeometry(rctBtn) pass # 子页面堆栈控件自适应 def _adjustStackPage(self, rctFuncGrp: QRect, rctUserGrp: QRect) -> None: rctStack = self.ui.stkMainContainer.geometry() rctStack.setLeft(rctFuncGrp.right() + g_uiGeometrySize['WND_MARGIN_HORI']) rctStack.setTop(rctFuncGrp.top()) rctStack.setHeight(rctFuncGrp.height()) rctStack.setRight(rctUserGrp.right()) self.ui.stkMainContainer.setGeometry(rctStack) # 功能组合框,单选按钮自适应排列 def _adjustRdoButtons(self) -> None: layVert = QVBoxLayout() layVert.addWidget(self.ui.rdbMainAutoProc, alignment=Qt.AlignmentFlag.AlignHCenter) layVert.addWidget(self.ui.rdbMainDebug, alignment=Qt.AlignmentFlag.AlignHCenter) layVert.addWidget(self.ui.rdbMainSetting, alignment=Qt.AlignmentFlag.AlignHCenter) layVert.addWidget(self.ui.rdbMainQuery, alignment=Qt.AlignmentFlag.AlignHCenter) layVert.addWidget(self.ui.rdbMainRecipe, alignment=Qt.AlignmentFlag.AlignHCenter) layVert.addWidget(self.ui.rdbMainUser, alignment=Qt.AlignmentFlag.AlignHCenter) # 计算组合框内radiobutton之间的垂直间距 grpHeight = self.ui.grpMainModule.geometry().height() nHeightGap = (grpHeight - g_uiGeometrySize['WND_MARGIN_VERT'] * 4 - self.ui.rdbMainDebug.height() * 6) / 5 layVert.setSpacing(nHeightGap) layVert.setContentsMargins(g_uiGeometrySize['WND_MARGIN_HORI'] * 2, g_uiGeometrySize['WND_MARGIN_VERT'] * 2, g_uiGeometrySize['WND_MARGIN_HORI'] * 2, g_uiGeometrySize['WND_MARGIN_VERT'] * 2) self.ui.grpMainModule.setLayout(layVert) # 产能统计控件布局排列 def _adjustCapacityStatisticsCtrl(self) -> None: nSizeArr = (self.ui.grpMainSysInfo_0.geometry().width(), self.ui.grpMainSysInfo_0.geometry().height()) # 计算控件之间的排列间隔宽度 nGapWidth = (nSizeArr[0] - g_uiGeometrySize['WND_MARGIN_VERT'] * 7 - self.ui.lblMainWoodTotal.width() - self.ui.lblMainWoodNG.width() - self.ui.lblMainPassRate.width() - self.ui.edtMainWoodNG.width() * 3) / 2 # 根据组合框的宽高,布局内部控件 ptPosition = [QPoint(), QPoint(),] # 0: 给label 1:给editbox ptPosition[0].setY(nSizeArr[1] / 2 - g_uiGeometrySize['WND_MARGIN_VERT']) # 设置第一个label的高度位置 ptPosition[0].setX(g_uiGeometrySize['WND_MARGIN_HORI'] * 2) # 设置第一个label的水平位置 nTempCtrlSize = [self.ui.lblMainWoodTotal.width(), self.ui.lblMainWoodTotal.height(),] # 临时存储控件的宽高 self.ui.lblMainWoodTotal.setGeometry(ptPosition[0].x(), ptPosition[0].y(), nTempCtrlSize[0], nTempCtrlSize[1]) # ----------------------------------------------------------- rctTemp = self.ui.lblMainWoodTotal.geometry() nLabelTop = rctTemp.top() ptPosition[1].setX(rctTemp.right() + g_uiGeometrySize['WND_MARGIN_HORI']) ptPosition[1].setY(rctTemp.top() - g_uiGeometrySize['WND_MARGIN_VERT'] / 2) nTempWidth = self.ui.edtMainWoodTotal.width() nTempHeight = self.ui.edtMainWoodTotal.height() self.ui.edtMainWoodTotal.setGeometry(ptPosition[1].x(), ptPosition[1].y(), nTempWidth, nTempHeight) # ----------------------------------------------------------- rctTemp = self.ui.edtMainWoodTotal.geometry() nEditTop = rctTemp.top() ptPosition[0].setX(rctTemp.right() + nGapWidth) ptPosition[0].setY(nLabelTop) nTempCtrlSize[0] = self.ui.lblMainWoodNG.width() nTempCtrlSize[1] = self.ui.lblMainWoodNG.height() self.ui.lblMainWoodNG.setGeometry(ptPosition[0].x(), ptPosition[0].y(), nTempCtrlSize[0], nTempCtrlSize[1]) # ----------------------------------------------------------- rctTemp = self.ui.lblMainWoodNG.geometry() ptPosition[1].setX(rctTemp.right() + g_uiGeometrySize['WND_MARGIN_HORI']) ptPosition[1].setY(nEditTop) self.ui.edtMainWoodNG.setGeometry(ptPosition[1].x(), ptPosition[1].y(), nTempWidth, nTempHeight) # ----------------------------------------------------------- rctTemp = self.ui.edtMainWoodNG.geometry() ptPosition[0].setX(rctTemp.right() + nGapWidth) nTempCtrlSize[0] = self.ui.lblMainPassRate.width() nTempCtrlSize[1] = self.ui.lblMainPassRate.height() self.ui.lblMainPassRate.setGeometry(ptPosition[0].x(), ptPosition[0].y(), nTempCtrlSize[0], nTempCtrlSize[1]) # ----------------------------------------------------------- rctTemp = self.ui.lblMainPassRate.geometry() ptPosition[1].setX(rctTemp.right() + g_uiGeometrySize['WND_MARGIN_HORI']) self.ui.edtMainPassRate.setGeometry(ptPosition[1].x(), ptPosition[1].y(), nTempWidth, nTempHeight) pass #------------------------------------------------------------------------------------------------------------ # 创建子页面实体 def _createSubPages(self, szStack: tuple[int, int]) -> None: # 在此处添加每个子页面 self.m_subPages = (CSubPageAutoProc(szStack, self), CSubPageDevDebug(szStack, self), CSubPageParaSetting(szStack, self), CSubPageQuery(szStack, self), CSubPageRecipe(self._m_currentUser[0], szStack, self), CSubPageUser(szStack, self)) for item in self.m_subPages: item.uiInit() # 将子页面添加到堆栈控件中 def _add2StackWidget(self): for item in self.m_subPages: self.ui.stkMainContainer.addWidget(item) self.ui.stkMainContainer.setCurrentWidget(self.m_subPages[0]) #------------------------------------------------------------------------------------------------------------ # 修改窗体属性 def _changeWndStyle(self): self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.CustomizeWindowHint | Qt.WindowType.WindowTitleHint | Qt.WindowType.WindowCloseButtonHint | Qt.WindowType.WindowMinimizeButtonHint) pass # 创建状态栏 def _initStatusBar(self): self._m_status = QStatusBar(self) self._m_status.setSizeGripEnabled(True) self.setStatusBar(self._m_status) # 添加标签到状态栏,用分隔符区分 nScan: int = 0 while 4 > nScan: self._m_status.addWidget(self.lblMainConstStatusItems[nScan]) self._m_status.addWidget(self.lblMainVariableItems[nScan]) self._m_status.addWidget(QLabel(g_otherScripts['OTHER_SEPARATOR'])) nScan += 1 else: self._m_status.addWidget(self.lblMainConstStatusItems[4]) self._m_status.addWidget(self.lblMainVariableItems[4]) # 更新状态栏中的当前登录用户和用户类别 CStatusbarView.fnRefreshGridScript(self.lblMainVariableItems[1], self._m_currentUser[0]) CStatusbarView.fnRefreshGridScript(self.lblMainVariableItems[2], self._m_currentUser[1]) # 更新当前作业状态 CStatusbarView.fnRefreshGridScript(self.lblMainVariableItems[3], g_otherScripts['OTHER_PROC_STATE_0']) pass # 创建状态显示标签 def _createStatusLabels(self) -> None: self.lblMainConstStatusItems = (QLabel(g_uiCtrlScript['WND_STATUSBAR_0']), QLabel(g_uiCtrlScript['WND_STATUSBAR_1']), QLabel(g_uiCtrlScript['WND_STATUSBAR_2']), QLabel(g_uiCtrlScript['WND_STATUSBAR_3']), QLabel(g_uiCtrlScript['WND_STATUSBAR_4'])) self.lblMainVariableItems = [QLabel(''), QLabel(''), QLabel(''), QLabel(''), QLabel('')] # -------------------------------------------- # 创建主界面功能区视图类 def _createFuncBarView(self) -> None: lstRdoButtons: list = [self.ui.rdbMainAutoProc, self.ui.rdbMainDebug, self.ui.rdbMainSetting, self.ui.rdbMainQuery, self.ui.rdbMainRecipe, self.ui.rdbMainUser] self._m_vwUpdatingFuncBar = CFunctionBarView(lstRdoButtons) # 声明功能区视图 # 更新功能区控件状态 def _updateFuncBar(self, userType: str) -> None: self._m_vwUpdatingFuncBar.setCtrlsEnabled(userType) if userType == g_uiCtrlScript['CTRL_USER_TYPE_ADMIN']: self.ui.rdbMainQuery.setChecked(True) self._setPageVisibleProperty(ESubPageType.DATAQUERY.value[0]) # -------------------------------------------- # 创建定时器 def _createTimer(self) -> None: self.m_timer = QTimer(self) self.m_timer.setTimerType(Qt.TimerType.PreciseTimer) self.m_timer.setInterval(100) #-------------------------------------------- # 内嵌页面跳转处理 def _setPageVisibleProperty(self, pageType: int) -> None: self.ui.stkMainContainer.setCurrentWidget(self.m_subPages[pageType]) # 建立信号槽连接 def _setupSignalSlotMapping(self) -> None: self.m_timer.timeout.connect(self._onTimer) # 定时器信号 self.ui.rdbMainAutoProc.toggled.connect(self._onClickRdoButton) self.ui.rdbMainDebug.toggled.connect(self._onClickRdoButton) self.ui.rdbMainSetting.toggled.connect(self._onClickRdoButton) self.ui.rdbMainQuery.toggled.connect(self._onClickRdoButton) self.ui.rdbMainRecipe.toggled.connect(self._onClickRdoButton) self.ui.rdbMainUser.toggled.connect(self._onClickRdoButton) self.ui.btnMainSwitchUser.clicked.connect(self._onClickBtnSwitchUser) self.ui.btnMainChangePasswd.clicked.connect(self._onClickBtnChangePasswd) pass # 主界面退出流程 def _quitMainWndProc(self, bQuitType: bool) -> None: # 先获取登录窗口引用 dlgParent = self.parentWidget() # 销毁主窗口,显示登录窗口 self.m_timer.stop() # 停止计时器 time.sleep(0.03) # 等待其他操作执行结束 self.close() # 显示之前的登录窗口 if bQuitType: QApplication.instance().quit() else: dlgParent.show() # ----------------事件重载---------------- def closeEvent(self, event: QCloseEvent) -> None: if CStateAutoProc.getProcState(): QMessageBox.information(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_errMsgText['ERR_AUTOPROC_BUSY']) event.ignore() else: reply = QMessageBox.question(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_CONFIRM'], QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No) if reply == QMessageBox.StandardButton.Yes: self._quitMainWndProc(self._m_bQuitType) event.accept() else: event.ignore() # ----------------信号槽接口---------------- @Slot() def _onTimer(self): # 定时器响应消息 if 10 == CSubUiMain._m_nTimeCount: self.lblMainVariableItems[0].setText(CCommon.fnGetCurrentTime()) CSubUiMain._m_nTimeCount = 0 CSubUiMain._m_nTimeCount += 1 # 读取io状态 # g_warnState.setIOReadingException(g_emv.readIO(), g_emv.getIOErrMessage()) # 将反馈结果同步到报警器 @Slot() def _onClickRdoButton(self): # 单选按钮关联信号接口 selRdo = self.sender() strName: str = selRdo.objectName() if 'rdbMainAutoProc' == strName and self.ui.rdbMainAutoProc.isChecked(): self._setPageVisibleProperty(ESubPageType.AUTOPROC.value[0]) elif 'rdbMainDebug' == strName and self.ui.rdbMainDebug.isChecked(): self._setPageVisibleProperty(ESubPageType.DEVDEBUG.value[0]) elif 'rdbMainSetting' == strName and self.ui.rdbMainSetting.isChecked(): self._setPageVisibleProperty(ESubPageType.PARASETTING.value[0]) elif 'rdbMainQuery' == strName and self.ui.rdbMainQuery.isChecked(): self._setPageVisibleProperty(ESubPageType.DATAQUERY.value[0]) elif 'rdbMainRecipe' == strName and self.ui.rdbMainRecipe.isChecked(): self._setPageVisibleProperty(ESubPageType.RECIPEMANAGE.value[0]) elif 'rdbMainUser' == strName and self.ui.rdbMainUser.isChecked(): self._setPageVisibleProperty(ESubPageType.USERMANAGE.value[0]) @Slot() def _onClickBtnSwitchUser(self): self._m_bQuitType = False self.close() pass @Slot() def _onClickBtnChangePasswd(self): passwd_dlg = CPasswdChange(self._m_currentUser[0], parent=self) passwd_dlg.uiInit() passwd_dlg.exec() pass