# 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, TransparentPushButton, EditableComboBox, PrimaryPushButton, Slider, DisplayLabel, TextBrowser, SwitchButton, PillPushButton, ToggleButton, ) from .gallery_interface import GalleryInterface from ..common.translator import Translator from ..common.style_sheet import StyleSheet import cv2 class SystemInterface(GalleryInterface): """Navigation view interface""" def __init__(self, parent=None): t = Translator() super().__init__( title=t.navigation, subtitle="qfluentwidgets.components.navigation", parent=parent, ) self.setObjectName("systemInterface") # 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) # clock self.clock = TransparentPushButton( "2025-08-04 16:55", self, FluentIcon.DATE_TIME ) # combo box self.comboBox1 = ComboBox() self.comboBox1.addItems(["反应釜1", "反应釜2"]) self.comboBox1.setCurrentIndex(0) self.comboBox1.setMinimumWidth(180) # label self.label = QLabel("自定义数量", self) # editable combo box self.comboBox = EditableComboBox() self.comboBox.addItems( [ "10", "20", "30", "40", "50", "60", "70", "80", ] ) self.comboBox.setPlaceholderText("自定义数量") self.comboBox.setMinimumWidth(90) # hBoxLayout self.container1 = QWidget() self.hBoxLayout1 = QHBoxLayout(self.container1) self.hBoxLayout1.addWidget(self.label) self.hBoxLayout1.addWidget(self.comboBox) # button self.primaryButton1 = PrimaryPushButton(FluentIcon.PLAY, "启动", self) self.primaryButton2 = PrimaryPushButton(FluentIcon.PAUSE, "暂停", self) self.primaryButton3 = PrimaryPushButton(FluentIcon.POWER_BUTTON, "停止", self) self.primaryButton4 = PrimaryPushButton(FluentIcon.ROTATE, "复位", self) self.primaryButton5 = PrimaryPushButton(FluentIcon.CLOSE, "急停", self) self.primaryButton6 = PrimaryPushButton(FluentIcon.SYNC, "清除", self) self.primaryButton1.setObjectName("primaryButton1") self.primaryButton2.setObjectName("primaryButton2") self.primaryButton3.setObjectName("primaryButton3") self.primaryButton4.setObjectName("primaryButton4") self.primaryButton5.setObjectName("primaryButton5") self.primaryButton6.setObjectName("primaryButton6") # hBoxLayout2 self.container2 = QWidget() self.hBoxLayout2 = QHBoxLayout(self.container2) self.hBoxLayout2.addWidget(self.primaryButton1) self.hBoxLayout2.addWidget(self.primaryButton2) # hBoxLayout3 self.container3 = QWidget() self.hBoxLayout3 = QHBoxLayout(self.container3) self.hBoxLayout3.addWidget(self.primaryButton3) self.hBoxLayout3.addWidget(self.primaryButton4) # hBoxLayout4 self.container4 = QWidget() self.hBoxLayout4 = QHBoxLayout(self.container4) self.hBoxLayout4.addWidget(self.primaryButton5) self.hBoxLayout4.addWidget(self.primaryButton6) # 滑动条 self.slider = Slider(Qt.Horizontal) self.slider.setFixedWidth(200) # 设置取值范围和当前值 self.slider.setRange(0, 50) self.slider.setValue(20) # Displaylabel self.label2 = DisplayLabel("目标袋数") self.label3 = DisplayLabel("0") self.label3.setObjectName("label3") self.label3.setStyleSheet("color: red;") self.label4 = DisplayLabel("剩余袋数") self.label5 = DisplayLabel("0") self.label5.setObjectName("label5") self.label5.setStyleSheet("color: green;") # hBoxLayout self.container5 = QWidget() self.hBoxLayout5 = QHBoxLayout(self.container5) self.hBoxLayout5.addWidget(self.label2) self.hBoxLayout5.addWidget(self.label3) # hBoxLayout self.container6 = QWidget() self.hBoxLayout6 = QHBoxLayout(self.container6) self.hBoxLayout6.addWidget(self.label4) self.hBoxLayout6.addWidget(self.label5) # 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) self.vBoxLayout = QVBoxLayout(self.tabView) self.panelLayout = QVBoxLayout(self.controlPanel) # 富文本编辑栏用来显示日志 self.textBrowser = TextBrowser() # self.textBrowser.setMarkdown("## Steel Ball Run \n * Johnny Joestar 🦄 \n * Gyro Zeppeli 🐴 aaa\n * aaa\n * aaa\n * aaa\n * aaa\n *") self.textBrowser.setMarkdown( "## 日志\n * 2025-08-06 09:54:24 - 🦄进入系统\n * 2025-08-06 09:54:24 - 🐴无回复\n * 2025-08-06 09:54:24 - 🦄进入系统\n * 2025-08-06 09:54:24 - 🐴无回复\n * 2025-08-06 09:54:24 - 🦄进入系统\n * 2025-08-06 09:54:24 - 🐴无回复\n * 2025-08-06 09:54:24 - 🦄进入系统\n * 2025-08-06 09:54:24 - 🐴无回复\n *" ) # 日志切换按钮 self.button = SwitchButton() # self.button.checkedChanged.connect( # lambda checked: print("是否选中按钮:", checked) # ) # 更改按钮状态 self.button.setChecked(True) # 获取按钮是否选中 self.button.setOffText("报警") self.button.setOnText("日志") # 状态按钮 # PillPushButton(self.tr('Tag'), self, FluentIcon.TAG), self.state_button1 = PillPushButton() self.state_button1.setFixedHeight(15) self.state_button1.setFixedWidth(100) self.state_button2 = PillPushButton("1", self, "") self.state_button2.setFixedHeight(15) self.state_button2.setFixedWidth(100) self.state_button3 = PillPushButton("0", self, "") self.state_button3.setFixedHeight(15) self.state_button3.setFixedWidth(100) self.state_button4 = PillPushButton() self.state_button4.setFixedHeight(15) self.state_button4.setFixedWidth(100) self.state_button5 = PillPushButton("0", self, "") self.state_button5.setFixedHeight(15) self.state_button5.setFixedWidth(100) self.state_button6 = PillPushButton("0", self, "") self.state_button6.setFixedHeight(15) self.state_button6.setFixedWidth(100) self.state1 = DisplayLabel("连接状态:") self.state2 = DisplayLabel("当前模式:") self.state3 = DisplayLabel("远程指令数量:") self.state4 = DisplayLabel("当前速度:") self.state5 = DisplayLabel("当前工具号:") self.state6 = DisplayLabel("报警代码:") # 状态hBoxLayout self.state_container1 = QWidget() self.state_hBoxLayout1 = QHBoxLayout(self.state_container1) self.state_hBoxLayout1.addWidget(self.state1) self.state_hBoxLayout1.addWidget(self.state_button1) self.state_container2 = QWidget() self.state_hBoxLayout2 = QHBoxLayout(self.state_container2) self.state_hBoxLayout2.addWidget(self.state2) self.state_hBoxLayout2.addWidget(self.state_button2) self.state_container3 = QWidget() self.state_hBoxLayout3 = QHBoxLayout(self.state_container3) self.state_hBoxLayout3.addWidget(self.state3) self.state_hBoxLayout3.addWidget(self.state_button3) self.state_container4 = QWidget() self.state_hBoxLayout4 = QHBoxLayout(self.state_container4) self.state_hBoxLayout4.addWidget(self.state4) self.state_hBoxLayout4.addWidget(self.state_button4) self.state_container5 = QWidget() self.state_hBoxLayout5 = QHBoxLayout(self.state_container5) self.state_hBoxLayout5.addWidget(self.state5) self.state_hBoxLayout5.addWidget(self.state_button5) self.state_container6 = QWidget() self.state_hBoxLayout6 = QHBoxLayout(self.state_container6) self.state_hBoxLayout6.addWidget(self.state6) self.state_hBoxLayout6.addWidget(self.state_button6) # 日志vboxlayout self.container7 = QWidget() self.vBoxLayout7 = QVBoxLayout(self.container7) self.vBoxLayout7.addWidget(self.button) self.vBoxLayout7.addWidget(self.textBrowser) # 状态vboxlayout self.container9 = QWidget() self.vBoxLayout9 = QVBoxLayout(self.container9) self.vBoxLayout9.addWidget(self.state_container1) self.vBoxLayout9.addWidget(self.state_container2) self.vBoxLayout9.addWidget(self.state_container3) self.vBoxLayout9.addWidget(self.state_container4) self.vBoxLayout9.addWidget(self.state_container5) self.vBoxLayout9.addWidget(self.state_container6) # 日志+状态vboxlayout self.container8 = QWidget() self.hBoxLayout8 = QHBoxLayout(self.container8) self.hBoxLayout8.addWidget(self.container7) self.hBoxLayout8.addWidget(self.container9) # self.songInterface = QLabel('Song Interface', self) # self.albumInterface = QLabel('Album Interface', self) # self.artistInterface = QLabel('Artist Interface', self) # add items to pivot self.__initWidget() 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.SYSTEM_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.setMaximumSize(787, 800) self.setMinimumSize(450, 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.clock) self.panelLayout.addStretch() self.panelLayout.addWidget(self.comboBox1) self.panelLayout.addStretch() self.panelLayout.addWidget(self.container1) self.panelLayout.addStretch() self.panelLayout.addWidget(self.container2) self.panelLayout.addStretch() self.panelLayout.addWidget(self.container3) self.panelLayout.addStretch() self.panelLayout.addWidget(self.container4) self.panelLayout.addStretch() self.panelLayout.addWidget(self.slider) self.panelLayout.addStretch() self.panelLayout.addWidget(self.container5) self.panelLayout.addStretch() self.panelLayout.addWidget(self.container6) self.panelLayout.addStretch() # 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) # 左边窗口 # 创建加载框 # self.loading_button1=ToggleButton(self.tr('Start practicing'), self, FluentIcon.BASKETBALL) self.loading_button1 = ToggleButton() self.loading_button2 = ToggleButton() self.loading_button3 = ToggleButton() self.loading_button4 = ToggleButton() self.loading1 = DisplayLabel("取料中...") self.loading2 = DisplayLabel("拍照中...") self.loading3 = DisplayLabel("抓料中...") self.loading4 = DisplayLabel("投料中...") self.loading_container = QWidget() self.loading_hBoxLayout = QHBoxLayout(self.loading_container) self.loading_hBoxLayout.addWidget(self.loading_button1) self.loading_hBoxLayout.addWidget(self.loading1) self.loading_hBoxLayout.addWidget(self.loading_button2) self.loading_hBoxLayout.addWidget(self.loading2) self.loading_hBoxLayout.addWidget(self.loading_button3) self.loading_hBoxLayout.addWidget(self.loading3) self.loading_hBoxLayout.addWidget(self.loading_button4) self.loading_hBoxLayout.addWidget(self.loading4) self.vBoxLayout.addWidget(self.loading_container) # 创建显示视频的 QLabel self.video_label = QLabel() self.vBoxLayout.addWidget(self.video_label) # 使用 OpenCV 读取视频 self.cap = cv2.VideoCapture( "./app/resource/video/test.mp4" ) # 替换为你的视频路径 if not self.cap.isOpened(): print("无法打开视频文件!") return # 使用 QTimer 定时更新视频帧 self.timer = QTimer() self.timer.timeout.connect(self.update_frame) self.timer.start(30) # 30ms 更新一帧(约 33 FPS) # self.vBoxLayout.addWidget() # 左边窗口下面的日志栏位和状态栏 self.vBoxLayout.addWidget(self.container8) 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_frame(self): ret, frame = self.cap.read() if not ret: self.timer.stop() self.cap.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_label.setPixmap( pixmap.scaled(self.video_label.size()) ) # 自适应窗口大小