当前位置: 首页 > article >正文

yolo自动化项目实例解析(六)自建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。
2、选择“文件” > “新建”,创建一个新的Qt Designer文档。
3、在“选择类”对话框中,选择QMainWindow作为基础类,并命名为mainWindow。

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

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

3、组件重命名

mainWindow
centralwidget
sa_main
scrollAreaWidgetContents
sb_main
toolBar

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

4、布局重命名

我们上面临时用了下布局样式这里可能叫_2什么的,修改为下图

5、工具栏调整到侧边

6、添加动作、ui转py

#动作文本名称如下
Save_All 
Add_Mode 
Add_Script

 ui转换

pyuic5 -o main.py main.ui

代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'main.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_mainWindow(object):
    def setupUi(self, mainWindow):
        mainWindow.setObjectName("mainWindow")
        mainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(mainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.sa_main = QtWidgets.QScrollArea(self.centralwidget)
        self.sa_main.setWidgetResizable(True)
        self.sa_main.setObjectName("sa_main")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 762, 551))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.sa_main.setWidget(self.scrollAreaWidgetContents)
        self.horizontalLayout.addWidget(self.sa_main)
        mainWindow.setCentralWidget(self.centralwidget)
        self.sb_main = QtWidgets.QStatusBar(mainWindow)
        self.sb_main.setObjectName("sb_main")
        mainWindow.setStatusBar(self.sb_main)
        self.toolBar = QtWidgets.QToolBar(mainWindow)
        self.toolBar.setObjectName("toolBar")
        mainWindow.addToolBar(QtCore.Qt.LeftToolBarArea, self.toolBar)
        self.actionSave_All = QtWidgets.QAction(mainWindow)
        self.actionSave_All.setObjectName("actionSave_All")
        self.actionAdd_Mode = QtWidgets.QAction(mainWindow)
        self.actionAdd_Mode.setObjectName("actionAdd_Mode")
        self.actionAdd_Script = QtWidgets.QAction(mainWindow)
        self.actionAdd_Script.setObjectName("actionAdd_Script")

        self.retranslateUi(mainWindow)
        QtCore.QMetaObject.connectSlotsByName(mainWindow)

    def retranslateUi(self, mainWindow):
        _translate = QtCore.QCoreApplication.translate
        mainWindow.setWindowTitle(_translate("mainWindow", "主页"))
        self.toolBar.setWindowTitle(_translate("mainWindow", "toolBar"))
        self.actionSave_All.setText(_translate("mainWindow", "Save_All "))
        self.actionAdd_Mode.setText(_translate("mainWindow", "Add_Mode "))
        self.actionAdd_Script.setText(_translate("mainWindow", "Add_Script"))

7、打开主窗口

import ctypes
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QDockWidget, QMainWindow, QApplication

import state
from ui.show import Ui_DockWidget
from ui.main import Ui_mainWindow





class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)  # 设置UI布局
        self.retranslateUi(self)  # 重新翻译UI组件的文字




if __name__ == '__main__':
    # 获取屏幕宽度和高度
    screen_width = ctypes.windll.user32.GetSystemMetrics(0)
    screen_height = ctypes.windll.user32.GetSystemMetrics(1)

    #初始化QT应用
    app = QApplication(sys.argv)
    ratio = screen_width / 2560  # 分辨率比例


    # 设置全局字体大小  计算字体大小
    base_font_size = 13
    # 基准字体大小,适合1920*1080分辨率
    new_font_size = int(base_font_size * ratio)
    font = QFont("Arial", new_font_size)

    # 子控件的宽度
    item_width = 320
    item_height = 240
    item_height_min = 60
    window_main = MainWindow()
    window_main.show()  #开启主窗口
    sys.exit(app.exec_())  # 监听消息不关闭

8、设置主窗口样式

