工控上位机控制系统通用UI框架

This commit is contained in:
2026-03-09 16:29:32 +08:00
parent 19af6e2b4e
commit a00e13b11a
54 changed files with 11356 additions and 0 deletions

View File

@ -0,0 +1,212 @@
# 配方管理内嵌页面子类
from PySide6.QtWidgets import QWidget, QHeaderView, QSpacerItem, QSizePolicy, QVBoxLayout, QMessageBox, QTableWidgetItem
from PySide6.QtCore import Qt, QObject, QEvent, Slot
from PySide6.QtGui import QKeyEvent
from msg_dict import g_uiGeometrySize
from wndMain.pageRecipeMgt.uiSub_Recipe import Ui_pageRecipe
from common.generalFunc import CCommon
from dbCtrl.clsRecipeTb import g_recipeCtrl
from msg_dict import g_uiCtrlScript
class CSubPageRecipe(QWidget):
# public:
def __init__(self, userId: str, widgetSize: tuple[int, int], parent=None):
super().__init__(parent)
self.creator = userId
self.ui = Ui_pageRecipe()
self.ui.setupUi(self)
# 按需声明对应的成员变量
self.szStack = widgetSize
pass
# 界面初始化
def uiInit(self) -> None:
self._screenAdapter() # 界面自适应
self._changeWndStyle() # 设置成无框架边框
self._centerWidget() # 居中显示
self._changeLine_edit() # 设置用户输入限制
self._setupSignalSlotMapping() # 创建信号映射 先创建信号映射,再加载配方数据
self._loadRecipeData() # 加载配方数据
self._changeTableStyle() # 设置表格样式
pass
# ----------------------------------------
# private:
# 配方操作按钮布局
def _adjustRecipeOpButtons(self) -> None:
nOriginWidth = self.ui.btnAddRecipe.width()
nWidthGap = (self.ui.grpRecipeOp.width() - self.ui.btnAddRecipe.width() * 3 - g_uiGeometrySize['WND_MARGIN_HORI'] * 8) / 2
rctTemp = [self.ui.btnAddRecipe.geometry(), self.ui.btnDelRecipe.geometry(), self.ui.btnUpdateRecipe.geometry()]
rctTemp[0].setLeft(g_uiGeometrySize['WND_MARGIN_HORI'] * 4)
rctTemp[0].setWidth(nOriginWidth)
self.ui.btnAddRecipe.setGeometry(rctTemp[0])
# ------------------------------
rctTemp[1].setLeft(rctTemp[0].right() + nWidthGap)
rctTemp[1].setWidth(nOriginWidth)
self.ui.btnDelRecipe.setGeometry(rctTemp[1])
# ------------------------------
rctTemp[2].setLeft(rctTemp[1].right() + nWidthGap)
rctTemp[2].setWidth(nOriginWidth)
self.ui.btnUpdateRecipe.setGeometry(rctTemp[2])
# 纵向调整子控件高度
def _adjustVerticalHeight(self) -> None:
nBottomPos = self.geometry().bottom() - g_uiGeometrySize['WND_MARGIN_VERT'] # 获取该子页面底部位置
rctTemp = self.ui.tableRecipe.geometry()
rctTemp.setBottom(nBottomPos)
self.ui.tableRecipe.setGeometry(rctTemp) # 调整配方信息列表的高度
# ----------------------------
rctTemp = self.ui.grpRecipeDetails.geometry()
rctTemp.setBottom(nBottomPos)
self.ui.grpRecipeDetails.setGeometry(rctTemp) # 调整配方详细组合框高度
# ----------------------------
rctOtherTemp = self.ui.lstRecipeDetail.geometry()
rctOtherTemp.setHeight(rctTemp.height() - rctOtherTemp.top() - g_uiGeometrySize['WND_MARGIN_VERT'] * 2)
self.ui.lstRecipeDetail.setGeometry(rctOtherTemp)
def _adjustTableWidth(self) -> None:
# 获取表格水平表头
header = self.ui.tableRecipe.horizontalHeader()
# 第一、二、三列设置最小宽度
self.ui.tableRecipe.setColumnWidth(0, 70)
self.ui.tableRecipe.setColumnWidth(1, 150)
self.ui.tableRecipe.setColumnWidth(2, 150)
# 其他列自适应
header.setSectionResizeMode(0, QHeaderView.Interactive)
header.setSectionResizeMode(1, QHeaderView.Interactive)
header.setSectionResizeMode(2, QHeaderView.Interactive)
header.setSectionResizeMode(3, QHeaderView.ResizeToContents)
pass
# 界面自适应
def _screenAdapter(self) -> None:
self.resize(self.szStack[0], self.szStack[1])
self._adjustRecipeOpButtons()
self._adjustVerticalHeight()
self._adjustTableWidth()
pass
# 修改窗体属性
def _changeWndStyle(self) -> None:
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
pass
# 修改表格样式
def _changeTableStyle(self) -> None:
# 禁止所有列宽拖动
self.ui.tableRecipe.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
# 单元格内容居中
for row in range(self.ui.tableRecipe.rowCount()):
for col in range(self.ui.tableRecipe.columnCount()):
item = self.ui.tableRecipe.item(row, col)
if item:
item.setTextAlignment(Qt.AlignCenter)
# 窗口居中显示
def _centerWidget(self) -> None:
pass
# 设置用户输入限制
def _changeLine_edit(self) -> None:
self.ui.edtRecipeName.installEventFilter(self) # 建立时间触发
# 添加配方到表格
def _addRecipeToTable(self, recipeID: str, createTime: str, updateTime: str, creator: str) -> None:
rowPosition = self.ui.tableRecipe.rowCount()
self.ui.tableRecipe.insertRow(rowPosition)
self.ui.tableRecipe.setItem(rowPosition, 0, QTableWidgetItem(recipeID))
self.ui.tableRecipe.setItem(rowPosition, 1, QTableWidgetItem(createTime))
self.ui.tableRecipe.setItem(rowPosition, 2, QTableWidgetItem(updateTime))
self.ui.tableRecipe.setItem(rowPosition, 3, QTableWidgetItem(creator))
# 加载配方数据到表格
def _loadRecipeData(self) -> None:
# 清空表格
self.ui.tableRecipe.setRowCount(0)
# 加载配方数据
recipe_list = g_recipeCtrl.readRecipeID_time_creator()
# 填充表格
for recipe_info in recipe_list:
self._addRecipeToTable(recipe_info[0], recipe_info[1], recipe_info[2], recipe_info[3])
# 重新加载表格样式
self._changeTableStyle()
# 建立信号槽连接
def _setupSignalSlotMapping(self) -> None:
self.ui.btnAddRecipe.clicked.connect(self._onAddRecipeClicked)
self.ui.btnDelRecipe.clicked.connect(self._onDelRecipeClicked)
pass
# ---------事件重载---------
def eventFilter(self, obj: QObject, event):
# 处理对应输入框的键盘事件
if obj == self.ui.edtRecipeName and QEvent.Type.KeyPress == event.type():
clsKeyEvent = QKeyEvent(event)
key = clsKeyEvent.key()
modifier = clsKeyEvent.modifiers()
key_char = clsKeyEvent.text()
return super().eventFilter(obj, event) if CCommon.fnCheckInputValid(key, modifier, key_char) else True
# 非输入框/非键盘按下事件,按默认逻辑处理
return super().eventFilter(obj, event)
# ----------------信号槽接口----------------
@Slot()
def _onAddRecipeClicked(self) -> None:
# 获取输入的配方名称
recipe_name = self.ui.edtRecipeName.text().strip()
if not recipe_name:
QMessageBox.warning(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_INPUT_RECIPE'])
return
# 检查配方名称是否已存在
if recipe_name in g_recipeCtrl.readAllRecipeNames():
QMessageBox.warning(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_RECIPE_EXIST'])
return
# 添加配方
success = g_recipeCtrl.addNewRecipe(recipe_name, self.creator)
if success:
self._loadRecipeData()
# 清空输入框
self.ui.edtRecipeName.clear()
QMessageBox.information(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_ADD_RECIPE_SUCCESS'])
else:
QMessageBox.warning(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_ADD_RECIPE_FAIL'])
pass
pass
@Slot()
def _onDelRecipeClicked(self) -> None:
# 获取选中的行
selected_items = self.ui.tableRecipe.selectedItems()
if not selected_items:
QMessageBox.warning(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_DEL_RECIPE_SELECT'])
return
# 获取选中的配方名
selected_recipes = []
for i in range(0, len(selected_items), 4):
row = selected_items[i].row()
recipe_name = self.ui.tableRecipe.item(row, 0).text()
selected_recipes.append(recipe_name)
# 确认删除
reply = QMessageBox.question(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_DEL_RECIPE_CONFIRM'].format(len(selected_recipes)),
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
success = g_recipeCtrl.delRecipe(selected_recipes)
if success:
self._loadRecipeData()
QMessageBox.information(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_DEL_RECIPE_SUCCESS'])
else:
QMessageBox.warning(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_uiCtrlScript['MSG_SCRIPT_DEL_RECIPE_FAIL'])
pass

View File

@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'uiSub_Recipe.ui'
##
## Created by: Qt User Interface Compiler version 6.9.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QAbstractItemView, QApplication, QGroupBox, QHeaderView,
QLabel, QLineEdit, QListView, QPushButton,
QSizePolicy, QTableWidget, QTableWidgetItem, QWidget)
class Ui_pageRecipe(object):
def setupUi(self, pageRecipe):
if not pageRecipe.objectName():
pageRecipe.setObjectName(u"pageRecipe")
pageRecipe.resize(1024, 768)
self.grpRecipeOp = QGroupBox(pageRecipe)
self.grpRecipeOp.setObjectName(u"grpRecipeOp")
self.grpRecipeOp.setGeometry(QRect(10, 10, 501, 121))
self.lblRecipeName = QLabel(self.grpRecipeOp)
self.lblRecipeName.setObjectName(u"lblRecipeName")
self.lblRecipeName.setGeometry(QRect(20, 20, 91, 16))
self.edtRecipeName = QLineEdit(self.grpRecipeOp)
self.edtRecipeName.setObjectName(u"edtRecipeName")
self.edtRecipeName.setGeometry(QRect(121, 18, 361, 21))
self.edtRecipeName.setMaxLength(30)
self.btnAddRecipe = QPushButton(self.grpRecipeOp)
self.btnAddRecipe.setObjectName(u"btnAddRecipe")
self.btnAddRecipe.setGeometry(QRect(30, 60, 100, 41))
self.btnAddRecipe.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.btnDelRecipe = QPushButton(self.grpRecipeOp)
self.btnDelRecipe.setObjectName(u"btnDelRecipe")
self.btnDelRecipe.setGeometry(QRect(160, 60, 100, 41))
self.btnDelRecipe.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.btnUpdateRecipe = QPushButton(self.grpRecipeOp)
self.btnUpdateRecipe.setObjectName(u"btnUpdateRecipe")
self.btnUpdateRecipe.setGeometry(QRect(300, 60, 100, 41))
self.btnUpdateRecipe.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.grpRecipeDetails = QGroupBox(pageRecipe)
self.grpRecipeDetails.setObjectName(u"grpRecipeDetails")
self.grpRecipeDetails.setGeometry(QRect(520, 10, 491, 751))
self.lblRecipeDetails = QLabel(self.grpRecipeDetails)
self.lblRecipeDetails.setObjectName(u"lblRecipeDetails")
self.lblRecipeDetails.setGeometry(QRect(20, 20, 91, 16))
self.lstRecipeDetail = QListView(self.grpRecipeDetails)
self.lstRecipeDetail.setObjectName(u"lstRecipeDetail")
self.lstRecipeDetail.setGeometry(QRect(20, 50, 451, 691))
self.tableRecipe = QTableWidget(pageRecipe)
if (self.tableRecipe.columnCount() < 4):
self.tableRecipe.setColumnCount(4)
__qtablewidgetitem = QTableWidgetItem()
self.tableRecipe.setHorizontalHeaderItem(0, __qtablewidgetitem)
__qtablewidgetitem1 = QTableWidgetItem()
self.tableRecipe.setHorizontalHeaderItem(1, __qtablewidgetitem1)
__qtablewidgetitem2 = QTableWidgetItem()
self.tableRecipe.setHorizontalHeaderItem(2, __qtablewidgetitem2)
__qtablewidgetitem3 = QTableWidgetItem()
self.tableRecipe.setHorizontalHeaderItem(3, __qtablewidgetitem3)
self.tableRecipe.setObjectName(u"tableRecipe")
self.tableRecipe.setEnabled(True)
self.tableRecipe.setGeometry(QRect(10, 140, 501, 621))
self.tableRecipe.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
self.tableRecipe.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection)
self.tableRecipe.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.tableRecipe.setColumnCount(4)
self.tableRecipe.horizontalHeader().setMinimumSectionSize(22)
self.tableRecipe.horizontalHeader().setStretchLastSection(True)
self.tableRecipe.verticalHeader().setStretchLastSection(False)
self.retranslateUi(pageRecipe)
QMetaObject.connectSlotsByName(pageRecipe)
# setupUi
def retranslateUi(self, pageRecipe):
pageRecipe.setWindowTitle(QCoreApplication.translate("pageRecipe", u"Form", None))
self.grpRecipeOp.setTitle("")
self.lblRecipeName.setText(QCoreApplication.translate("pageRecipe", u"\u65b0\u5efa\u914d\u65b9\u540d\u79f0\uff1a", None))
self.edtRecipeName.setPlaceholderText(QCoreApplication.translate("pageRecipe", u"\u957f\u5ea630\uff0c\u4ec5\u9650\u82f1\u6587\u3001\u6570\u5b57\u548c\u4e0b\u5212\u7ebf", None))
self.btnAddRecipe.setText(QCoreApplication.translate("pageRecipe", u"\u65b0\u5efa\u914d\u65b9", None))
self.btnDelRecipe.setText(QCoreApplication.translate("pageRecipe", u"\u5220\u9664\u914d\u65b9", None))
self.btnUpdateRecipe.setText(QCoreApplication.translate("pageRecipe", u"\u66f4\u65b0\u914d\u65b9", None))
self.grpRecipeDetails.setTitle("")
self.lblRecipeDetails.setText(QCoreApplication.translate("pageRecipe", u"\u914d\u65b9\u8be6\u7ec6\u53c2\u6570\uff1a", None))
___qtablewidgetitem = self.tableRecipe.horizontalHeaderItem(0)
___qtablewidgetitem.setText(QCoreApplication.translate("pageRecipe", u"\u914d\u65b9\u540d\u79f0", None));
___qtablewidgetitem1 = self.tableRecipe.horizontalHeaderItem(1)
___qtablewidgetitem1.setText(QCoreApplication.translate("pageRecipe", u"\u521b\u5efa\u65f6\u95f4", None));
___qtablewidgetitem2 = self.tableRecipe.horizontalHeaderItem(2)
___qtablewidgetitem2.setText(QCoreApplication.translate("pageRecipe", u"\u66f4\u65b0\u65f6\u95f4", None));
___qtablewidgetitem3 = self.tableRecipe.horizontalHeaderItem(3)
___qtablewidgetitem3.setText(QCoreApplication.translate("pageRecipe", u"\u521b\u5efa\u8005", None));
# retranslateUi