栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

QThread创建多线程之子类化QThread方法

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

QThread创建多线程之子类化QThread方法

参考《qt5与opencv3计算机视觉应用开发》

通过创建一个示例项目来说明如何使用QThread及其附属类创建多线程应用程序。qt里创建多线程有两种方法:一是子类化 QThread 并重写run方法,另一种是使用moveToThread函数。

1 子类化QThread 1.1 创建应用程序

创建名为 MultithreadedCV 的Qt 控件应用程序,注意在 .pro 文件中包含 opencv。在 ui 界面上添加两个 QLbel 类标签,网格布局,左边标签为 inVideo,右边标签为 outVideo。将两者的 alignment/Horizontal 属性设置为 AlignHCenter。如下图:

1.2 创建 QThread 子类

右键项目,从菜单中选择 " Add new",创建名为 VideoProcessorThread 的新类。确保在新的类向导中的界面与下图一致:

1.3 更新代码

首先在新创建的 .h 头文件中更新包含文件 #include,添加

#include 
#include "opencv2/opencv.hpp"
#include 

更新类名,将头文件中的继承自 QObject 改成继承自 QThread,如下:

class VideoProcessorThread : public QThread

更新新创建的 .cpp 文件中的构造函数:

VideoProcessorThread::VideoProcessorThread(QObject *parent) : QThread(parent)
{

}

然后就可以编辑函数定义和实现了。
向新添加的头文件中添加一些必要的声明,将下列代码添加至类的私有成员区域:

void run() override;

然后将下列代码添加至 signals 部分:

void inDisplay(QPixmap pixmap);
void outDisplay(QPixmap pixmap);

将 run 函数的实现添加到 .cpp 文件:

 void VideoProcessorThread::run()
{
    using namespace cv;

    VideoCapture camera(0);
    Mat inFrame, outFrame;
    while(camera.isOpened() && !isInterruptionRequested())
    {
        camera >> inFrame;
        if(inFrame.empty())
            continue;
        bitwise_not(inFrame, outFrame);

        emit inDisplay(
                    QPixmap::fromImage(
                        QImage(
                            inFrame.data,
                            inFrame.cols,
                            inFrame.rows,
                            inFrame.step,
                            QImage::Format_RGB888)
                        .rgbSwapped()));

        emit outDisplay(
                    QPixmap::fromImage(
                        QImage(
                            outFrame.data,
                            outFrame.cols,
                            outFrame.rows,
                            outFrame.step,
                            QImage::Format_RGB888)
                        .rgbSwapped()));
    }
}
1.4 启动程序

为了控制线程及其执行行为,需要使用以下函数:

  • start: 用于启动一个尚未启动的线程,该函数通过调用所实现的 run 函数来启动执行。在这里就是我们实现的子类 run()。
  • terminate: 用于强制终止线程。
  • setTerminationEnabled: 用于允许或禁止 terminater 函数。
  • wait: 用于阻塞线程(强制等待),直至线程完成或者达到超时值。
  • requestInterruption 和 isRequestInterrupted: 用于设置和获取中断请求状态。
  • isRunning 和 isFinished: 用于请求线程的执行状态。
    在 MainWindow 中使用线程(调用线程),将其头文件包含进 mainwindow.h:
#include "videoprocessorthread.h"

然后,将下面的代码行添加到 MainWindow 的私有成员部分:

VideoProcessorThread processor;

使用 connect 将连接信号和槽,在 MainWindow 构造函数中添加如下代码:

connect(&processor,
        SIGNAL(inDisplay(QPixmap)),
        ui -> inVideo,
        SLOT(setPixmap(QPixmap)));

connect(&processor,
        SIGNAL(outDisplay(QPixmap)),
        ui -> outVideo,
        SLOT(setPixmap(QPixmap)));

processor.start();

将下列代码添加到 MainWindow 析构函数中,放在 delete ui; 代码行之前:

processor.requestInterruption();
processor.wait();

在析构函数中调用 requestInterruption() 函数,能够保证一旦 MainWindow 关闭并且删除 GUI 之前请求线程停止,通过调用 wait 函数,能够确保等待线程完成清理并安全执行完毕之后再继续执行 delete 指令。

1.5 流程总结
  1. 创建应用程序,一定要包含 QObject,修改 ui 界面,修改 ObjectName 属性,修改布局等;

  2. 创建新的子类,在头文件中添加要使用的文件,修改相关类和构造函数; 在子类中添加函数声明和实现;

  3. 在主程序中添加包含文件,并在头文件中的私有成员中使用 VideoProccessorThread 类的构造函数创建线程指针processer,然后添加信号和槽的连接;

  4. 调用 start() 函数启动线程,在析构函数中添加 requestInterruption 和 wait 函数用于保证安全。

可以在一个进程中创建多个线程,方法就是创建多个 QThread 的实例(即为创建多个类),然后在 MainWindow 的头文件中创建一个 VideoProcessorThread(创建的类名) 的指针,然后使用 start() 函数即可启动多个线程。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1005053.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号