class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)  # 设置UI布局
        self.retranslateUi(self)  # 重新翻译UI组件的文字

        #修改窗口样式为黑灰色,高亮
        self.set_ui()

    #设置主窗口样式
    def set_ui(self):
        # 设置主题样式为 Flatwhite
        # 创建 QtitanRibbon 实例
        from qt_material import apply_stylesheet
        apply_stylesheet(app, theme='dark_pink.xml')
        self.setStyleSheet("""
        QScrollBar::handle:horizontal {
        background-color: #A50F2C;  /* 设置滑块颜色 */
            }
           QScrollBar::handle:horizontal:hover{
        background-color: #FF1744;  /* 设置滑块颜色 */
            } 
            QPushButton:hover{
            background-color: #DFC472;  /* 设置颜色 */
            }
            QPlainTextEdit{padding: 0px;margin: 0px;}
            QPushButton{padding: 0px;margin: 1px;}
        """ + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))

9、滚动可扩展窗口

class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self):


    。。。

        #sa_main是我们之前定义的QScrollArea 也就是滚动条类型的容器
        #我们在滚动条布局sa_main内放了一个普通部件QWidget()  ,self.sa_main.setWidget(self.container_widget)
        #这样一来,如果普通部件内的数据超出了显示范围,就能通过滚动条查看了
        self.g_box = QGridLayout()
        #创建了一个普通的窗口部件(QWidget),这个部件将用于包含所有的子控件,并且可以独立于其父窗口进行尺寸调整,为了可以让g_布局超过窗口大小
        self.container_widget = QWidget()  # 创建一个中间部件
        self.container_widget.setLayout(self.g_box)  # 将网格布局设置给中间部件
        self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft)  # 布局 左上对齐
        self.g_box.setContentsMargins(0, 0, 0, 0)  # 边距
        self.g_box.setAlignment(Qt.AlignTop)
        self.sa_main.setWidget(self.container_widget)  # 将中间部件设置为QScrollArea的子部件

        # 获取纵向滚动条控件
        vertical_scrollbar = self.findChild(QScrollArea)
        self.v_scrollbar = vertical_scrollbar.verticalScrollBar()
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.row = 0
        self.column = -1
        self.run_times = 1
        self.column_step = 310



        # 获取主窗口的状态栏对象
        self.statusbar = self.statusBar()

        # 设置状态栏文本
        self.statusbar.showMessage('欢迎使用')

10、延迟布局更新

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

