0


yolo自动化项目实例解析(六)自建UI(主窗口、预览窗口)

前面我们大致把各个代码块梳理出来了,但是得到的信息非常杂乱,一大堆的代码,不知道怎么来的ui,那个拷贝的datas也没说是什么情况,对于我们没有怎么整过ui的来说阅读非常困难,所以在开始之前我们先需要学习一些关于ui的知识点,然后在通过ui页面的元素去推理整个执行过程,我们首先需要知道ui功能里面有那些组件

qt设计师基础控件

Qt Designer 是一个图形界面设计工具,用于创建 Qt 应用程序的用户界面。它提供了丰富的控件(也称为窗口部件或widgets)来构建各种类型的用户界面

类型窗口部件说明基础控件QLabel显示静态文本或图像基础控件QPushButton用户可以点击的按钮基础控件QLineEdit单行文本输入框基础控件QTextEdit多行文本编辑器基础控件QCheckBox复选框,用户可以选择或取消选择基础控件QRadioButton单选按钮,用于一组互斥的选择项基础控件QComboBox下拉列表框,用户可以从列表中选择一项基础控件QSlider滑块控件,用于数值的选择范围基础控件QSpinBox/QDoubleSpinBox数字输入框,用户可以输入整数或浮点数基础控件QProgressBar进度条,显示任务完成的进度基础控件QToolButton工具按钮,常用于工具栏上,支持弹出菜单基础控件QGraphicsView图形视图,用于显示复杂的图形场景布局管理器QVBoxLayout垂直布局管理器,用于管理控件的垂直排列布局管理器QHBoxLayout水平布局管理器,用于管理控件的水平排列布局管理器QGridLayout网格布局管理器,用于将控件放置在网格单元格中布局管理器QFormLayout表单布局管理器,用于创建标签和控件成对出现的布局布局管理器QStackedLayout堆叠布局管理器,用于堆叠多个控件,一次只显示一个容器QWidget最基础的窗口部件,可以包含其他控件容器QFrame带边框的容器,可以设置不同的样式容器QGroupBox带标题的框架,常用于分组控件容器QTabWidget带标签页的容器,允许用户在多个页面之间切换容器QScrollArea滚动区域,当内容超过显示区域时提供滚动条容器QDockWidget码头窗口,通常用于显示附加信息或工具对话框QMessageBox提示信息对话框,用于显示警告、错误等消息对话框QFileDialog文件对话框,用于选择文件或目录对话框QColorDialog颜色选择对话框,用于选取颜色对话框QFontDialog字体选择对话框,用于选取字体其他QMenuBar菜单栏,通常位于窗口顶部其他QToolBar工具栏,通常包含一些快捷按钮其他QStatusBar状态栏,显示临时的消息

我们打开窗口的时候会发现中间有一块显示大屏,如下

我们先看看怎么实现这个大屏显示,打开qt设计师

新建项目目录

我们先不在原本的项目上找,先根据已有的信息参考源代码进行推断

一、添加主窗口

1、主窗口、窗口大小、标题

1、打开Qt Designer。 (命令designer)
2、选择“文件” > “新建”,创建一个新的Qt Designer文档。
3、在“选择类”对话框中,选择QMainWindow作为基础类,并命名为mainWindow。

4、添加布局,layouts--Horizontal layouts--- 添加后选择类名右键--布局--水平布局,然后将我们刚才添加的Horizontal layouts删除
5、设置窗口大小(geometry关键字)为800x600像素,并设置窗口标题(windowTitle)为 "主页"

6、添加容器空间containers--scroll area 直接拖到窗口会自动根据水平进行布局

(后面才知道步骤4添加布局的时候,其实不是非得用对应的Horizontal layouts才能添加水平布局,我们任意仍个组件上去就可以右键设置主窗口的布局了)

2、添加工具栏、移除菜单栏

3、组件重命名

  1. mainWindow
  2. centralwidget
  3. sa_main
  4. scrollAreaWidgetContents
  5. sb_main
  6. toolBar

这里我们给布局内的各个元素重命名后,我们在ui转py会转换为各个关键字方便使用

4、布局重命名

我们在上面中,给主窗口添加了一个水平布局,这个布局也是有名称的,如果存在多个布局需要区分开,这里我们要查看下布局是什么名称,如果和下图不一样统一修改

5、工具栏调整到侧边

6、添加动作、ui转py

  1. #动作文本名称如下
  2. Save_All
  3. Add_Mode
  4. Add_Script

ui转换

  1. pyuic5 -o main.py main.ui

ui/main.py

  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file 'main.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.15.11
  5. #
  6. # WARNING: Any manual changes made to this file will be lost when pyuic5 is
  7. # run again. Do not edit this file unless you know what you are doing.
  8. from PyQt5 import QtCore, QtGui, QtWidgets
  9. class Ui_mainWindow(object):
  10. def setupUi(self, mainWindow):
  11. mainWindow.setObjectName("mainWindow")
  12. mainWindow.resize(800, 600)
  13. self.centralwidget = QtWidgets.QWidget(mainWindow)
  14. self.centralwidget.setObjectName("centralwidget")
  15. self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
  16. self.horizontalLayout.setObjectName("horizontalLayout")
  17. self.sa_main = QtWidgets.QScrollArea(self.centralwidget)
  18. self.sa_main.setWidgetResizable(True)
  19. self.sa_main.setObjectName("sa_main")
  20. self.scrollAreaWidgetContents = QtWidgets.QWidget()
  21. self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 762, 551))
  22. self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
  23. self.sa_main.setWidget(self.scrollAreaWidgetContents)
  24. self.horizontalLayout.addWidget(self.sa_main)
  25. mainWindow.setCentralWidget(self.centralwidget)
  26. self.sb_main = QtWidgets.QStatusBar(mainWindow)
  27. self.sb_main.setObjectName("sb_main")
  28. mainWindow.setStatusBar(self.sb_main)
  29. self.toolBar = QtWidgets.QToolBar(mainWindow)
  30. self.toolBar.setObjectName("toolBar")
  31. mainWindow.addToolBar(QtCore.Qt.LeftToolBarArea, self.toolBar)
  32. self.actionSave_All = QtWidgets.QAction(mainWindow)
  33. self.actionSave_All.setObjectName("actionSave_All")
  34. self.actionAdd_Mode = QtWidgets.QAction(mainWindow)
  35. self.actionAdd_Mode.setObjectName("actionAdd_Mode")
  36. self.actionAdd_Script = QtWidgets.QAction(mainWindow)
  37. self.actionAdd_Script.setObjectName("actionAdd_Script")
  38. self.retranslateUi(mainWindow)
  39. QtCore.QMetaObject.connectSlotsByName(mainWindow)
  40. def retranslateUi(self, mainWindow):
  41. _translate = QtCore.QCoreApplication.translate
  42. mainWindow.setWindowTitle(_translate("mainWindow", "主页"))
  43. self.toolBar.setWindowTitle(_translate("mainWindow", "toolBar"))
  44. self.actionSave_All.setText(_translate("mainWindow", "Save_All "))
  45. self.actionAdd_Mode.setText(_translate("mainWindow", "Add_Mode "))
  46. self.actionAdd_Script.setText(_translate("mainWindow", "Add_Script"))

