Qt多线程之继承QObject(moveToThread方式)

mac2025-02-07  20

Qt多线程有两两种方式,第一种继承QThread,复写run()函数,但是run()和main()类似,run()函数才是子线程的入口函数,所以在设计到类的操作时,必须把对象或者指针放在run函数里面,否则就不在一个线程里面了,会出现错误。

第二种方式,继承QObject,通过moveToThread()将自定义的线程添加到子线程QThread里,然后信号槽的方式实现,shix实现主线程和子线程的交互。

本文只为给自己学习QT多线程做个笔记。本文使用第二种方式,Qt官方主推的方式。

注意:

继承QObject,调用moveToThread方法用的时候要强调的几个重点: 自定义的MyThread线程类的对象在创建时不能指定父对象! 启动子线程后,并没有启动子线程处理函数; 启动子线程处理函数必须用signal-slot方式!!! 在线程处理函数内部,绝对不允许操作ui图形界面(比如跳个弹窗等等),线程内部通常是纯数据处理!  

代码如下:

1.pro文件

#------------------------------------------------- # # Project created by QtCreator 2019-10-29T14:52:07 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = ThreadUI2 TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 CONFIG += c++11 SOURCES += \ main.cpp \ widget.cpp \ mythread.cpp HEADERS += \ widget.h \ mythread.h FORMS += \ widget.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target

2.mythread.h文件

#ifndef MYTHREAD_H #define MYTHREAD_H #include <QObject> class MyThread : public QObject { Q_OBJECT public: explicit MyThread(QObject *parent = nullptr); ~MyThread(); //线程处理函数 void MyTimeout(); void setFlag(bool flag = true); signals: void mySignal();//定义一个信号,在该子线程中每秒发射一次该信号 private: bool isStop; public slots: }; #endif // MYTHREAD_H

3.mythread.h文件

#include "mythread.h" #include<QThread> #include<QtDebug> MyThread::MyThread(QObject *parent) : QObject(parent) { isStop=false; } MyThread::~MyThread() { } void MyThread::MyTimeout() { while(isStop==false) { QThread::sleep(1); emit mySignal(); qDebug()<<"sub thread :"<<QThread::currentThread(); if(true==isStop) { break; } } } void MyThread::setFlag(bool flag) { isStop=flag; }

4.widget.h文件

#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include"mythread.h" #include<QThread> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = nullptr); ~Widget(); signals: void startThread();//启动子线程的信号 private slots: void on_pushButtonStart_clicked(); void on_pushButtonStop_clicked(); void dealSignal(); void dealClose(); private: Ui::Widget *ui; MyThread *myT; QThread *thread; }; #endif // WIDGET_H

5.widget.cpp文件

#include "widget.h" #include "ui_widget.h" #include<QtDebug> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); myT=new MyThread; thread=new QThread(this);//创建子线程 myT->moveToThread(thread);//把自定义的线程加入到子线程中 connect(myT,&MyThread::mySignal,this,&Widget::dealSignal); qDebug()<<"main thread: "<<QThread::currentThread(); connect(this,&Widget::startThread,myT,&MyThread::MyTimeout); connect(this,&Widget::destroyed,this,&Widget::dealClose);//右上角X 关了 窗口线程还在运行 } Widget::~Widget() { delete ui; } void Widget::dealSignal() { static int i=0; i++; ui->lcdNumber->display(i); } void Widget::dealClose() { on_pushButtonStop_clicked();//停止线程 delete myT; //释放线程空间 } //start按钮 void Widget::on_pushButtonStart_clicked() { if(thread->isRunning()==true) { return; } //启动线程 但是满意启动线程处理函数 thread->start(); myT->setFlag(false); //不能直接调用线程处理函数,直接调用导致线程处理函数和主线程在同一个线程 // myT->myTimeout();/ //只能通过signal - slot方式 emit startThread(); } //stop按钮 void Widget::on_pushButtonStop_clicked() { if(thread->isRunning()==false) { return; } myT->setFlag(true); thread->quit(); thread->wait(); }

6.widget.ui文件

<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Widget</class> <widget class="QWidget" name="Widget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>418</width> <height>276</height> </rect> </property> <property name="windowTitle"> <string>Widget</string> </property> <layout class="QVBoxLayout" name="verticalLayout" stretch="2,0"> <item> <widget class="QLCDNumber" name="lcdNumber"/> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QPushButton" name="pushButtonStart"> <property name="text"> <string>Start</string> </property> </widget> </item> <item> <widget class="QPushButton" name="pushButtonStop"> <property name="text"> <string>Stop</string> </property> </widget> </item> </layout> </item> </layout> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui>

7.UI界面

最新回复(0)