class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self):


     。。。



        # 所有数据
        self.datas = []
        # 创建一个计时器,用于延迟布局
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)  # 设置为单次触发
        self.timer.timeout.connect(self.update_layout)

    def update_layout(self):
        try:
            # 获取主窗口的宽度
            width = self.centralWidget().width()

            # 计算每行可以容纳的组件数量
            num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200
            if num_per_row < 1:
                num_per_row = 1

            # 清空当前布局
            for i in reversed(range(self.g_box.count())):
                self.g_box.itemAt(i).widget().setParent(None)

            # 重新添加组件到网格布局
            for i, data in enumerate(self.datas):
                self.row = int(i // num_per_row)
                self.column = int(i % num_per_row)
                self.g_box.addWidget(data["f_item"], self.row, self.column)
        except:
            pass

11、全量代码

import ctypes
import sys

from PyQt5.QtCore import Qt, QTimer, QObject, pyqtSignal
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QDockWidget, QMainWindow, QApplication, QGridLayout, QWidget, QScrollArea

from ui.show import Ui_DockWidget
from ui.main import Ui_mainWindow





class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)  # 设置UI布局
        self.retranslateUi(self)  # 重新翻译UI组件的文字

        #修改窗口样式为黑灰色,高亮
        self.set_ui()

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


        #sa_main是我们之前定义的QScrollArea 也就是滚动条类型的容器
        #我们在滚动条布局sa_main内放了一个普通部件QWidget()  ,self.sa_main.setWidget(self.container_widget)
        #这样一来,如果普通部件内的数据超出了显示范围,就能通过滚动条查看了
        self.g_box = QGridLayout()
        #创建了一个普通的窗口部件(QWidget),这个部件将用于包含所有的子控件,并且可以独立于其父窗口进行尺寸调整,为了可以让g_布局超过窗口大小
        self.container_widget = QWidget()  # 创建一个中间部件
        self.container_widget.setLayout(self.g_box)  # 将网格布局设置给中间部件
        self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft)  # 布局 左上对齐
        self.g_box.setContentsMargins(0, 0, 0, 0)  # 边距
        self.g_box.setAlignment(Qt.AlignTop)
        self.sa_main.setWidget(self.container_widget)  # 将中间部件设置为QScrollArea的子部件

        # 获取纵向滚动条控件
        vertical_scrollbar = self.findChild(QScrollArea)
        self.v_scrollbar = vertical_scrollbar.verticalScrollBar()
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.row = 0
        self.column = -1
        self.run_times = 1
        self.column_step = 310

        # 获取主窗口的状态栏对象
        self.statusbar = self.statusBar()

        # 设置状态栏文本
        self.statusbar.showMessage('欢迎使用')




        # 所有数据
        self.datas = []
        # 创建一个计时器,用于延迟布局
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)  # 设置为单次触发
        self.timer.timeout.connect(self.update_layout)






    #更新布局
    def update_layout(self):
        try:
            # 获取主窗口的宽度
            width = self.centralWidget().width()

            # 计算每行可以容纳的组件数量
            num_per_row = (width) // (self.column_step * ratio)  # 假设每个组件的宽度为200
            if num_per_row < 1:
                num_per_row = 1

            # 清空当前布局
            for i in reversed(range(self.g_box.count())):
                self.g_box.itemAt(i).widget().setParent(None)

            # 重新添加组件到网格布局
            for i, data in enumerate(self.datas):
                self.row = int(i // num_per_row)
                self.column = int(i % num_per_row)
                self.g_box.addWidget(data["f_item"], self.row, self.column)
        except:
            pass




    #设置主窗口样式
    def set_ui(self):
        # 设置主题样式为 Flatwhite
        # 创建 QtitanRibbon 实例
        from qt_material import apply_stylesheet
        apply_stylesheet(app, theme='dark_pink.xml')
        self.setStyleSheet("""
        QScrollBar::handle:horizontal {
        background-color: #A50F2C;  /* 设置滑块颜色 */
            }
           QScrollBar::handle:horizontal:hover{
        background-color: #FF1744;  /* 设置滑块颜色 */
            } 
            QPushButton:hover{
            background-color: #DFC472;  /* 设置颜色 */
            }
            QPlainTextEdit{padding: 0px;margin: 0px;}
            QPushButton{padding: 0px;margin: 1px;}
        """ + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))




if __name__ == '__main__':
    # 获取屏幕宽度和高度
    screen_width = ctypes.windll.user32.GetSystemMetrics(0)
    screen_height = ctypes.windll.user32.GetSystemMetrics(1)

    #初始化QT应用
    app = QApplication(sys.argv)
    ratio = screen_width / 2560  # 分辨率比例


    # 设置全局字体大小  计算字体大小
    base_font_size = 13
    # 基准字体大小,适合1920*1080分辨率
    new_font_size = int(base_font_size * ratio)
    font = QFont("Arial", new_font_size)

    # 子控件的宽度
    item_width = 320
    item_height = 240
    item_height_min = 60
    window_main = MainWindow()
    window_main.show()  #开启主窗口
    sys.exit(app.exec_())  # 监听消息不关闭

二、添加UI预览窗口

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

1、预览窗口定义

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

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

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

#寻路标签背景颜色为黑色
background-color: rgb(0, 0, 0);



#标签背景颜色为灰色
background-color: rgb(20, 20, 20);

 

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

2、组件名称修改

DockWidget
dockWidgetContents
bt_jia
bt_jian
lb_xunlu
lb_yolov

3、label最大尺寸修改

寻路

yolo

4、调整各个组件前后台

jia 和jian调整为前台

xunlu和yolo调整到后台  

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

5、ui转py

pyuic5 -o show.py show.ui