7、打开主窗口

vi main.py

  1. import ctypes
  2. import sys
  3. #ui有好多方法,挨个导入太麻烦了,这里直接全量导入
  4. #如果下面有找不到在哪里的函数就来这里找
  5. from PyQt5.QtCore import *
  6. from PyQt5.QtGui import *
  7. from PyQt5.QtWidgets import *
  8. #引入主窗口函数
  9. from ui.main import Ui_mainWindow
  10. #添加主窗口类, 他会继承QMainWindow主窗口类 和 Ui_mainWindow ui下所有的方法
  11. class MainWindow(QMainWindow, Ui_mainWindow):
  12. def __init__(self):
  13. super(MainWindow, self).__init__()
  14. self.setupUi(self) # 设置UI布局
  15. self.retranslateUi(self) # 重新翻译UI组件的文字
  16. if __name__ == '__main__':
  17. # 获取屏幕宽度和高度
  18. screen_width = ctypes.windll.user32.GetSystemMetrics(0)
  19. screen_height = ctypes.windll.user32.GetSystemMetrics(1)
  20. # 初始化QT应用
  21. app = QApplication(sys.argv)
  22. ratio = screen_width / 2560 # 分辨率比例
  23. # 设置全局字体大小 计算字体大小
  24. base_font_size = 13
  25. # 基准字体大小,适合1920*1080分辨率
  26. new_font_size = int(base_font_size * ratio)
  27. font = QFont("Arial", new_font_size)
  28. # 子控件的宽度
  29. item_width = 320
  30. item_height = 240
  31. item_height_min = 60
  32. window_main = MainWindow()
  33. window_main.show() # 开启主窗口
  34. sys.exit(app.exec_()) # 监听消息不关闭

8、主窗口样式

  1. class MainWindow(QMainWindow, Ui_mainWindow):
  2. def __init__(self):
  3. super(MainWindow, self).__init__()
  4. self.setupUi(self)
  5. self.retranslateUi(self)
  6. #添加样式
  7. self.set_ui()
  8. # 设置主窗口样式
  9. def set_ui(self):
  10. # 设置主题样式为 Flatwhite
  11. # 创建 QtitanRibbon 实例
  12. from qt_material import apply_stylesheet
  13. apply_stylesheet(app, theme='dark_pink.xml')
  14. self.setStyleSheet("""
  15. QScrollBar::handle:horizontal {
  16. background-color: #A50F2C; /* 设置滑块颜色 */
  17. }
  18. QScrollBar::handle:horizontal:hover{
  19. background-color: #FF1744; /* 设置滑块颜色 */
  20. }
  21. QPushButton:hover{
  22. background-color: #DFC472; /* 设置颜色 */
  23. }
  24. QPlainTextEdit{padding: 0px;margin: 0px;}
  25. QPushButton{padding: 0px;margin: 1px;}
  26. """ + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))

9、窗口伸缩

  1. class MainWindow(QMainWindow, Ui_mainWindow):
  2. def __init__(self):
  3. super(MainWindow, self).__init__()
  4. self.setupUi(self)
  5. self.retranslateUi(self)
  6. self.set_ui() #添加样式
  7. #sa_main是我们之前定义的QScrollArea 也就是滚动条类型的容器
  8. #我们在滚动条布局sa_main内放了一个普通部件QWidget() ,self.sa_main.setWidget(self.container_widget)
  9. #这样一来,如果普通部件内的数据超出了显示范围,就能通过滚动条查看了
  10. self.g_box = QGridLayout()
  11. #创建了一个普通的窗口部件(QWidget),这个部件将用于包含所有的子控件
  12. #并且可以独立于其父窗口进行尺寸调整,为了可以让g_布局超过窗口大小
  13. self.container_widget = QWidget() # 创建一个中间部件
  14. self.container_widget.setLayout(self.g_box) # 将网格布局设置给中间部件
  15. self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 布局 左上对齐
  16. self.g_box.setContentsMargins(0, 0, 0, 0) # 边距
  17. self.g_box.setAlignment(Qt.AlignTop)
  18. self.sa_main.setWidget(self.container_widget) # 将中间部件设置为QScrollArea的子部件
  19. # 获取纵向滚动条控件
  20. vertical_scrollbar = self.findChild(QScrollArea)
  21. self.v_scrollbar = vertical_scrollbar.verticalScrollBar()
  22. self.setWindowFlags(Qt.WindowStaysOnTopHint)
  23. self.row = 0
  24. self.column = -1
  25. self.run_times = 1
  26. self.column_step = 310
  27. # 获取主窗口的状态栏对象
  28. self.statusbar = self.statusBar()
  29. # 设置状态栏文本
  30. self.statusbar.showMessage('欢迎使用')

10、添加窗口标题、大小、起始位置

  1. def __init__(self):
  2. ...
  3. # self.setWindowIcon(QIcon("datas/logo.png")) 设置图标
  4. self.setWindowTitle(f" 修改主页标题")
  5. self.resize(640, 900) # 窗口的长宽
  6. self.move(0, 300) # 窗口的起点位置

