欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > QT_Demo(1)之实现多线程实现简单的电脑摄像头视频流开关

QT_Demo(1)之实现多线程实现简单的电脑摄像头视频流开关

2025/10/23 17:20:40 来源:https://blog.csdn.net/yohnyang/article/details/144645707  浏览:    关键词:QT_Demo(1)之实现多线程实现简单的电脑摄像头视频流开关

QT_Demo(1)之实现多线程实现简单的电脑摄像头视频流开关

  • 使用qt中的多线程进行功能控制:继承QThread
  • 直接通过代码进行UI搭建
  • 简单示例使用信号与槽

1. 功能介绍

  • 首先想搭一个界面可以交互,从而实现手动开关笔记本摄像头的目的

  • 想通过多线程进行功能实现,从而提升稳定性和运行速度

  • 基础界面设置为QWidget,图像通过QLabel 显示

  • 界面一览:
    在这里插入图片描述

  • 创建项目

    • 我用的是VS中的qt插件 qt tools 来进行界面开发,如果没有在扩展->管理扩展->联网下载即可
    • 下方给出了两种工程种类,1是一个全空的qt 工程,2比1多了个UI文件,并在创建项目的时候可以选择UI文件的基类,在此我选择2进行开发吧
    • 工程2自带了UI文件,我目前对纯代码界面开发还不太熟练,稍微复杂的话还是直接通过QDesigner打开UI文件直接进行拉控件搭界面简单易行一些
      在这里插入图片描述
  • 基类可以在QMainWindow 、QWidget、QDialog中选择,这里随便选一个,先进入工程
    在这里插入图片描述

  • 选择完成后工程文件列表如下:
    在这里插入图片描述

2. 代码实现

  • 本文中主要通过纯代码进行UI搭建

  • 本次使用了opencv,需要在项目属性中配置opencv

  • 右键项目添加新建项 -> 添加类
    在这里插入图片描述

  • 代码如下:

  • VideoDisplayWidget.h