py代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'show.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_DockWidget(object):
    def setupUi(self, DockWidget):
        DockWidget.setObjectName("DockWidget")
        DockWidget.resize(483, 565)
        self.dockWidgetContents = QtWidgets.QWidget()
        self.dockWidgetContents.setObjectName("dockWidgetContents")
        self.lb_xunlu = QtWidgets.QLabel(self.dockWidgetContents)
        self.lb_xunlu.setGeometry(QtCore.QRect(0, 0, 480, 270))
        self.lb_xunlu.setMinimumSize(QtCore.QSize(0, 0))
        self.lb_xunlu.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self.lb_xunlu.setStyleSheet("background-color: rgb(0, 0, 0);")
        self.lb_xunlu.setText("")
        self.lb_xunlu.setObjectName("lb_xunlu")
        self.lb_yolov = QtWidgets.QLabel(self.dockWidgetContents)
        self.lb_yolov.setGeometry(QtCore.QRect(0, 270, 480, 270))
        self.lb_yolov.setMinimumSize(QtCore.QSize(480, 270))
        self.lb_yolov.setMaximumSize(QtCore.QSize(1920, 1080))
        self.lb_yolov.setStyleSheet("background-color: rgb(20, 20, 20);")
        self.lb_yolov.setText("")
        self.lb_yolov.setObjectName("lb_yolov")
        self.bt_jia = QtWidgets.QPushButton(self.dockWidgetContents)
        self.bt_jia.setGeometry(QtCore.QRect(30, 40, 31, 28))
        self.bt_jia.setObjectName("bt_jia")
        self.bt_jian = QtWidgets.QPushButton(self.dockWidgetContents)
        self.bt_jian.setGeometry(QtCore.QRect(60, 40, 31, 28))
        self.bt_jian.setObjectName("bt_jian")
        self.lb_yolov.raise_()
        self.lb_xunlu.raise_()
        self.bt_jia.raise_()
        self.bt_jian.raise_()
        DockWidget.setWidget(self.dockWidgetContents)

        self.retranslateUi(DockWidget)
        QtCore.QMetaObject.connectSlotsByName(DockWidget)

    def retranslateUi(self, DockWidget):
        _translate = QtCore.QCoreApplication.translate
        DockWidget.setWindowTitle(_translate("DockWidget", "DockWidget"))
        self.bt_jia.setText(_translate("DockWidget", "+"))
        self.bt_jian.setText(_translate("DockWidget", "-"))

三、主窗口添加子窗口

1、添加自定义信号

class MySignal(QObject):

    # 无参数信号,可能用于触发显示某个路径或轨迹的操作
    mysig_show_xunlu = pyqtSignal()  

    # 无参数信号,可能与YOLOv模型有关,用于触发显示模型输出或其他相关操作
    mysig_show_yolov = pyqtSignal()  

2、添加预览窗口显示类


class FormShow(QDockWidget, Ui_DockWidget):
    def __init__(self, parent=None):
        super(QDockWidget, self).__init__(parent)
        self.parent = parent
        self.setParent(parent)
        self.setupUi(self)
        self.set_ui()
        # self.timer = QTimer()
        self.setWindowTitle("检测预览")
        self.lb_yolov.setScaledContents(True)
        self.lb_yolov.setAlignment(Qt.AlignCenter)
        self.lb_xunlu.setAlignment(Qt.AlignCenter)
        self.move(0, 0)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.window_height = int(270 * ratio)
        self.window_width = int(480 * ratio)
        self.setMinimumSize(self.window_width, self.window_height * 2)
        self.bt_jia.clicked.connect(self.clicked_jia)
        self.bt_jian.clicked.connect(self.clicked_jian)

    def set_ui(self):
        pass

    def clicked_jia(self):

        if self.window_height + 108 * ratio > 1080 * ratio:
            return
        self.window_height += int(108 * ratio)
        self.window_width += int(190 * ratio)
        self.lb_xunlu.setFixedHeight(self.window_height)
        if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
            self.lb_yolov.move(self.lb_xunlu.width(), 0)
        else:
            self.lb_yolov.move(0, self.lb_xunlu.height())
        self.lb_yolov.setFixedHeight(self.window_height)
        self.lb_yolov.setFixedWidth(self.window_width)

    def clicked_jian(self):
        if self.window_height - 108 * ratio < 270 * ratio:
            return
        self.window_height -= int(108 * ratio)
        self.window_width -= int(190 * ratio)
        self.lb_xunlu.setFixedHeight(self.window_height)

        if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
            self.lb_yolov.move(self.lb_xunlu.width(), 0)
        else:
            self.lb_yolov.move(0, self.lb_xunlu.height())
        self.lb_yolov.setFixedHeight(self.window_height)
        self.lb_yolov.setFixedWidth(self.window_width)

    def closeEvent(self, event):
        self.parent.action_isShow.setChecked(False)

    def resizeEvent(self, event):
        if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
            self.lb_yolov.move(self.lb_xunlu.width(), 0)
        else:
            self.lb_yolov.move(0, self.lb_xunlu.height())