11、延迟布局更新

当窗口尺寸变化或其他条件满足时(例如计时器触发),重新计算并更新网格布局中的控件位置,使其适应当前窗口的大小

  1. class MainWindow(QMainWindow, Ui_mainWindow):
  2. def __init__(self):
  3. ...
  4. # 所有数据
  5. self.datas = []
  6. # 创建一个计时器,用于延迟布局
  7. self.timer = QTimer(self)
  8. self.timer.setSingleShot(True) # 设置为单次触发
  9. self.timer.timeout.connect(self.update_layout)
  10. #计算窗口位置动态调整布局
  11. def update_layout(self):
  12. try:
  13. # 获取主窗口的宽度
  14. width = self.centralWidget().width()
  15. # 计算每行可以容纳的组件数量
  16. num_per_row = (width) // (self.column_step * ratio) # 假设每个组件的宽度为200
  17. if num_per_row < 1:
  18. num_per_row = 1
  19. # 清空当前布局
  20. for i in reversed(range(self.g_box.count())):
  21. self.g_box.itemAt(i).widget().setParent(None)
  22. # 重新添加组件到网格布局
  23. for i, data in enumerate(self.datas):
  24. self.row = int(i // num_per_row)
  25. self.column = int(i % num_per_row)
  26. self.g_box.addWidget(data["f_item"], self.row, self.column)
  27. except:
  28. pass

12、全量py代码

  1. import ctypes
  2. import sys
  3. from PyQt5.QtCore import *
  4. from PyQt5.QtGui import *
  5. from PyQt5.QtWidgets import *
  6. #引入主窗口函数
  7. from ui.main import Ui_mainWindow
  8. #添加主窗口类, 他会继承QMainWindow主窗口类 和 Ui_mainWindow ui下所有的方法
  9. class MainWindow(QMainWindow, Ui_mainWindow):
  10. def __init__(self):
  11. super(MainWindow, self).__init__()
  12. self.setupUi(self) # 设置UI布局
  13. self.retranslateUi(self) # 重新翻译UI组件的文字
  14. #添加样式
  15. self.set_ui()
  16. # self.setWindowIcon(QIcon("datas/logo.png")) 设置图标
  17. self.setWindowTitle(f" 修改主页标题")
  18. self.resize(640, 900) # 窗口的长宽
  19. self.move(0, 300) # 窗口的起点位置
  20. #sa_main是我们之前定义的QScrollArea 也就是滚动条类型的容器
  21. #我们在滚动条布局sa_main内放了一个普通部件QWidget() ,self.sa_main.setWidget(self.container_widget)
  22. #这样一来,如果普通部件内的数据超出了显示范围,就能通过滚动条查看了
  23. self.g_box = QGridLayout()
  24. #创建了一个普通的窗口部件(QWidget),这个部件将用于包含所有的子控件,并且可以独立于其父窗口进行尺寸调整,为了可以让g_布局超过窗口大小
  25. self.container_widget = QWidget() # 创建一个中间部件
  26. self.container_widget.setLayout(self.g_box) # 将网格布局设置给中间部件
  27. self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 布局 左上对齐
  28. self.g_box.setContentsMargins(0, 0, 0, 0) # 边距
  29. self.g_box.setAlignment(Qt.AlignTop)
  30. self.sa_main.setWidget(self.container_widget) # 将中间部件设置为QScrollArea的子部件
  31. # 获取纵向滚动条控件
  32. vertical_scrollbar = self.findChild(QScrollArea)
  33. self.v_scrollbar = vertical_scrollbar.verticalScrollBar()
  34. self.setWindowFlags(Qt.WindowStaysOnTopHint)
  35. self.row = 0
  36. self.column = -1
  37. self.run_times = 1
  38. self.column_step = 310
  39. # 获取主窗口的状态栏对象
  40. self.statusbar = self.statusBar()
  41. # 设置状态栏文本
  42. self.statusbar.showMessage('欢迎使用')
  43. # 所有数据
  44. self.datas = []
  45. # 创建一个计时器,用于延迟布局
  46. self.timer = QTimer(self)
  47. self.timer.setSingleShot(True) # 设置为单次触发
  48. self.timer.timeout.connect(self.update_layout)
  49. def update_layout(self):
  50. try:
  51. # 获取主窗口的宽度
  52. width = self.centralWidget().width()
  53. # 计算每行可以容纳的组件数量
  54. num_per_row = (width) // (self.column_step * ratio) # 假设每个组件的宽度为200
  55. if num_per_row < 1:
  56. num_per_row = 1
  57. # 清空当前布局
  58. for i in reversed(range(self.g_box.count())):
  59. self.g_box.itemAt(i).widget().setParent(None)
  60. # 重新添加组件到网格布局
  61. for i, data in enumerate(self.datas):
  62. self.row = int(i // num_per_row)
  63. self.column = int(i % num_per_row)
  64. self.g_box.addWidget(data["f_item"], self.row, self.column)
  65. except:
  66. pass
  67. # 设置主窗口样式
  68. def set_ui(self):
  69. # 设置主题样式为 Flatwhite
  70. # 创建 QtitanRibbon 实例
  71. from qt_material import apply_stylesheet
  72. apply_stylesheet(app, theme='dark_pink.xml')
  73. self.setStyleSheet("""
  74. QScrollBar::handle:horizontal {
  75. background-color: #A50F2C; /* 设置滑块颜色 */
  76. }
  77. QScrollBar::handle:horizontal:hover{
  78. background-color: #FF1744; /* 设置滑块颜色 */
  79. }
  80. QPushButton:hover{
  81. background-color: #DFC472; /* 设置颜色 */
  82. }
  83. QPlainTextEdit{padding: 0px;margin: 0px;}
  84. QPushButton{padding: 0px;margin: 1px;}
  85. """ + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))
  86. if __name__ == '__main__':
  87. # 获取屏幕宽度和高度
  88. screen_width = ctypes.windll.user32.GetSystemMetrics(0)
  89. screen_height = ctypes.windll.user32.GetSystemMetrics(1)
  90. # 初始化QT应用
  91. app = QApplication(sys.argv)
  92. ratio = screen_width / 2560 # 分辨率比例
  93. # 设置全局字体大小 计算字体大小
  94. base_font_size = 13
  95. # 基准字体大小,适合1920*1080分辨率
  96. new_font_size = int(base_font_size * ratio)
  97. font = QFont("Arial", new_font_size)
  98. # 子控件的宽度
  99. item_width = 320
  100. item_height = 240
  101. item_height_min = 60
  102. window_main = MainWindow()
  103. window_main.show() # 开启主窗口
  104. sys.exit(app.exec_()) # 监听消息不关闭

13、全量ui代码

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ui version="4.0">
  3. <class>mainWindow</class>
  4. <widget class="QMainWindow" name="mainWindow">
  5. <property name="geometry">
  6. <rect>
  7. <x>0</x>
  8. <y>0</y>
  9. <width>800</width>
  10. <height>600</height>
  11. </rect>
  12. </property>
  13. <property name="windowTitle">
  14. <string>主页</string>
  15. </property>
  16. <widget class="QWidget" name="centralwidget">
  17. <layout class="QHBoxLayout" name="horizontalLayout">
  18. <item>
  19. <widget class="QScrollArea" name="sa_main">
  20. <property name="widgetResizable">
  21. <bool>true</bool>
  22. </property>
  23. <widget class="QWidget" name="scrollAreaWidgetContents">
  24. <property name="geometry">
  25. <rect>
  26. <x>0</x>
  27. <y>0</y>
  28. <width>762</width>
  29. <height>551</height>
  30. </rect>
  31. </property>
  32. </widget>
  33. </widget>
  34. </item>
  35. </layout>
  36. </widget>
  37. <widget class="QStatusBar" name="sb_main"/>
  38. <widget class="QToolBar" name="toolBar">
  39. <property name="windowTitle">
  40. <string>toolBar</string>
  41. </property>
  42. <attribute name="toolBarArea">
  43. <enum>LeftToolBarArea</enum>
  44. </attribute>
  45. <attribute name="toolBarBreak">
  46. <bool>false</bool>
  47. </attribute>
  48. </widget>
  49. <action name="actionSave_All">
  50. <property name="text">
  51. <string>Save_All</string>
  52. </property>
  53. </action>
  54. <action name="actionAdd_Mode">
  55. <property name="text">
  56. <string>Add_Mode </string>
  57. </property>
  58. </action>
  59. <action name="actionAdd_Script">
  60. <property name="text">
  61. <string>Add_Script</string>
  62. </property>
  63. </action>
  64. </widget>
  65. <resources/>
  66. <connections/>
  67. </ui>

二、添加UI预览窗口

QDockWidget 码头窗口,通常用于显示附加信息或工具

1、预览窗口定义

1、新建项目-窗口部件--QDockWidget (483X565)

2、添加两个label 大小480 X 270 ,设置样式表

3、添加按钮 修改按钮文本 + -

  1. #寻路标签背景颜色为黑色
  2. background-color: rgb(0, 0, 0);
  3. #标签背景颜色为灰色
  4. background-color: rgb(20, 20, 20);

** 这里图里搞错了,yolo那个label应该设置为**background-color: rgb(20, 20, 20);

2、组件名称修改

  1. DockWidget
  2. dockWidgetContents
  3. bt_jia
  4. bt_jian
  5. lb_xunlu
  6. lb_yolov

3、label最大尺寸修改

寻路

yolo

4、调整各个组件前后台

jia 和jian调整为前台

**xunlu和yolo调整到后台 **

(直接右键组件--放到前面/放到后面)

5、ui转py

  1. pyuic5 -o show.py show.ui

ui全量

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ui version="4.0">
  3. <class>DockWidget</class>
  4. <widget class="QDockWidget" name="DockWidget">
  5. <property name="geometry">
  6. <rect>
  7. <x>0</x>
  8. <y>0</y>
  9. <width>483</width>
  10. <height>565</height>
  11. </rect>
  12. </property>
  13. <property name="windowTitle">
  14. <string>DockWidget</string>
  15. </property>
  16. <widget class="QWidget" name="dockWidgetContents">
  17. <widget class="QLabel" name="lb_xunlu">
  18. <property name="geometry">
  19. <rect>
  20. <x>0</x>
  21. <y>0</y>
  22. <width>480</width>
  23. <height>270</height>
  24. </rect>
  25. </property>
  26. <property name="minimumSize">
  27. <size>
  28. <width>0</width>
  29. <height>0</height>
  30. </size>
  31. </property>
  32. <property name="maximumSize">
  33. <size>
  34. <width>16777215</width>
  35. <height>16777215</height>
  36. </size>
  37. </property>
  38. <property name="styleSheet">
  39. <string notr="true">background-color: rgb(0, 0, 0);</string>
  40. </property>
  41. <property name="text">
  42. <string/>
  43. </property>
  44. </widget>
  45. <widget class="QLabel" name="lb_yolov">
  46. <property name="geometry">
  47. <rect>
  48. <x>0</x>
  49. <y>270</y>
  50. <width>480</width>
  51. <height>270</height>
  52. </rect>
  53. </property>
  54. <property name="minimumSize">
  55. <size>
  56. <width>480</width>
  57. <height>270</height>
  58. </size>
  59. </property>
  60. <property name="maximumSize">
  61. <size>
  62. <width>1920</width>
  63. <height>1080</height>
  64. </size>
  65. </property>
  66. <property name="styleSheet">
  67. <string notr="true">background-color: rgb(20, 20, 20);</string>
  68. </property>
  69. <property name="text">
  70. <string/>
  71. </property>
  72. </widget>
  73. <widget class="QPushButton" name="bt_jia">
  74. <property name="geometry">
  75. <rect>
  76. <x>30</x>
  77. <y>40</y>
  78. <width>31</width>
  79. <height>28</height>
  80. </rect>
  81. </property>
  82. <property name="text">
  83. <string>+</string>
  84. </property>
  85. </widget>
  86. <widget class="QPushButton" name="bt_jian">
  87. <property name="geometry">
  88. <rect>
  89. <x>60</x>
  90. <y>40</y>
  91. <width>31</width>
  92. <height>28</height>
  93. </rect>
  94. </property>
  95. <property name="text">
  96. <string>-</string>
  97. </property>
  98. </widget>
  99. <zorder>lb_yolov</zorder>
  100. <zorder>lb_xunlu</zorder>
  101. <zorder>bt_jia</zorder>
  102. <zorder>bt_jian</zorder>
  103. </widget>
  104. </widget>
  105. <resources/>
  106. <connections/>
  107. </ui>

py代码

  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file 'show.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.15.11
  5. #
  6. # WARNING: Any manual changes made to this file will be lost when pyuic5 is
  7. # run again. Do not edit this file unless you know what you are doing.
  8. from PyQt5 import QtCore, QtGui, QtWidgets
  9. class Ui_DockWidget(object):
  10. def setupUi(self, DockWidget):
  11. DockWidget.setObjectName("DockWidget")
  12. DockWidget.resize(483, 565)
  13. self.dockWidgetContents = QtWidgets.QWidget()
  14. self.dockWidgetContents.setObjectName("dockWidgetContents")
  15. self.lb_xunlu = QtWidgets.QLabel(self.dockWidgetContents)
  16. self.lb_xunlu.setGeometry(QtCore.QRect(0, 0, 480, 270))
  17. self.lb_xunlu.setMinimumSize(QtCore.QSize(0, 0))
  18. self.lb_xunlu.setMaximumSize(QtCore.QSize(16777215, 16777215))
  19. self.lb_xunlu.setStyleSheet("background-color: rgb(0, 0, 0);")
  20. self.lb_xunlu.setText("")
  21. self.lb_xunlu.setObjectName("lb_xunlu")
  22. self.lb_yolov = QtWidgets.QLabel(self.dockWidgetContents)
  23. self.lb_yolov.setGeometry(QtCore.QRect(0, 270, 480, 270))
  24. self.lb_yolov.setMinimumSize(QtCore.QSize(480, 270))
  25. self.lb_yolov.setMaximumSize(QtCore.QSize(1920, 1080))
  26. self.lb_yolov.setStyleSheet("background-color: rgb(20, 20, 20);")
  27. self.lb_yolov.setText("")
  28. self.lb_yolov.setObjectName("lb_yolov")
  29. self.bt_jia = QtWidgets.QPushButton(self.dockWidgetContents)
  30. self.bt_jia.setGeometry(QtCore.QRect(30, 40, 31, 28))
  31. self.bt_jia.setObjectName("bt_jia")
  32. self.bt_jian = QtWidgets.QPushButton(self.dockWidgetContents)
  33. self.bt_jian.setGeometry(QtCore.QRect(60, 40, 31, 28))
  34. self.bt_jian.setObjectName("bt_jian")
  35. self.lb_yolov.raise_()
  36. self.lb_xunlu.raise_()
  37. self.bt_jia.raise_()
  38. self.bt_jian.raise_()
  39. DockWidget.setWidget(self.dockWidgetContents)
  40. self.retranslateUi(DockWidget)
  41. QtCore.QMetaObject.connectSlotsByName(DockWidget)
  42. def retranslateUi(self, DockWidget):
  43. _translate = QtCore.QCoreApplication.translate
  44. DockWidget.setWindowTitle(_translate("DockWidget", "DockWidget"))
  45. self.bt_jia.setText(_translate("DockWidget", "+"))
  46. self.bt_jian.setText(_translate("DockWidget", "-"))

三、主窗口添加子窗口

1、添加预览窗口显示类

  1. #添加预览窗口
  2. from ui.show import Ui_DockWidget
  3. class FormShow(QDockWidget, Ui_DockWidget):
  4. def __init__(self, parent=None):
  5. super(QDockWidget, self).__init__(parent)
  6. self.parent = parent
  7. self.setParent(parent)
  8. self.setupUi(self)
  9. self.set_ui()
  10. # self.timer = QTimer()
  11. self.setWindowTitle("检测预览")
  12. self.lb_yolov.setScaledContents(True)
  13. self.lb_yolov.setAlignment(Qt.AlignCenter)
  14. self.lb_xunlu.setAlignment(Qt.AlignCenter)
  15. self.move(0, 0)
  16. self.setWindowFlags(Qt.WindowStaysOnTopHint)
  17. self.window_height = int(270 * ratio)
  18. self.window_width = int(480 * ratio)
  19. self.setMinimumSize(self.window_width, self.window_height * 2)
  20. self.bt_jia.clicked.connect(self.clicked_jia)
  21. self.bt_jian.clicked.connect(self.clicked_jian)
  22. def set_ui(self):
  23. pass
  24. def clicked_jia(self):
  25. if self.window_height + 108 * ratio > 1080 * ratio:
  26. return
  27. self.window_height += int(108 * ratio)
  28. self.window_width += int(190 * ratio)
  29. self.lb_xunlu.setFixedHeight(self.window_height)
  30. if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
  31. self.lb_yolov.move(self.lb_xunlu.width(), 0)
  32. else:
  33. self.lb_yolov.move(0, self.lb_xunlu.height())
  34. self.lb_yolov.setFixedHeight(self.window_height)
  35. self.lb_yolov.setFixedWidth(self.window_width)
  36. def clicked_jian(self):
  37. if self.window_height - 108 * ratio < 270 * ratio:
  38. return
  39. self.window_height -= int(108 * ratio)
  40. self.window_width -= int(190 * ratio)
  41. self.lb_xunlu.setFixedHeight(self.window_height)
  42. if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
  43. self.lb_yolov.move(self.lb_xunlu.width(), 0)
  44. else:
  45. self.lb_yolov.move(0, self.lb_xunlu.height())
  46. self.lb_yolov.setFixedHeight(self.window_height)
  47. self.lb_yolov.setFixedWidth(self.window_width)
  48. def closeEvent(self, event):
  49. self.parent.action_isShow.setChecked(False)
  50. def resizeEvent(self, event):
  51. if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
  52. self.lb_yolov.move(self.lb_xunlu.width(), 0)
  53. else:
  54. self.lb_yolov.move(0, self.lb_xunlu.height())

2、主窗口添加顶级菜单

  1. class MainWindow(QMainWindow, Ui_mainWindow):
  2. ...
  3. #添加菜单控制栏
  4. def connect_set(self):
  5. # 创建一个顶级菜单
  6. self.menu = self.menuBar() #创建菜单栏
  7. self.menu_view = self.menu.addMenu("视图") #定义菜单栏名称
  8. # 创建一个动作
  9. self.action_isShow = QAction("显示检测结果窗口", self) #菜单栏选项, 关联为当前qt窗口self
  10. self.action_isShow.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F11)) #设置快捷键ctrl + F11
  11. self.action_isShow.triggered.connect(self.hotkey_isShow) #当按钮被按下或者 快捷键时触发函数
  12. self.action_isShow.setCheckable(True) #添加复选框
  13. self.action_isShow.setChecked(True) #默认被选中
  14. # 添加动作到试图窗口
  15. self.menu_view.addAction(self.action_isShow)
  16. # 初始化的时候立刻调用显示qt窗口
  17. self.hotkey_isShow()

