Files

223 lines
7.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 自动作业内嵌页面子类
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界面将当前业务类实例传入setupUiUI组件成为实例属性
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()