3、主窗口 添加 预览窗口显示

    def connect_set(self):


        # 创建一个顶级菜单
        self.menu = self.menuBar()
        self.menu_view = self.menu.addMenu("视图")
        # 创建一个动作
        self.action_isShow = QAction("显示检测结果窗口", self)
        self.action_isShow.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F11))
        self.action_isShow.triggered.connect(self.hotkey_isShow)
        self.action_isShow.setCheckable(True)
        self.action_isShow.setChecked(True)
        self.menu_view.addAction(self.action_isShow)
        self.hotkey_isShow()





    #打开预测窗口
    def hotkey_isShow(self):
        # 尝试创建悬浮窗口实例
        if not hasattr(self, "fromshow"):
            self.fromshow = FormShow(self)  # 创建悬浮窗口实例
            print(111111)
            self.addDockWidget(Qt.TopDockWidgetArea, self.fromshow)  # 添加悬浮窗口到主窗口

4、添加信号槽

    # 绑定信号槽
    def connect_set(self):
        ...


        #添加信号
        self.sg = MySignal()
        #绑定信号槽
        self.sg.mysig_show_xunlu.connect(self.show_xunlu)  #寻路
        self.sg.mysig_show_yolov.connect(self.show_yolov)  #推理

5、添加信号槽及对应函数

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

    def show_xunlu(self, image_path="./datas/111.png"):
        # 加载本地图片
        pixmap = QPixmap(image_path)

        # 设置图片到 lb_xunlu 控件
        self.fromshow.lb_xunlu.setPixmap(pixmap)

        # 设置宽度固定,高度自适应
        self.fromshow.window_width = int(self.fromshow.window_height * pixmap.width() / pixmap.height())
        self.fromshow.lb_xunlu.setFixedHeight(self.fromshow.window_height)
        self.fromshow.lb_xunlu.setFixedWidth(self.fromshow.window_width)
        self.fromshow.lb_xunlu.setScaledContents(True)

    def show_yolov(self, image_path="./datas/111.png"):
        print(2222)
        # 加载本地图片
        pixmap1 = QPixmap(image_path)

        # 设置图片到 lb_yolov 控件
        self.fromshow.lb_yolov.setPixmap(pixmap1)

        # 根据窗口宽度调整 lb_yolov 的位置
        if self.fromshow.width() >= self.fromshow.lb_yolov.width() + self.fromshow.lb_xunlu.width():
            self.fromshow.lb_yolov.move(self.fromshow.lb_xunlu.width(), 0)
        else:
            self.fromshow.lb_yolov.move(0, self.fromshow.lb_xunlu.height())

6、发送信号

我们在init中定义一个新的定时器,每5s触发on_timer_timeout函数,然后会发送mysig_show_xunlu和mysig_show_yolov信号,信号槽接收到后,触发show_xunlu 和show_yolov 函数,去显示图片

    def __init__(self):

        。。。

        # 绑定信号槽
        self.connect_set()

        # 创建定时器  用于周期显示图片
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.on_timer_timeout)
        self.timer.start(5000)  # 每5秒触发一次

    def on_timer_timeout(self):
        # 每隔一段时间自动显示图片
        #emit() 方法用于发送信号
        self.sg.mysig_show_xunlu.emit()
        self.sg.mysig_show_yolov.emit()

 

然我们后面使用的时候不会这么草率的发送信号,而是通过循环截取地图,和屏幕中yolo推理当前屏幕图片进行显示的

7、全量代码

import ctypes
import sys

# 导入PyQt5模块
from PyQt5.QtCore import Qt, QTimer, QObject, pyqtSignal
from PyQt5.QtGui import QFont, QImage, QPixmap, QKeySequence
from PyQt5.QtWidgets import QDockWidget, QMainWindow, QApplication, QGridLayout, QWidget, QScrollArea, QAction