3、预测窗口显示

我们在定义菜单栏的时候通过self.action_isShow.triggered.connect 绑定了当被选中时触发的函数,我们下面就定义当按钮被按下的时候会将我们的预览窗口

  1. class MainWindow(QMainWindow, Ui_mainWindow):
  2. ...
  3. def hotkey_isShow(self):
  4. if not hasattr(self, "fromshow"):
  5. self.fromshow = FormShow(self) #打开预览ui页面
  6. #self 是当前主窗口的对象,传递给 FormShow 类作为父对象
  7. #这样 FormShow 实例就可以访问主窗口的一些属性和方法
  8. #添加预览窗口到主窗口
  9. self.addDockWidget(Qt.TopDockWidgetArea, self.fromshow)
  10. #设置动作被选中
  11. self.action_isShow.setChecked(True)
  12. else:
  13. if self.fromshow.isVisible(): #isVisible 检查窗口是否可见
  14. self.fromshow.hide() #如果可见则隐藏
  15. self.action_isShow.setChecked(False) #设置为False 清空选中
  16. else:
  17. self.fromshow.show() #如果不可见,设置为可见
  18. self.action_isShow.setChecked(True) #改为True 选中

四、信号槽

上面初步的给主窗口添加了我们做好的预览页面,但是预览页面什么东西都没有,只有俩label的无文本贴图,这里我们让他显示点东西处理

