工控上位机控制系统通用UI框架
This commit is contained in:
223
wndMain/pageAutoPage/sub_uiAutoPage.py
Normal file
223
wndMain/pageAutoPage/sub_uiAutoPage.py
Normal file
@ -0,0 +1,223 @@
|
||||
# 自动作业内嵌页面子类
|
||||
from PySide6.QtCore import Slot, Qt, QTimer
|
||||
from PySide6.QtWidgets import QWidget, QMessageBox, QLabel
|
||||
from PySide6.QtGui import QImage, QPixmap
|
||||
from wndCtrl.stateCtrl.clsSysState_autoproc import CStateAutoProc
|
||||
from .uiSub_AutoPage import Ui_pageAutoProc
|
||||
from msg_dict import g_uiCtrlScript, g_uiGeometrySize, g_errMsgText
|
||||
from ..camera_img_get import Camera
|
||||
import cv2 # 确保导入OpenCV
|
||||
|
||||
|
||||
class CSubPageAutoProc(QWidget):
|
||||
# public:
|
||||
def __init__(self, widgetSize: tuple[int, int], parent=None):
|
||||
super().__init__(parent)
|
||||
# 挂载UI界面:将当前业务类实例传入setupUi,UI组件成为实例属性
|
||||
self.ui = Ui_pageAutoProc()
|
||||
self.ui.setupUi(self)
|
||||
# 按需声明对应的成员变量
|
||||
self.szStack = widgetSize
|
||||
|
||||
# 摄像头相关变量
|
||||
self.cam0 = None # 第一个摄像头
|
||||
self.cam1 = None # 第二个摄像头
|
||||
self.timer = None # 定时器
|
||||
self.camera_label = None # 专门用于显示摄像头的Label,避免重复创建
|
||||
|
||||
pass
|
||||
|
||||
# 界面初始化
|
||||
def uiInit(self) -> None:
|
||||
self._editCtrlTitle()
|
||||
self._screenAdapter() # 界面自适应
|
||||
# 添加其他和界面或控件初始化相关的操作
|
||||
self._changeWndStyle() # 设置成无框架边框
|
||||
self._centerWidget() # 居中显示
|
||||
# ---------------------------------------------------------------
|
||||
self._setupSignalSlotMapping()
|
||||
|
||||
# 添加摄像头实时图片
|
||||
self._camera_show()
|
||||
|
||||
pass
|
||||
|
||||
# -----------------------------------------
|
||||
# private:
|
||||
# 初始化修改页面控件文字
|
||||
def _editCtrlTitle(self) -> None:
|
||||
# 修改tab页面文字
|
||||
self.ui.tabProc.setTabText(0, g_uiCtrlScript['PAGE_AUTOPROC_TAB_0'])
|
||||
self.ui.tabProc.setTabText(1, g_uiCtrlScript['PAGE_AUTOPROC_TAB_1'])
|
||||
|
||||
# 界面自适应
|
||||
def _screenAdapter(self) -> None:
|
||||
self.resize(self.szStack[0], self.szStack[1])
|
||||
self.ui.tabProc.setGeometry(g_uiGeometrySize['WND_MARGIN_HORI'], g_uiGeometrySize['WND_MARGIN_VERT'],
|
||||
self.szStack[0] - g_uiGeometrySize['WND_MARGIN_HORI'] * 2,
|
||||
self.szStack[1] - g_uiGeometrySize['WND_MARGIN_VERT'] * 2)
|
||||
self._adjustTabCtrls() # 调整tab页内控件的位置及大小
|
||||
pass
|
||||
|
||||
# 窗口居中显示
|
||||
def _centerWidget(self) -> None:
|
||||
pass
|
||||
|
||||
# 修改窗体属性
|
||||
def _changeWndStyle(self) -> None:
|
||||
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
||||
pass
|
||||
|
||||
# 调整tab页面控件
|
||||
def _adjustTabCtrls(self):
|
||||
rctTemp = self.ui.grpCamera0.geometry()
|
||||
nSize = (rctTemp.width(), rctTemp.height())
|
||||
self.ui.grpCamera0.setGeometry(g_uiGeometrySize['WND_MARGIN_HORI'], 0, nSize[0], nSize[1])
|
||||
|
||||
# -------------------------------------------
|
||||
# 建立信号槽连接
|
||||
def _setupSignalSlotMapping(self) -> None:
|
||||
# self.ui.btnProcStart.clicked.connect(self._onBtnProcStart)
|
||||
self.ui.btnProcStop.clicked.connect(self._onBtnProcStop)
|
||||
self.ui.btnReset.clicked.connect(self._onBtnReset)
|
||||
pass
|
||||
|
||||
# ----------槽函数----------
|
||||
# @Slot()
|
||||
# def _onBtnProcStart(self):
|
||||
# # 启动自动作业
|
||||
# if g_warnState.checkSysWarning():
|
||||
# QMessageBox.information(self, g_uiCtrlScript['MSG_TITLE_TIPS'], g_errMsgText['ERR_SYS_WARNING'])
|
||||
# else:
|
||||
#
|
||||
# tProcJob = CProcThread()
|
||||
# CStateAutoProc.setProcState(True)
|
||||
# tProcJob.runProc()
|
||||
# # 更新作业按钮的使能状态
|
||||
# self.ui.btnProcStart.setEnabled(False)
|
||||
# self.ui.btnProcStop.setEnabled(True)
|
||||
# pass
|
||||
|
||||
@Slot()
|
||||
def _onBtnProcStop(self):
|
||||
# 停止自动作业
|
||||
pass
|
||||
|
||||
@Slot()
|
||||
def _onBtnReset(self):
|
||||
pass
|
||||
|
||||
def _camera_show(self):
|
||||
"""
|
||||
初始化摄像头并启动实时显示
|
||||
"""
|
||||
try:
|
||||
# 1. 初始化摄像头(保持打开状态)
|
||||
self.cam0 = Camera()
|
||||
if not self.cam0._open():
|
||||
print("[Error] Failed to open camera")
|
||||
QMessageBox.warning(self, "摄像头错误", "无法打开摄像头,请检查设备连接!")
|
||||
return
|
||||
|
||||
# 2. 初始化显示用的Label
|
||||
self._init_camera_label()
|
||||
|
||||
# 3. 创建定时器,每50毫秒更新一次图像
|
||||
self.timer = QTimer(self)
|
||||
self.timer.timeout.connect(self._update_camera_image)
|
||||
self.timer.start(10) # 50ms,约20fps
|
||||
print("[Info] Camera started successfully")
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"摄像头初始化失败: {str(e)}"
|
||||
print(f"[Error] {error_msg}")
|
||||
QMessageBox.critical(self, "摄像头错误", error_msg)
|
||||
|
||||
def _init_camera_label(self):
|
||||
"""
|
||||
初始化摄像头显示用的Label(只创建一次)
|
||||
"""
|
||||
# 如果Label已存在,直接返回
|
||||
if self.camera_label is not None:
|
||||
return
|
||||
|
||||
# 创建Label并设置属性
|
||||
self.camera_label = QLabel(self.ui.fraCamera0)
|
||||
# 设置Label充满父容器fraCamera0
|
||||
self.camera_label.setGeometry(0, 0, self.ui.fraCamera0.width(), self.ui.fraCamera0.height())
|
||||
# 设置图像自适应缩放
|
||||
self.camera_label.setScaledContents(True)
|
||||
# 设置对齐方式
|
||||
self.camera_label.setAlignment(Qt.AlignCenter)
|
||||
# 确保Label在最上层显示
|
||||
self.camera_label.raise_()
|
||||
|
||||
def _update_camera_image(self):
|
||||
"""
|
||||
定时更新摄像头图像(修复版)
|
||||
"""
|
||||
try:
|
||||
if self.cam0 is None or self.camera_label is None:
|
||||
return
|
||||
|
||||
# 1. 获取摄像头图像
|
||||
img = self.cam0.get_img()
|
||||
if img is None or img.size == 0:
|
||||
print("[Warning] 获取到空图像")
|
||||
return
|
||||
|
||||
# 2. OpenCV图像是BGR格式,需要转换为RGB
|
||||
# 先检查图像通道数
|
||||
if len(img.shape) == 3 and img.shape[2] == 3:
|
||||
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||
else:
|
||||
# 灰度图像处理
|
||||
img_rgb = img
|
||||
|
||||
# 3. 转换为QImage
|
||||
h, w = img_rgb.shape[:2]
|
||||
ch = 3 if len(img_rgb.shape) == 3 else 1
|
||||
bytes_per_line = ch * w
|
||||
|
||||
if ch == 3:
|
||||
q_img = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format_RGB888)
|
||||
else:
|
||||
q_img = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format_Grayscale8)
|
||||
|
||||
# 4. 转换为QPixmap并显示
|
||||
pixmap = QPixmap.fromImage(q_img)
|
||||
if not pixmap.isNull():
|
||||
self.camera_label.setPixmap(pixmap)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[Error] 更新摄像头图像失败: {e}")
|
||||
# 不中断程序,继续尝试
|
||||
|
||||
def resizeEvent(self, event):
|
||||
"""
|
||||
窗口大小变化时,同步调整摄像头显示Label的大小
|
||||
"""
|
||||
super().resizeEvent(event)
|
||||
if self.camera_label is not None and self.ui.fraCamera0 is not None:
|
||||
self.camera_label.setGeometry(0, 0, self.ui.fraCamera0.width(), self.ui.fraCamera0.height())
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""
|
||||
关闭窗口时释放摄像头资源(增强版)
|
||||
"""
|
||||
# 停止定时器
|
||||
if self.timer is not None and self.timer.isActive():
|
||||
self.timer.stop()
|
||||
self.timer.deleteLater()
|
||||
self.timer = None
|
||||
|
||||
# 释放摄像头资源
|
||||
if self.cam0 is not None:
|
||||
self.cam0._close()
|
||||
self.cam0 = None
|
||||
|
||||
if self.cam1 is not None:
|
||||
self.cam1._close()
|
||||
self.cam1 = None
|
||||
|
||||
event.accept()
|
||||
162
wndMain/pageAutoPage/uiSub_AutoPage.py
Normal file
162
wndMain/pageAutoPage/uiSub_AutoPage.py
Normal file
@ -0,0 +1,162 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'uiSub_AutoPage.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 (QApplication, QFrame, QGroupBox, QHBoxLayout,
|
||||
QLabel, QProgressBar, QPushButton, QSizePolicy,
|
||||
QTabWidget, QTextEdit, QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_pageAutoProc(object):
|
||||
def setupUi(self, pageAutoProc):
|
||||
if not pageAutoProc.objectName():
|
||||
pageAutoProc.setObjectName(u"pageAutoProc")
|
||||
pageAutoProc.resize(1696, 1262)
|
||||
self.tabProc = QTabWidget(pageAutoProc)
|
||||
self.tabProc.setObjectName(u"tabProc")
|
||||
self.tabProc.setGeometry(QRect(10, 10, 1041, 691))
|
||||
self.tab_8 = QWidget()
|
||||
self.tab_8.setObjectName(u"tab_8")
|
||||
self.widget = QWidget(self.tab_8)
|
||||
self.widget.setObjectName(u"widget")
|
||||
self.widget.setGeometry(QRect(30, 50, 951, 571))
|
||||
self.verticalLayout = QVBoxLayout(self.widget)
|
||||
self.verticalLayout.setObjectName(u"verticalLayout")
|
||||
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.horizontalLayout = QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(u"horizontalLayout")
|
||||
self.grpCamera0 = QGroupBox(self.widget)
|
||||
self.grpCamera0.setObjectName(u"grpCamera0")
|
||||
self.fraCamera0 = QFrame(self.grpCamera0)
|
||||
self.fraCamera0.setObjectName(u"fraCamera0")
|
||||
self.fraCamera0.setGeometry(QRect(20, 40, 421, 231))
|
||||
self.fraCamera0.setFrameShape(QFrame.Shape.StyledPanel)
|
||||
self.fraCamera0.setFrameShadow(QFrame.Shadow.Raised)
|
||||
|
||||
self.horizontalLayout.addWidget(self.grpCamera0)
|
||||
|
||||
self.grpCamera1 = QGroupBox(self.widget)
|
||||
self.grpCamera1.setObjectName(u"grpCamera1")
|
||||
self.fraCamera1 = QFrame(self.grpCamera1)
|
||||
self.fraCamera1.setObjectName(u"fraCamera1")
|
||||
self.fraCamera1.setGeometry(QRect(20, 40, 441, 231))
|
||||
self.fraCamera1.setFrameShape(QFrame.Shape.StyledPanel)
|
||||
self.fraCamera1.setFrameShadow(QFrame.Shadow.Raised)
|
||||
|
||||
self.horizontalLayout.addWidget(self.grpCamera1)
|
||||
|
||||
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
|
||||
self.horizontalLayout_2 = QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
|
||||
self.grpOperate = QGroupBox(self.widget)
|
||||
self.grpOperate.setObjectName(u"grpOperate")
|
||||
self.btnProcStart = QPushButton(self.grpOperate)
|
||||
self.btnProcStart.setObjectName(u"btnProcStart")
|
||||
self.btnProcStart.setGeometry(QRect(60, 41, 110, 50))
|
||||
self.btnProcStart.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
|
||||
self.btnProcStop = QPushButton(self.grpOperate)
|
||||
self.btnProcStop.setObjectName(u"btnProcStop")
|
||||
self.btnProcStop.setEnabled(False)
|
||||
self.btnProcStop.setGeometry(QRect(60, 110, 110, 50))
|
||||
self.btnProcStop.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
|
||||
self.btnReset = QPushButton(self.grpOperate)
|
||||
self.btnReset.setObjectName(u"btnReset")
|
||||
self.btnReset.setGeometry(QRect(60, 180, 110, 50))
|
||||
self.btnReset.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.grpOperate)
|
||||
|
||||
self.grpWaste = QGroupBox(self.widget)
|
||||
self.grpWaste.setObjectName(u"grpWaste")
|
||||
self.lblWaste = QLabel(self.grpWaste)
|
||||
self.lblWaste.setObjectName(u"lblWaste")
|
||||
self.lblWaste.setGeometry(QRect(20, 60, 81, 16))
|
||||
self.editWaste = QTextEdit(self.grpWaste)
|
||||
self.editWaste.setObjectName(u"editWaste")
|
||||
self.editWaste.setGeometry(QRect(110, 50, 81, 31))
|
||||
self.btnWasteZero = QPushButton(self.grpWaste)
|
||||
self.btnWasteZero.setObjectName(u"btnWasteZero")
|
||||
self.btnWasteZero.setGeometry(QRect(20, 120, 111, 51))
|
||||
self.pgbWaste = QProgressBar(self.grpWaste)
|
||||
self.pgbWaste.setObjectName(u"pgbWaste")
|
||||
self.pgbWaste.setGeometry(QRect(110, 150, 151, 91))
|
||||
self.pgbWaste.setLayoutDirection(Qt.LayoutDirection.LeftToRight)
|
||||
self.pgbWaste.setValue(24)
|
||||
self.pgbWaste.setOrientation(Qt.Orientation.Vertical)
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.grpWaste)
|
||||
|
||||
self.grpInfo = QGroupBox(self.widget)
|
||||
self.grpInfo.setObjectName(u"grpInfo")
|
||||
self.tabInfo = QTabWidget(self.grpInfo)
|
||||
self.tabInfo.setObjectName(u"tabInfo")
|
||||
self.tabInfo.setGeometry(QRect(20, 30, 191, 211))
|
||||
self.tab_9 = QWidget()
|
||||
self.tab_9.setObjectName(u"tab_9")
|
||||
self.tabInfo.addTab(self.tab_9, "")
|
||||
self.tab_13 = QWidget()
|
||||
self.tab_13.setObjectName(u"tab_13")
|
||||
self.tabInfo.addTab(self.tab_13, "")
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.grpInfo)
|
||||
|
||||
self.grpType = QGroupBox(self.widget)
|
||||
self.grpType.setObjectName(u"grpType")
|
||||
self.fraType = QFrame(self.grpType)
|
||||
self.fraType.setObjectName(u"fraType")
|
||||
self.fraType.setGeometry(QRect(20, 30, 191, 201))
|
||||
self.fraType.setFrameShape(QFrame.Shape.StyledPanel)
|
||||
self.fraType.setFrameShadow(QFrame.Shadow.Raised)
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.grpType)
|
||||
|
||||
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||
|
||||
self.tabProc.addTab(self.tab_8, "")
|
||||
self.tab_14 = QWidget()
|
||||
self.tab_14.setObjectName(u"tab_14")
|
||||
self.tabProc.addTab(self.tab_14, "")
|
||||
|
||||
self.retranslateUi(pageAutoProc)
|
||||
|
||||
self.tabProc.setCurrentIndex(0)
|
||||
self.tabInfo.setCurrentIndex(0)
|
||||
|
||||
|
||||
QMetaObject.connectSlotsByName(pageAutoProc)
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, pageAutoProc):
|
||||
pageAutoProc.setWindowTitle("")
|
||||
self.grpCamera0.setTitle(QCoreApplication.translate("pageAutoProc", u"\u76f8\u673a0", None))
|
||||
self.grpCamera1.setTitle(QCoreApplication.translate("pageAutoProc", u"\u76f8\u673a1", None))
|
||||
self.grpOperate.setTitle(QCoreApplication.translate("pageAutoProc", u"\u64cd\u4f5c\u4f5c\u4e1a", None))
|
||||
self.btnProcStart.setText(QCoreApplication.translate("pageAutoProc", u"\u542f\u52a8\u7801\u579b\u4f5c\u4e1a", None))
|
||||
self.btnProcStop.setText(QCoreApplication.translate("pageAutoProc", u"\u505c\u6b62\u7801\u579b\u4f5c\u4e1a", None))
|
||||
self.btnReset.setText(QCoreApplication.translate("pageAutoProc", u"\u8bbe\u5907\u590d\u4f4d", None))
|
||||
self.grpWaste.setTitle(QCoreApplication.translate("pageAutoProc", u"\u5e9f\u6599\u533a\u72b6\u6001", None))
|
||||
self.lblWaste.setText(QCoreApplication.translate("pageAutoProc", u"\u5f53\u524d\u5e9f\u6599\u4e2a\u6570\uff1a", None))
|
||||
self.btnWasteZero.setText(QCoreApplication.translate("pageAutoProc", u"\u5e9f\u6599\u533a\u6e05\u96f6", None))
|
||||
self.grpInfo.setTitle(QCoreApplication.translate("pageAutoProc", u"\u4f5c\u4e1a\u4fe1\u606f", None))
|
||||
self.tabInfo.setTabText(self.tabInfo.indexOf(self.tab_9), QCoreApplication.translate("pageAutoProc", u"\u6d41\u7a0b\u4fe1\u606f", None))
|
||||
self.tabInfo.setTabText(self.tabInfo.indexOf(self.tab_13), QCoreApplication.translate("pageAutoProc", u"\u62a5\u8b66\u4fe1\u606f", None))
|
||||
self.grpType.setTitle(QCoreApplication.translate("pageAutoProc", u"\u7ebf\u6761\u7c7b\u578b", None))
|
||||
self.tabProc.setTabText(self.tabProc.indexOf(self.tab_8), QCoreApplication.translate("pageAutoProc", u"\u4f5c\u4e1a\u4fe1\u606f0", None))
|
||||
self.tabProc.setTabText(self.tabProc.indexOf(self.tab_14), QCoreApplication.translate("pageAutoProc", u"\u4f5c\u4e1a\u4fe1\u606f1", None))
|
||||
# retranslateUi
|
||||
|
||||
Reference in New Issue
Block a user