# 导入UI文件生成的类
from ui.show import Ui_DockWidget
from ui.main import Ui_mainWindow

class MySignal(QObject):

    # 无参数信号,可能用于触发显示某个路径或轨迹的操作
    mysig_show_xunlu = pyqtSignal()

    # 无参数信号,可能与YOLOv模型有关,用于触发显示模型输出或其他相关操作
    mysig_show_yolov = pyqtSignal()


# 定义FormShow类,继承自QDockWidget和Ui_DockWidget
class FormShow(QDockWidget, Ui_DockWidget):
    def __init__(self, parent=None):
        super(QDockWidget, self).__init__(parent)  # 调用父类构造函数
        self.parent = parent  # 保存父窗口引用
        self.setParent(parent)  # 设置父窗口
        self.setupUi(self)  # 初始化UI界面
        self.set_ui()  # 自定义设置UI界面

        # 设置窗口标题
        self.setWindowTitle("检测预览")

        # 设置标签控件属性
        self.lb_yolov.setScaledContents(True)
        self.lb_yolov.setAlignment(Qt.AlignCenter)
        self.lb_xunlu.setAlignment(Qt.AlignCenter)

        # 移动窗口位置
        self.move(0, 0)

        # 设置窗口保持在最顶层
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        # 计算窗口大小
        self.window_height = int(270 * ratio)
        self.window_width = int(480 * ratio)

        # 设置窗口最小尺寸
        self.setMinimumSize(self.window_width, self.window_height * 2)

        # 连接按钮点击事件
        self.bt_jia.clicked.connect(self.clicked_jia)
        self.bt_jian.clicked.connect(self.clicked_jian)

    # 自定义UI设置
    def set_ui(self):
        pass  # 此处可添加更多UI设置

    # 按钮“加”点击事件处理
    def clicked_jia(self):
        # 如果窗口高度加上增量后超过屏幕高度,则返回
        if self.window_height + 108 * ratio > 1080 * ratio:
            return

        # 更新窗口大小
        self.window_height += int(108 * ratio)
        self.window_width += int(190 * ratio)

        # 设置标签固定高度
        self.lb_xunlu.setFixedHeight(self.window_height)

        # 根据窗口宽度调整标签位置
        if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
            self.lb_yolov.move(self.lb_xunlu.width(), 0)
        else:
            self.lb_yolov.move(0, self.lb_xunlu.height())

        # 设置标签固定大小
        self.lb_yolov.setFixedHeight(self.window_height)
        self.lb_yolov.setFixedWidth(self.window_width)

    # 按钮“减”点击事件处理
    def clicked_jian(self):
        # 如果窗口高度减去增量后小于最小高度,则返回
        if self.window_height - 108 * ratio < 270 * ratio:
            return

        # 更新窗口大小
        self.window_height -= int(108 * ratio)
        self.window_width -= int(190 * ratio)

        # 设置标签固定高度
        self.lb_xunlu.setFixedHeight(self.window_height)

        # 根据窗口宽度调整标签位置
        if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
            self.lb_yolov.move(self.lb_xunlu.width(), 0)
        else:
            self.lb_yolov.move(0, self.lb_xunlu.height())

        # 设置标签固定大小
        self.lb_yolov.setFixedHeight(self.window_height)
        self.lb_yolov.setFixedWidth(self.window_width)

    # 重写关闭事件
    def closeEvent(self, event):
        # 关闭窗口时取消主窗口上的动作选中状态
        self.parent.action_isShow.setChecked(False)

    # 重写调整大小事件
    def resizeEvent(self, event):
        # 根据窗口宽度调整标签位置
        if self.width() >= self.lb_yolov.width() + self.lb_xunlu.width():
            self.lb_yolov.move(self.lb_xunlu.width(), 0)
        else:
            self.lb_yolov.move(0, self.lb_xunlu.height())