1、添加自定义信号

  1. class MySignal(QObject):
  2. #我们这里给 xunlu和yolo单独定义俩信号
  3. mysig_show_xunlu = pyqtSignal()
  4. mysig_show_yolov = pyqtSignal()

2、添加信号槽

  1. # 绑定信号槽
  2. def connect_set(self):
  3. ...
  4. #添加信号
  5. self.sg = MySignal()
  6. #绑定信号槽
  7. #其实和上面绑定按钮差不多,这里是将信号绑定到指定函数
  8. #如果要发送信号则是下面两种方法,进行触发
  9. #方法1 通过父对象访问sg
  10. #self.parent.sg.mysig_show_yolov.emit()
  11. #方法2 通过当前对象的sg,我们sg是定义在主窗口的,所以如果要用的话就是这个
  12. #self.sg.mysig_show_yolov.emit()
  13. self.sg.mysig_show_xunlu.connect(self.show_xunlu) #寻路
  14. self.sg.mysig_show_yolov.connect(self.show_yolov) #推理

3、添加触发函数

这里先偷个懒,直接使用本地图片显示上去,后续整完之后在加具体功能

我们在test目录下创建个/datas/目录 放一张图片,我这里是111.png

  1. def show_xunlu(self, image_path="./datas/111.png"):
  2. # 加载本地图片
  3. pixmap = QPixmap(image_path)
  4. # 设置图片到 lb_xunlu 控件
  5. self.fromshow.lb_xunlu.setPixmap(pixmap)
  6. # 设置宽度固定,高度自适应
  7. self.fromshow.window_width = int(self.fromshow.window_height * pixmap.width() / pixmap.height())
  8. self.fromshow.lb_xunlu.setFixedHeight(self.fromshow.window_height)
  9. self.fromshow.lb_xunlu.setFixedWidth(self.fromshow.window_width)
  10. self.fromshow.lb_xunlu.setScaledContents(True)
  11. def show_yolov(self, image_path="./datas/111.png"):
  12. # 加载本地图片
  13. pixmap1 = QPixmap(image_path)
  14. # 设置图片到 lb_yolov 控件
  15. self.fromshow.lb_yolov.setPixmap(pixmap1)
  16. # 根据窗口宽度调整 lb_yolov 的位置
  17. if self.fromshow.width() >= self.fromshow.lb_yolov.width() + self.fromshow.lb_xunlu.width():
  18. self.fromshow.lb_yolov.move(self.fromshow.lb_xunlu.width(), 0)
  19. else:
  20. self.fromshow.lb_yolov.move(0, self.fromshow.lb_xunlu.height())