#include <QApplication>
#include <QWidget>
#include <QImage>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QThread>
#include <opencv2/opencv.hpp>#include <QPainter>
#include <QMouseEvent>
#include <QWheelEvent>// 视频采集线程
class VideoCaptureThread : public QThread
{Q_OBJECT
public:VideoCaptureThread(QObject* parent = nullptr);~VideoCaptureThread();void startCapture();void stopCapture();void run() override;public:cv::VideoCapture cap;signals:void newFrame(const QImage& frame); // 向主线程发送新帧private:bool running;
};// 主窗口类
class VideoDisplayWidget : public QWidget
{Q_OBJECT
public:VideoDisplayWidget(QWidget* parent = nullptr);~VideoDisplayWidget();public slots:void onNewFrame(const QImage& frame);// 启动视频采集线程void startCapture();// 停止视频采集线程void stopCapture();private:QLabel* label;VideoCaptureThread* captureThread;};
  • VideoDisplayWidget.cpp
#include"VideoDisplayWidget.h"// 视频采集线程
VideoCaptureThread::VideoCaptureThread(QObject* parent) : QThread(parent), running(false) {}
VideoCaptureThread::~VideoCaptureThread() {}void VideoCaptureThread::startCapture()
{cap.open(0); // 打开默认摄像头if (!cap.isOpened()) {qWarning("Failed to open the camera");return;}running = true;start();
}void VideoCaptureThread::stopCapture()
{running = false;
}void VideoCaptureThread::run()
{while (running) {cv::Mat frame;if (cap.read(frame)) {cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); // 转换为 RGB 格式QImage image(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);emit newFrame(image);}msleep(30); // 控制帧率}
}// -----------------------VideoDisplayWidget------------------------------------------// 主窗口类
VideoDisplayWidget::VideoDisplayWidget(QWidget* parent) : QWidget(parent), label(new QLabel(this)), captureThread(new VideoCaptureThread())
{// 设置界面布局QVBoxLayout* layout = new QVBoxLayout(this);layout->addWidget(label);QPushButton* startButton = new QPushButton("Start Capture", this);QPushButton* stopButton = new QPushButton("Stop Capture", this);layout->addWidget(startButton);layout->addWidget(stopButton);// 设置窗口大小setFixedSize(640, 480);this->setWindowTitle(QString::fromLocal8Bit("VideoManager"));// 初始化线程和控件label->setFixedSize(640, 480);label->setAlignment(Qt::AlignCenter);connect(captureThread, &VideoCaptureThread::newFrame, this, &VideoDisplayWidget::onNewFrame);connect(startButton, &QPushButton::clicked, this, &VideoDisplayWidget::startCapture);connect(stopButton, &QPushButton::clicked, this, &VideoDisplayWidget::stopCapture);
}VideoDisplayWidget::~VideoDisplayWidget()
{captureThread->stopCapture();captureThread->wait();
}void VideoDisplayWidget::onNewFrame(const QImage& frame)
{label->setPixmap(QPixmap::fromImage(frame));
}void VideoDisplayWidget::startCapture()
{captureThread->startCapture();
}void VideoDisplayWidget::stopCapture()
{captureThread->stopCapture();
}
  • main.cpp 更改如下:
//#include "videocam1.h"
#include <QtWidgets/QApplication>
#include"VideoDisplayWidget.h"int main(int argc, char *argv[])
{//基类时QMainWindowQApplication a(argc, argv);//videocam1 w;//基类时QWidgetVideoDisplayWidget w;w.show();return a.exec();
}

3. designer 搭建UI

  • 使用qdesigner打开ui文件如下:起始UI主要包含右上角4项:中心主控件、菜单栏、工具栏和状态栏
  • 然后简单拉两个按钮+个label进行搭建
  • 窗体->查看代码->保存 会生成ui_videocam1.h,它包含了界面的相关内容:控件及尺寸、位置等属性
    在这里插入图片描述
  • 添加布局,并将所有控件的策略改为preferred,最后将总布局设为网格布局,UI就支持整体缩放了,具体实现可参考:https://blog.csdn.net/yohnyang/article/details/128469084
    在这里插入图片描述
  • 然后在项目中的VideoDisplayWidget.h,VideoDisplayWidget.cpp 移除项目,videocam1.h,videocam1.cpp做出如下更改:
#pragma once#include <QtWidgets/QMainWindow>
#include "ui_videocam1.h"
#include <QApplication>
#include <QWidget>
#include <QImage>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QThread>
#include <opencv2/opencv.hpp>#include <QPainter>
#include <QMouseEvent>
#include <QWheelEvent>// 视频采集线程
class VideoCaptureThread : public QThread
{Q_OBJECT
public:VideoCaptureThread(QObject* parent = nullptr);~VideoCaptureThread();void startCapture();void stopCapture();void run() override;public:cv::VideoCapture cap;signals:void newFrame(const QImage& frame); // 向主线程发送新帧private:bool running;
};class videocam1 : public QMainWindow
{Q_OBJECTpublic:videocam1(QWidget *parent = nullptr);~videocam1();public slots:void onNewFrame(const QImage& frame);// 启动视频采集线程void startCapture();// 停止视频采集线程void stopCapture();private:Ui::videocam1Class ui;VideoCaptureThread* captureThread;
};
#include "videocam1.h"// 视频采集线程
VideoCaptureThread::VideoCaptureThread(QObject* parent) : QThread(parent), running(false) {}
VideoCaptureThread::~VideoCaptureThread() {}void VideoCaptureThread::startCapture()
{cap.open(0); // 打开默认摄像头if (!cap.isOpened()) {qWarning("Failed to open the camera");return;}running = true;start();
}void VideoCaptureThread::stopCapture()
{running = false;
}void VideoCaptureThread::run()
{while (running) {cv::Mat frame;if (cap.read(frame)) {cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); // 转换为 RGB 格式QImage image(frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888);emit newFrame(image);}msleep(30); // 控制帧率}
}videocam1::videocam1(QWidget *parent)
{ui.setupUi(this);this->setWindowTitle(QString::fromLocal8Bit("VideoManager"));captureThread = new VideoCaptureThread();connect(captureThread, &VideoCaptureThread::newFrame, this, &videocam1::onNewFrame);connect(ui.pushButton, &QPushButton::clicked, this, &videocam1::startCapture);connect(ui.pushButton_2, &QPushButton::clicked, this, &videocam1::stopCapture);
}videocam1::~videocam1()
{}void videocam1::onNewFrame(const QImage& frame)
{ui.label->setPixmap(QPixmap::fromImage(frame));ui.label->setScaledContents(true);
}void videocam1::startCapture()
{captureThread->startCapture();
}void videocam1::stopCapture()
{captureThread->stopCapture();
}
  • main()更改如下:
#include "videocam1.h"
#include <QtWidgets/QApplication>
//#include"VideoDisplayWidget.h"int main(int argc, char *argv[])
{//基类时QMainWindowQApplication a(argc, argv);videocam1 w;//基类时QWidget//VideoDisplayWidget w;w.show();return a.exec();
}
  • 运行如下:
    在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词