# 定义MainWindow类,继承自QMainWindow和Ui_mainWindow
class MainWindow(QMainWindow, Ui_mainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()  # 调用父类构造函数
        self.setupUi(self)  # 设置UI布局
        self.retranslateUi(self)  # 重新翻译UI组件的文字

        # 修改窗口样式为黑灰色,高亮
        self.set_ui()

        # 设置窗口标题
        self.setWindowTitle(f"修改主页标题")

        # 设置窗口尺寸
        self.resize(640, 900)

        # 设置窗口起始位置
        self.move(0, 300)

        # 创建网格布局
        self.g_box = QGridLayout()

        # 创建一个中间部件
        self.container_widget = QWidget()

        # 将网格布局设置给中间部件
        self.container_widget.setLayout(self.g_box)

        # 设置布局左上对齐
        self.g_box.setAlignment(Qt.AlignTop | Qt.AlignLeft)

        # 设置布局边距
        self.g_box.setContentsMargins(0, 0, 0, 0)

        # 设置布局左对齐
        self.g_box.setAlignment(Qt.AlignTop)

        # 将中间部件设置为QScrollArea的子部件
        self.sa_main.setWidget(self.container_widget)

        # 获取纵向滚动条控件
        vertical_scrollbar = self.findChild(QScrollArea)
        self.v_scrollbar = vertical_scrollbar.verticalScrollBar()

        # 设置窗口保持在最顶层
        self.setWindowFlags(Qt.WindowStaysOnTopHint)

        # 初始化变量
        self.row = 0
        self.column = -1
        self.run_times = 1
        self.column_step = 310

        # 获取主窗口的状态栏对象
        self.statusbar = self.statusBar()

        # 设置状态栏文本
        self.statusbar.showMessage('欢迎使用')

        # 初始化数据列表
        self.datas = []

        # 创建一个计时器,用于延迟布局
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)  # 设置为单次触发
        self.timer.timeout.connect(self.update_layout)

        # 绑定信号槽
        self.connect_set()

        # 创建定时器  用于周期显示图片
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.on_timer_timeout)
        self.timer.start(5000)  # 每5秒触发一次

    def on_timer_timeout(self):
        # 每隔一段时间自动显示图片
        self.sg.mysig_show_xunlu.emit()
        self.sg.mysig_show_yolov.emit()
    # 绑定信号槽
    def connect_set(self):
        # 创建一个顶级菜单
        self.menu = self.menuBar()
        self.menu_view = self.menu.addMenu("视图")

        # 创建一个动作
        self.action_isShow = QAction("显示检测结果窗口", self)
        self.action_isShow.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_F11))
        self.action_isShow.triggered.connect(self.hotkey_isShow)
        self.action_isShow.setCheckable(True)
        self.action_isShow.setChecked(True)
        self.menu_view.addAction(self.action_isShow)

        # 打开预测窗口
        self.hotkey_isShow()

        self.sg = MySignal()
        self.sg.mysig_show_xunlu.connect(self.show_xunlu)
        self.sg.mysig_show_yolov.connect(self.show_yolov)

    def show_xunlu(self, image_path="./datas/111.png"):
        # 加载本地图片
        pixmap = QPixmap(image_path)

        # 设置图片到 lb_xunlu 控件
        self.fromshow.lb_xunlu.setPixmap(pixmap)

        # 设置宽度固定,高度自适应
        self.fromshow.window_width = int(self.fromshow.window_height * pixmap.width() / pixmap.height())
        self.fromshow.lb_xunlu.setFixedHeight(self.fromshow.window_height)
        self.fromshow.lb_xunlu.setFixedWidth(self.fromshow.window_width)
        self.fromshow.lb_xunlu.setScaledContents(True)

    def show_yolov(self, image_path="./datas/111.png"):
        print(2222)
        # 加载本地图片
        pixmap1 = QPixmap(image_path)

        # 设置图片到 lb_yolov 控件
        self.fromshow.lb_yolov.setPixmap(pixmap1)

        # 根据窗口宽度调整 lb_yolov 的位置
        if self.fromshow.width() >= self.fromshow.lb_yolov.width() + self.fromshow.lb_xunlu.width():
            self.fromshow.lb_yolov.move(self.fromshow.lb_xunlu.width(), 0)
        else:
            self.fromshow.lb_yolov.move(0, self.fromshow.lb_xunlu.height())

    # 打开预测窗口
    def hotkey_isShow(self):
        # 尝试创建悬浮窗口实例
        if not hasattr(self, "fromshow"):
            self.fromshow = FormShow(self)  # 创建悬浮窗口实例

            self.addDockWidget(Qt.TopDockWidgetArea, self.fromshow)  # 添加悬浮窗口到主窗口

    # 更新布局
    def update_layout(self):
        try:
            # 获取主窗口的宽度
            width = self.centralWidget().width()

            # 计算每行可以容纳的组件数量
            num_per_row = (width) // (self.column_step * ratio)
            if num_per_row < 1:
                num_per_row = 1

            # 清空当前布局
            for i in reversed(range(self.g_box.count())):
                self.g_box.itemAt(i).widget().setParent(None)

            # 重新添加组件到网格布局
            for i, data in enumerate(self.datas):
                self.row = int(i // num_per_row)
                self.column = int(i % num_per_row)
                self.g_box.addWidget(data["f_item"], self.row, self.column)
        except:
            pass

    # 设置主窗口样式
    def set_ui(self):
        # 设置主题样式为 Flatwhite
        from qt_material import apply_stylesheet
        apply_stylesheet(app, theme='dark_pink.xml')

        # 设置窗口样式表
        self.setStyleSheet("""
        QScrollBar::handle:horizontal {
            background-color: #A50F2C;  /* 设置滑块颜色 */
        }
        QScrollBar::handle:horizontal:hover {
            background-color: #FF1744;  /* 设置滑块颜色 */
        }
        QPushButton:hover {
            background-color: #DFC472;  /* 设置颜色 */
        }
        QPlainTextEdit {
            padding: 0px;
            margin: 0px;
        }
        QPushButton {
            padding: 0px;
            margin: 1px;
        }
        """ + "font-family: {}; font-size: {}pt;".format(font.family(), font.pointSize()))


# 主程序入口
if __name__ == '__main__':
    # 获取屏幕宽度和高度
    screen_width = ctypes.windll.user32.GetSystemMetrics(0)
    screen_height = ctypes.windll.user32.GetSystemMetrics(1)

    # 初始化QT应用
    app = QApplication(sys.argv)

    # 计算分辨率比例
    ratio = screen_width / 2560

    # 设置全局字体大小
    base_font_size = 13
    new_font_size = int(base_font_size * ratio)
    font = QFont("Arial", new_font_size)

    # 创建主窗口实例
    window_main = MainWindow()

    # 显示主窗口
    window_main.show()

    # 监听消息不关闭
    sys.exit(app.exec_())


http://www.kler.cn/a/320541.html

相关文章:

  • LeetCode 2816.翻倍以链表形式表示的数字
  • 系统思考—跳出症状看全局
  • 如何在MindMaster思维导图中制作PPT课件?
  • 深入探索Scala迭代器:实用技巧与最佳实践
  • HTML之列表学习记录
  • 解决 IDEA 修改代码重启不生效的问题
  • 鸿蒙开发(NEXT/API 12)【硬件(取消注册监听系统导航信息和指令)】车载系统
  • 博图软件项目创建
  • 百度数据科学岗社招一面
  • pytorch学习笔记二:用pytorch神经网络模型做气温预测、分类任务构建和分类网络构建、卷积神经网络原理介绍
  • VM+Ubuntu16.04硬盘扩容
  • Python类里引用其他类
  • c++ day06
  • 【深度学习】(7)--神经网络之保存最优模型
  • 自动驾驶,被逼着上市?
  • 【Python机器学习】NLP信息提取——提取人物/事物关系
  • WPS文字 分栏注意项
  • Java项目实战II基于Java+Spring Boot+MySQL的汽车销售网站(文档+源码+数据库)
  • PyTorch开源的深度学习框架
  • 2、electron vue3 怎么创建子窗口,并给子窗口路由传参
  • 【Linux系统编程】第二十二弹---操作系统核心概念:进程创建与终止机制详解
  • LInux操作系统安装Jenkins
  • MFC-基础架构
  • 实验二十:ds1302时钟实验
  • 【MYSQL】聚合查询、分组查询、联合查询
  • CSS开发全攻略