4、发送信号

关于怎么去显示,我们在主窗口初始化函数中定义一个定时器,让他每5s发送一次mysig_show_xunlu和mysig_show_yolov信号,信号槽接收到后,触发show_xunlu 和show_yolov 函数,去显示图片

  1. def __init__(self):
  2. ...
  3. # 创建定时器 用于周期显示图片
  4. self.timer = QTimer(self)
  5. self.timer.timeout.connect(self.on_timer_timeout)
  6. self.timer.start(5000) # 每5秒触发一次
  7. #发送信号
  8. def on_timer_timeout(self):
  9. # 每隔一段时间自动显示图片
  10. # emit() 方法用于发送信号
  11. self.sg.mysig_show_xunlu.emit()
  12. self.sg.mysig_show_yolov.emit()

后面使用的时候不会这么草率的显示俩图片,而是通过循环截取地图,将yolo识别的到的视频流和地图位置作为显示查询

5、全量代码

  1. import ctypes
  2. import sys
  3. from PyQt5.QtCore import *
  4. from PyQt5.QtGui import *
  5. from PyQt5.QtWidgets import *
  6. from websockets import connect
  7. #引入主窗口函数
  8. from ui.main import Ui_mainWindow
  9. #添加预览窗口
  10. from ui.show import Ui_DockWidget
  11. class FormShow(QDockWidget, Ui_DockWidget):
  12. def __init__(self, parent=None):
  13. super(QDockWidget, self).__init__(parent)
  14. self.parent = parent
  15. self.setParent(parent)
  16. self.setupUi(self)
  17. self.set_ui()
  18. # self.timer = QTimer()
  19. self.setWindowTitle("检测预览")
  20. self.lb_yolov.setScaledContents(True)
  21. self.lb_yolov.setAlignment(Qt.AlignCenter)
  22. self.lb_xunlu.setAlignment(Qt.AlignCenter)
  23. self.move(0, 0)
  24. self.setWindowFlags(Qt.WindowStaysOnTopHint)
  25. self.window_height = int(270 * ratio)
  26. self.window_width = int(480 * ratio)
  27. self.setMinimumSize(self.window_width, self.window_height * 2)
  28. self.bt_jia.clicked.connect(self.clicked_jia)
  29. self.bt_jian.clicked.connect(self.clicked_jian)
  30. def set_ui(self):
  31. pass
  32. def clicked_jia(self):
  33. if self.window_height + 108 * ratio > 1080 * ratio:
  34. return
  35. self.window_height += int(108 * ratio)
  36. self.window_width += int(190 * ratio)
  37. self.lb_xunlu.setFixedHeight(self.window_height)
  38. if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
  39. self.lb_yolov.move(self.lb_xunlu.width(), 0)
  40. else:
  41. self.lb_yolov.move(0, self.lb_xunlu.height())
  42. self.lb_yolov.setFixedHeight(self.window_height)
  43. self.lb_yolov.setFixedWidth(self.window_width)
  44. def clicked_jian(self):
  45. if self.window_height - 108 * ratio < 270 * ratio:
  46. return
  47. self.window_height -= int(108 * ratio)
  48. self.window_width -= int(190 * ratio)
  49. self.lb_xunlu.setFixedHeight(self.window_height)
  50. if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
  51. self.lb_yolov.move(self.lb_xunlu.width(), 0)
  52. else:
  53. self.lb_yolov.move(0, self.lb_xunlu.height())
  54. self.lb_yolov.setFixedHeight(self.window_height)
  55. self.lb_yolov.setFixedWidth(self.window_width)
  56. def closeEvent(self, event):
  57. self.parent.action_isShow.setChecked(False)
  58. def resizeEvent(self, event):
  59. if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
  60. self.lb_yolov.move(self.lb_xunlu.width(), 0)
  61. else:
  62. self.lb_yolov.move(0, self.lb_xunlu.height())
  63. class MySignal(QObject):
  64. #我们这里给 xunlu和yolo单独定义俩信号
  65. mysig_show_xunlu = pyqtSignal()
  66. mysig_show_yolov = pyqtSignal()
  67. #添加主窗口类, 他会继承QMainWindow主窗口类 和 Ui_mainWindow ui下所有的方法
  68. class MainWindow(QMainWindow, Ui_mainWindow):
  69. def __init__(self):
  70. super(MainWindow, self).__init__()
  71. self.setupUi(self) # 设置UI布局
  72. self.retranslateUi(self) # 重新翻译UI组件的文字
  73. #添加样式
  74. self.set_ui()
  75. # self.setWindowIcon(QIcon("datas/logo.png")) 设置图标
  76. self.setWindowTitle(f" 修改主页标题")
  77. self.resize(640, 900) # 窗口的长宽
  78. self.move(0, 300) # 窗口的起点位置
  79. #sa_main是我们之前定义的QScrollArea 也就是滚动条类型的容器
  80. #我们在滚动条布局sa_main内放了一个普通部件QWidget() ,self.sa_main.setWidget(self.container_widget)
  81. #这样一来,如果普通部件内的数据超出了显示范围,就能通过滚动条查看了
  82. self.g_box = QGridLayout()
  83. #创建了一个普通的窗口部件(QWidget),这个部件将用于包含所有的子控件,并且可以独立于其父窗口进行尺寸调整,为了可以让g_布局超过窗口大小
  84. self.container_widget = QWidget() # 创建一个中间部件
  85. self.container_widget.setLayout(self.g_box) # 将网格布局设置给中间部件
  86. self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft) # 布局 左上对齐
  87. self.g_box.setContentsMargins(0, 0, 0, 0) # 边距
  88. self.g_box.setAlignment(Qt.AlignTop)
  89. self.sa_main.setWidget(self.container_widget) # 将中间部件设置为QScrollArea的子部件
  90. # 获取纵向滚动条控件
  91. vertical_scrollbar = self.findChild(QScrollArea)
  92. self.v_scrollbar = vertical_scrollbar.verticalScrollBar()
  93. self.setWindowFlags(Qt.WindowStaysOnTopHint)
  94. self.row = 0
  95. self.column = -1
  96. self.run_times = 1
  97. self.column_step = 310
  98. # 获取主窗口的状态栏对象
  99. self.statusbar = self.statusBar()
  100. # 设置状态栏文本
  101. self.statusbar.showMessage('欢迎使用')
  102. # 所有数据
  103. self.datas = []
  104. # 创建一个计时器,用于延迟布局
  105. self.timer = QTimer(self)
  106. self.timer.setSingleShot(True) # 设置为单次触发
  107. self.timer.timeout.connect(self.update_layout)
  108. #调用菜单栏
  109. self.connect_set()
  110. # 创建定时器 用于周期显示图片
  111. self.timer = QTimer(self)
  112. self.timer.timeout.connect(self.on_timer_timeout)
  113. self.timer.start(5000) # 每5秒触发一次
  114. def on_timer_timeout(self):
  115. # 每隔一段时间自动显示图片
  116. #emit() 方法用于发送信号
  117. self.sg.mysig_show_xunlu.emit()
  118. self.sg.mysig_show_yolov.emit()
  119. def connect_set(self):
  120. #添加信号
  121. self.sg = MySignal()
  122. #绑定信号槽
  123. #这里是给我们上面定义的自定义信号,mysig_show_xunlu 这种绑定给特定的元素
  124. #因为我们上面hotkey_isShow函数中做了FormShow(self)
  125. self.sg.mysig_show_xunlu.connect(self.show_xunlu) #寻路 show_xunlu是下面我们
  126. self.sg.mysig_show_yolov.connect(self.show_yolov) #推理
  127. #如果要发送信号则是
  128. #self.parent.sg.mysig_show_yolov.emit()
  129. #当检查到发送信号的时候会触发函数
  130. # 创建一个顶级菜单
  131. self.menu = self.menuBar() #创建菜单栏
  132. self.menu_view = self.menu.addMenu("视图") #定义菜单栏名称
  133. # 创建一个动作
  134. self.action_isShow = QAction("显示检测结果窗口", self) #菜单栏选项, 关联为当前qt窗口self
  135. self.action_isShow.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F11)) #设置快捷键ctrl + F11
  136. self.action_isShow.triggered.connect(self.hotkey_isShow) #当按钮被按下或者 快捷键时触发函数
  137. self.action_isShow.setCheckable(True) #添加复选框
  138. self.action_isShow.setChecked(True) #默认被选中
  139. # 添加动作到试图窗口
  140. self.menu_view.addAction(self.action_isShow)
  141. # 初始化的时候立刻调用显示qt窗口
  142. self.hotkey_isShow()
  143. def show_xunlu(self, image_path="./datas/111.png"):
  144. # 加载本地图片
  145. pixmap = QPixmap(image_path)
  146. # 设置图片到 lb_xunlu 控件
  147. self.fromshow.lb_xunlu.setPixmap(pixmap)
  148. # 设置宽度固定,高度自适应
  149. self.fromshow.window_width = int(self.fromshow.window_height * pixmap.width() / pixmap.height())
  150. self.fromshow.lb_xunlu.setFixedHeight(self.fromshow.window_height)
  151. self.fromshow.lb_xunlu.setFixedWidth(self.fromshow.window_width)
  152. self.fromshow.lb_xunlu.setScaledContents(True)
  153. def show_yolov(self, image_path="./datas/111.png"):
  154. # 加载本地图片
  155. pixmap1 = QPixmap(image_path)
  156. # 设置图片到 lb_yolov 控件
  157. self.fromshow.lb_yolov.setPixmap(pixmap1)
  158. # 根据窗口宽度调整 lb_yolov 的位置
  159. if self.fromshow.width() >= self.fromshow.lb_yolov.width() + self.fromshow.lb_xunlu.width():
  160. self.fromshow.lb_yolov.move(self.fromshow.lb_xunlu.width(), 0)
  161. else:
  162. self.fromshow.lb_yolov.move(0, self.fromshow.lb_xunlu.height())
  163. def hotkey_isShow(self):
  164. if not hasattr(self, "fromshow"):
  165. self.fromshow = FormShow(self)
  166. self.addDockWidget(Qt.TopDockWidgetArea, self.fromshow)
  167. self.action_isShow.setChecked(True)
  168. else:
  169. if self.fromshow.isVisible():
  170. self.fromshow.hide()
  171. self.action_isShow.setChecked(False)
  172. else:
  173. self.fromshow.show()
  174. self.action_isShow.setChecked(True)
  175. def update_layout(self):
  176. try:
  177. # 获取主窗口的宽度
  178. width = self.centralWidget().width()
  179. # 计算每行可以容纳的组件数量
  180. num_per_row = (width) // (self.column_step * ratio) # 假设每个组件的宽度为200
  181. if num_per_row < 1:
  182. num_per_row = 1
  183. # 清空当前布局
  184. for i in reversed(range(self.g_box.count())):
  185. self.g_box.itemAt(i).widget().setParent(None)
  186. # 重新添加组件到网格布局
  187. for i, data in enumerate(self.datas):
  188. self.row = int(i // num_per_row)
  189. self.column = int(i % num_per_row)
  190. self.g_box.addWidget(data["f_item"], self.row, self.column)
  191. except:
  192. pass
  193. # 设置主窗口样式
  194. def set_ui(self):
  195. # 设置主题样式为 Flatwhite
  196. # 创建 QtitanRibbon 实例
  197. from qt_material import apply_stylesheet
  198. apply_stylesheet(app, theme='dark_pink.xml')
  199. self.setStyleSheet("""
  200. QScrollBar::handle:horizontal {
  201. background-color: #A50F2C; /* 设置滑块颜色 */
  202. }
  203. QScrollBar::handle:horizontal:hover{
  204. background-color: #FF1744; /* 设置滑块颜色 */
  205. }
  206. QPushButton:hover{
  207. background-color: #DFC472; /* 设置颜色 */
  208. }
  209. QPlainTextEdit{padding: 0px;margin: 0px;}
  210. QPushButton{padding: 0px;margin: 1px;}
  211. """ + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))
  212. if __name__ == '__main__':
  213. # 获取屏幕宽度和高度
  214. screen_width = ctypes.windll.user32.GetSystemMetrics(0)
  215. screen_height = ctypes.windll.user32.GetSystemMetrics(1)
  216. # 初始化QT应用
  217. app = QApplication(sys.argv)
  218. ratio = screen_width / 2560 # 分辨率比例
  219. # 设置全局字体大小 计算字体大小
  220. base_font_size = 13
  221. # 基准字体大小,适合1920*1080分辨率
  222. new_font_size = int(base_font_size * ratio)
  223. font = QFont("Arial", new_font_size)
  224. # 子控件的宽度
  225. item_width = 320
  226. item_height = 240
  227. item_height_min = 60
  228. window_main = MainWindow()
  229. window_main.show() # 开启主窗口
  230. sys.exit(app.exec_()) # 监听消息不关闭
标签: YOLO 自动化 运维

本文转载自: https://blog.csdn.net/qq_42883074/article/details/142483353
版权归原作者 默子昂 所有, 如有侵权,请联系我们删除。

“yolo自动化项目实例解析(六)自建UI(主窗口、预览窗口)”的评论:

还没有评论