336 lines
13 KiB
Python
336 lines
13 KiB
Python
|
|
# coding:utf-8
|
|||
|
|
from PySide6.QtCore import Qt, QEasingCurve, QTimer
|
|||
|
|
from PySide6.QtGui import QColor, QImage, QPixmap
|
|||
|
|
from PySide6.QtWidgets import QWidget, QStackedWidget, QVBoxLayout, QLabel, QHBoxLayout, QFrame, QSizePolicy
|
|||
|
|
from qfluentwidgets import (Pivot, qrouter, SegmentedWidget, TabBar, CheckBox, ComboBox,
|
|||
|
|
TabCloseButtonDisplayMode, BodyLabel, SpinBox, BreadcrumbBar,
|
|||
|
|
SegmentedToggleToolWidget, FluentIcon, LineEdit, PrimaryPushButton, PillPushButton, DisplayLabel)
|
|||
|
|
|
|||
|
|
from .gallery_interface import GalleryInterface
|
|||
|
|
from ..common.translator import Translator
|
|||
|
|
from ..common.style_sheet import StyleSheet
|
|||
|
|
import cv2
|
|||
|
|
|
|||
|
|
class DataInterface(GalleryInterface):
|
|||
|
|
""" Navigation view interface """
|
|||
|
|
|
|||
|
|
def __init__(self, parent=None):
|
|||
|
|
t = Translator()
|
|||
|
|
super().__init__(
|
|||
|
|
title=t.navigation,
|
|||
|
|
subtitle="qfluentwidgets.components.navigation",
|
|||
|
|
parent=parent
|
|||
|
|
)
|
|||
|
|
self.setObjectName('dataInterface')
|
|||
|
|
|
|||
|
|
# breadcrumb bar
|
|||
|
|
|
|||
|
|
card = self.addExampleCard(
|
|||
|
|
title=self.tr(''),
|
|||
|
|
widget=TabInterface(self),
|
|||
|
|
sourcePath='https://github.com/zhiyiYo/PyQt-Fluent-Widgets/blob/PySide6/examples/navigation/tab_view/demo.py',
|
|||
|
|
stretch=1
|
|||
|
|
)
|
|||
|
|
card.topLayout.setContentsMargins(12, 0, 0, 0)
|
|||
|
|
|
|||
|
|
def createToggleToolWidget(self):
|
|||
|
|
w = SegmentedToggleToolWidget(self)
|
|||
|
|
w.addItem('k1', FluentIcon.TRANSPARENT)
|
|||
|
|
w.addItem('k2', FluentIcon.CHECKBOX)
|
|||
|
|
w.addItem('k3', FluentIcon.CONSTRACT)
|
|||
|
|
w.setCurrentItem('k1')
|
|||
|
|
return w
|
|||
|
|
|
|||
|
|
class TabInterface(QWidget):
|
|||
|
|
""" Tab interface """
|
|||
|
|
|
|||
|
|
def __init__(self, parent=None):
|
|||
|
|
super().__init__(parent=parent)
|
|||
|
|
self.tabCount = 1
|
|||
|
|
|
|||
|
|
# self.tabBar = TabBar(self)
|
|||
|
|
# self.stackedWidget = QStackedWidget(self)
|
|||
|
|
self.tabView = QWidget(self)
|
|||
|
|
self.controlPanel = QFrame(self)
|
|||
|
|
|
|||
|
|
#self.movableCheckBox = CheckBox(self.tr('IsTabMovable'), self)
|
|||
|
|
#self.scrollableCheckBox = CheckBox(self.tr('IsTabScrollable'), self)
|
|||
|
|
#self.shadowEnabledCheckBox = CheckBox(self.tr('IsTabShadowEnabled'), self)
|
|||
|
|
#self.tabMaxWidthLabel = BodyLabel(self.tr('TabMaximumWidth'), self)
|
|||
|
|
# self.tabMaxWidthSpinBox = SpinBox(self)
|
|||
|
|
#self.closeDisplayModeLabel = BodyLabel(self.tr('TabCloseButtonDisplayMode'), self)
|
|||
|
|
#self.closeDisplayModeComboBox = ComboBox(self)
|
|||
|
|
|
|||
|
|
self.hBoxLayout = QHBoxLayout(self)
|
|||
|
|
|
|||
|
|
######################界面1
|
|||
|
|
self.video_label1 = QLabel()
|
|||
|
|
self.video_label1.setFixedHeight(500)
|
|||
|
|
# self.vBoxLayout.addWidget(self.video_label1)
|
|||
|
|
|
|||
|
|
# 使用 OpenCV 读取视频
|
|||
|
|
self.cap1 = cv2.VideoCapture("./app/resource/video/test.mp4") # 替换为你的视频路径
|
|||
|
|
if not self.cap1.isOpened():
|
|||
|
|
print("无法打开视频文件!")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 使用 QTimer 定时更新视频帧
|
|||
|
|
self.timer1 = QTimer()
|
|||
|
|
self.timer1.timeout.connect(self.update_frame1)
|
|||
|
|
self.timer1.start(30) # 30ms 更新一帧(约 33 FPS)
|
|||
|
|
|
|||
|
|
######################界面2
|
|||
|
|
self.video_label2 = QLabel()
|
|||
|
|
self.video_label2.setFixedHeight(500)
|
|||
|
|
# self.vBoxLayout.addWidget(self.video_label1)
|
|||
|
|
|
|||
|
|
# 使用 OpenCV 读取视频
|
|||
|
|
self.cap2 = cv2.VideoCapture("./app/resource/video/test.mp4") # 替换为你的视频路径
|
|||
|
|
if not self.cap2.isOpened():
|
|||
|
|
print("无法打开视频文件!")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 使用 QTimer 定时更新视频帧
|
|||
|
|
self.timer2 = QTimer()
|
|||
|
|
self.timer2.timeout.connect(self.update_frame2)
|
|||
|
|
self.timer2.start(30) # 30ms 更新一帧(约 33 FPS)
|
|||
|
|
|
|||
|
|
#操作按钮1
|
|||
|
|
self.lineEdit1 = LineEdit()
|
|||
|
|
# 设置提示文本
|
|||
|
|
self.lineEdit1.setPlaceholderText("请输入存储路径")
|
|||
|
|
# 设置文本
|
|||
|
|
self.lineEdit1.setText("/userdata/camera01")
|
|||
|
|
# print(self.lineEdit1.text())
|
|||
|
|
# 启用清空按钮
|
|||
|
|
self.lineEdit1.setClearButtonEnabled(True)
|
|||
|
|
|
|||
|
|
#操作按钮2
|
|||
|
|
self.lineEdit2 = LineEdit()
|
|||
|
|
# 设置提示文本
|
|||
|
|
self.lineEdit2.setPlaceholderText("请输入存储路径")
|
|||
|
|
# 设置文本
|
|||
|
|
self.lineEdit2.setText("/userdata/camera02")
|
|||
|
|
# print(self.lineEdit1.text())
|
|||
|
|
# 启用清空按钮
|
|||
|
|
self.lineEdit2.setClearButtonEnabled(True)
|
|||
|
|
|
|||
|
|
#启动按钮1
|
|||
|
|
self.start_button1=PrimaryPushButton(FluentIcon.PLAY, '开始采集')
|
|||
|
|
#停止按钮1
|
|||
|
|
self.stop_button1=PrimaryPushButton(FluentIcon.PAUSE, '停止采集')
|
|||
|
|
|
|||
|
|
#启动按钮2
|
|||
|
|
self.start_button2=PrimaryPushButton(FluentIcon.PLAY, '开始采集')
|
|||
|
|
#停止按钮2
|
|||
|
|
self.stop_button2=PrimaryPushButton(FluentIcon.PAUSE, '停止采集')
|
|||
|
|
|
|||
|
|
# Displaylabel
|
|||
|
|
self.label1 = DisplayLabel("存储路径")
|
|||
|
|
self.label2 = DisplayLabel("存储路径")
|
|||
|
|
self.label3 = DisplayLabel("")
|
|||
|
|
self.label4 = DisplayLabel("")
|
|||
|
|
|
|||
|
|
#hBoxLayout
|
|||
|
|
self.hcontainer1 = QWidget()
|
|||
|
|
self.hBoxLayout1 = QHBoxLayout(self.hcontainer1)
|
|||
|
|
self.hBoxLayout1.addWidget(self.label1)
|
|||
|
|
self.hBoxLayout1.addWidget(self.lineEdit1)
|
|||
|
|
|
|||
|
|
self.hcontainer2 = QWidget()
|
|||
|
|
self.hBoxLayout2 = QHBoxLayout(self.hcontainer2)
|
|||
|
|
self.hBoxLayout2.addWidget(self.label2)
|
|||
|
|
self.hBoxLayout2.addWidget(self.lineEdit2)
|
|||
|
|
|
|||
|
|
#布局
|
|||
|
|
self.container1 = QWidget()
|
|||
|
|
self.hBoxLayout1 = QVBoxLayout(self.container1)
|
|||
|
|
self.hBoxLayout1.addWidget(self.video_label1)
|
|||
|
|
self.hBoxLayout1.addWidget(self.hcontainer1)
|
|||
|
|
self.hBoxLayout1.addWidget(self.start_button1)
|
|||
|
|
self.hBoxLayout1.addWidget(self.stop_button1)
|
|||
|
|
self.container1.setMaximumSize(400, 500)
|
|||
|
|
self.container1.setMinimumSize(300, 200)
|
|||
|
|
|
|||
|
|
self.container2 = QWidget()
|
|||
|
|
self.hBoxLayout2 = QVBoxLayout(self.container2)
|
|||
|
|
self.hBoxLayout2.addWidget(self.video_label2)
|
|||
|
|
self.hBoxLayout2.addWidget(self.hcontainer2)
|
|||
|
|
self.hBoxLayout2.addWidget(self.start_button2)
|
|||
|
|
self.hBoxLayout2.addWidget(self.stop_button2)
|
|||
|
|
self.container2.setMaximumSize(400, 500)
|
|||
|
|
self.container2.setMinimumSize(300, 200)
|
|||
|
|
|
|||
|
|
#左边 self.vBoxLayout 右边 self.panelLayout
|
|||
|
|
# self.vBoxLayout = QVBoxLayout(self.tabView)
|
|||
|
|
# self.panelLayout = QVBoxLayout(self.controlPanel)
|
|||
|
|
|
|||
|
|
# self.songInterface = QLabel('Song Interface', self)
|
|||
|
|
# self.albumInterface = QLabel('Album Interface', self)
|
|||
|
|
# self.artistInterface = QLabel('Artist Interface', self)
|
|||
|
|
|
|||
|
|
# add items to pivot
|
|||
|
|
# self.__initWidget()
|
|||
|
|
|
|||
|
|
self.hBoxLayout.addWidget(self.container1)
|
|||
|
|
self.hBoxLayout.addWidget(self.container2)
|
|||
|
|
|
|||
|
|
def __initWidget(self):
|
|||
|
|
self.initLayout()
|
|||
|
|
|
|||
|
|
# self.shadowEnabledCheckBox.setChecked(True)
|
|||
|
|
|
|||
|
|
# self.tabMaxWidthSpinBox.setRange(60, 400)
|
|||
|
|
#self.tabMaxWidthSpinBox.setValue(self.tabBar.tabMaximumWidth())
|
|||
|
|
|
|||
|
|
# self.closeDisplayModeComboBox.addItem(self.tr('Always'), userData=TabCloseButtonDisplayMode.ALWAYS)
|
|||
|
|
# self.closeDisplayModeComboBox.addItem(self.tr('OnHover'), userData=TabCloseButtonDisplayMode.ON_HOVER)
|
|||
|
|
# self.closeDisplayModeComboBox.addItem(self.tr('Never'), userData=TabCloseButtonDisplayMode.NEVER)
|
|||
|
|
# self.closeDisplayModeComboBox.currentIndexChanged.connect(self.onDisplayModeChanged)
|
|||
|
|
|
|||
|
|
# self.addSubInterface(self.songInterface,
|
|||
|
|
# 'tabSongInterface', self.tr('Song'), ':/gallery/images/MusicNote.png')
|
|||
|
|
# self.addSubInterface(self.albumInterface,
|
|||
|
|
# 'tabAlbumInterface', self.tr('Album'), ':/gallery/images/Dvd.png')
|
|||
|
|
# self.addSubInterface(self.artistInterface,
|
|||
|
|
# 'tabArtistInterface', self.tr('Artist'), ':/gallery/images/Singer.png')
|
|||
|
|
|
|||
|
|
self.controlPanel.setObjectName('controlPanel')
|
|||
|
|
StyleSheet.NAVIGATION_VIEW_INTERFACE.apply(self)
|
|||
|
|
|
|||
|
|
#self.connectSignalToSlot()
|
|||
|
|
|
|||
|
|
# qrouter.setDefaultRouteKey(
|
|||
|
|
# self.stackedWidget, self.songInterface.objectName())
|
|||
|
|
|
|||
|
|
# def connectSignalToSlot(self):
|
|||
|
|
# self.movableCheckBox.stateChanged.connect(
|
|||
|
|
# lambda: self.tabBar.setMovable(self.movableCheckBox.isChecked()))
|
|||
|
|
# self.scrollableCheckBox.stateChanged.connect(
|
|||
|
|
# lambda: self.tabBar.setScrollable(self.scrollableCheckBox.isChecked()))
|
|||
|
|
# self.shadowEnabledCheckBox.stateChanged.connect(
|
|||
|
|
# lambda: self.tabBar.setTabShadowEnabled(self.shadowEnabledCheckBox.isChecked()))
|
|||
|
|
|
|||
|
|
#self.tabMaxWidthSpinBox.valueChanged.connect(self.tabBar.setTabMaximumWidth)
|
|||
|
|
|
|||
|
|
# self.tabBar.tabAddRequested.connect(self.addTab)
|
|||
|
|
# self.tabBar.tabCloseRequested.connect(self.removeTab)
|
|||
|
|
|
|||
|
|
# self.stackedWidget.currentChanged.connect(self.onCurrentIndexChanged)
|
|||
|
|
|
|||
|
|
def initLayout(self):
|
|||
|
|
# self.tabBar.setTabMaximumWidth(200)
|
|||
|
|
|
|||
|
|
self.setFixedHeight(450)
|
|||
|
|
self.controlPanel.setFixedWidth(220)
|
|||
|
|
self.hBoxLayout.addWidget(self.tabView, 1)
|
|||
|
|
self.hBoxLayout.addWidget(self.controlPanel, 0, Qt.AlignRight)
|
|||
|
|
self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
|
|||
|
|
|
|||
|
|
#self.vBoxLayout.addWidget(self.tabBar)
|
|||
|
|
# self.vBoxLayout.addWidget(self.stackedWidget)
|
|||
|
|
self.vBoxLayout.setContentsMargins(0, 0, 0, 0)
|
|||
|
|
|
|||
|
|
self.panelLayout.setSpacing(8)
|
|||
|
|
self.panelLayout.setContentsMargins(14, 16, 14, 14)
|
|||
|
|
self.panelLayout.setAlignment(Qt.AlignTop)
|
|||
|
|
|
|||
|
|
# self.panelLayout.addWidget(self.movableCheckBox)
|
|||
|
|
# self.panelLayout.addWidget(self.scrollableCheckBox)
|
|||
|
|
# self.panelLayout.addWidget(self.shadowEnabledCheckBox)
|
|||
|
|
|
|||
|
|
self.panelLayout.addSpacing(4)
|
|||
|
|
# self.panelLayout.addWidget(self.tabMaxWidthLabel)
|
|||
|
|
# self.panelLayout.addWidget(self.tabMaxWidthSpinBox)
|
|||
|
|
|
|||
|
|
self.panelLayout.addSpacing(4)
|
|||
|
|
# self.panelLayout.addWidget(self.closeDisplayModeLabel)
|
|||
|
|
# self.panelLayout.addWidget(self.closeDisplayModeComboBox)
|
|||
|
|
|
|||
|
|
######################界面1
|
|||
|
|
self.video_label1 = QLabel()
|
|||
|
|
# self.vBoxLayout.addWidget(self.video_label1)
|
|||
|
|
|
|||
|
|
# 使用 OpenCV 读取视频
|
|||
|
|
self.cap1 = cv2.VideoCapture("./app/resource/video/test.mp4") # 替换为你的视频路径
|
|||
|
|
if not self.cap1.isOpened():
|
|||
|
|
print("无法打开视频文件!")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 使用 QTimer 定时更新视频帧
|
|||
|
|
self.timer1 = QTimer()
|
|||
|
|
self.timer1.timeout.connect(self.update_frame1)
|
|||
|
|
self.timer1.start(30) # 30ms 更新一帧(约 33 FPS)
|
|||
|
|
|
|||
|
|
######################界面2
|
|||
|
|
# self.video_label2 = QLabel()
|
|||
|
|
# self.vBoxLayout.addWidget(self.video_label2)
|
|||
|
|
|
|||
|
|
# # 使用 OpenCV 读取视频
|
|||
|
|
# self.cap2 = cv2.VideoCapture("./app/resource/video/test.mp4") # 替换为你的视频路径
|
|||
|
|
# if not self.cap2.isOpened():
|
|||
|
|
# print("无法打开视频文件!")
|
|||
|
|
# return
|
|||
|
|
|
|||
|
|
# # 使用 QTimer 定时更新视频帧
|
|||
|
|
# self.timer2 = QTimer()
|
|||
|
|
# self.timer2.timeout.connect(self.update_frame2)
|
|||
|
|
# self.timer2.start(30) # 30ms 更新一帧(约 33 FPS)
|
|||
|
|
|
|||
|
|
#self.vBoxLayout.addWidget(self.video_label1)
|
|||
|
|
self.panelLayout.addWidget(self.video_label1)
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
def addSubInterface(self, widget: QLabel, objectName, text, icon):
|
|||
|
|
widget.setObjectName(objectName)
|
|||
|
|
widget.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
|||
|
|
# self.stackedWidget.addWidget(widget)
|
|||
|
|
# self.tabBar.addTab(
|
|||
|
|
# routeKey=objectName,
|
|||
|
|
# text=text,
|
|||
|
|
# icon=icon,
|
|||
|
|
# onClick=lambda: self.stackedWidget.setCurrentWidget(widget)
|
|||
|
|
# )
|
|||
|
|
|
|||
|
|
# def onDisplayModeChanged(self, index):
|
|||
|
|
# mode = self.closeDisplayModeComboBox.itemData(index)
|
|||
|
|
# self.tabBar.setCloseButtonDisplayMode(mode)
|
|||
|
|
|
|||
|
|
# def onCurrentIndexChanged(self, index):
|
|||
|
|
# widget = self.stackedWidget.widget(index)
|
|||
|
|
# if not widget:
|
|||
|
|
# return
|
|||
|
|
|
|||
|
|
# self.tabBar.setCurrentTab(widget.objectName())
|
|||
|
|
# qrouter.push(self.stackedWidget, widget.objectName())
|
|||
|
|
|
|||
|
|
def update_frame1(self):
|
|||
|
|
ret, frame = self.cap1.read()
|
|||
|
|
if not ret:
|
|||
|
|
self.timer1.stop()
|
|||
|
|
self.cap1.release()
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 转换 OpenCV BGR 格式为 RGB,并调整大小以适应 QLabel
|
|||
|
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|||
|
|
h, w, ch = frame.shape
|
|||
|
|
bytes_per_line = ch * w
|
|||
|
|
q_img = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
|
|||
|
|
pixmap = QPixmap.fromImage(q_img)
|
|||
|
|
self.video_label1.setPixmap(pixmap.scaled(self.video_label1.size())) # 自适应窗口大小
|
|||
|
|
|
|||
|
|
def update_frame2(self):
|
|||
|
|
ret, frame = self.cap2.read()
|
|||
|
|
if not ret:
|
|||
|
|
self.timer2.stop()
|
|||
|
|
self.cap2.release()
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 转换 OpenCV BGR 格式为 RGB,并调整大小以适应 QLabel
|
|||
|
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|||
|
|
h, w, ch = frame.shape
|
|||
|
|
bytes_per_line = ch * w
|
|||
|
|
q_img = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
|
|||
|
|
pixmap = QPixmap.fromImage(q_img)
|
|||
|
|
self.video_label2.setPixmap(pixmap.scaled(self.video_label2.size())) # 自适应窗口大小
|