日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

QT线程之 moveToThread() 只能用信号槽方式触发

發布時間:2024/1/8 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 QT线程之 moveToThread() 只能用信号槽方式触发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

qt的線程使用方法有把某個對象的函數放置線程里執行,方法為moveToThread()

具體操作步驟為:
1、創建一個新的類,讓這個類從 QObject 派生

class MyWork:public QObject {....... }

2、在這個類中添加一個公共的成員函數,函數體就是我們要子線程中執行的業務邏輯

class MyWork:public QObject { public:.......// 函數名自己指定, 叫什么都可以, 參數可以根據實際需求添加void working(); }

3、在主線程中創建一個 QThread 對象,這就是子線程的對象

QThread* sub = new QThread;

4、在主線程中創建工作的類對象(千萬不要指定給創建的對象指定父對象)

MyWork* work = new MyWork(this); // error MyWork* work = new MyWork; // ok

5、將 MyWork 對象移動到創建的子線程對象中,需要調用 QObject 類提供的 moveToThread() 方法

// void QObject::moveToThread(QThread *targetThread); // 如果給work指定了父對象, 這個函數調用就失敗了 // 提示: QObject::moveToThread: Cannot move objects with a parent work->moveToThread(sub); // 移動到子線程中工作

6、啟動子線程,調用 start(), 這時候線程啟動了,但是移動到線程中的對象并沒有工作
7、信號槽調用 MyWork 類對象的工作函數,讓這個函數開始執行,這時候是在移動到的那個子線程中運行的,需要外面的信號傳來讓MyWork執行工作函數。

下面是一套完整的工程:

//mywork.h #ifndef MYWORK_H #define MYWORK_H#include <QObject>class MyWork : public QObject {Q_OBJECT public:explicit MyWork(QObject *parent = nullptr);// 工作函數void working();signals:void curNumber(int num);public slots: };#endif // MYWORK_H //mywork.cpp #include "mywork.h" #include <QDebug> #include <QThread>MyWork::MyWork(QObject *parent) : QObject(parent) {}void MyWork::working() {qDebug() << "當前線程對象的地址: " << QThread::currentThread();int num = 0;while(1){emit curNumber(num++);if(num == 1000){break;}QThread::usleep(1);}qDebug() << "run() 執行完畢, 子線程退出...";} //widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QString> #include<QThread> #include "mywork.h"QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pbStart_clicked();void setNum(int num);private:Ui::Widget *ui;MyWork *work;QThread* sub; }; #endif // WIDGET_H //widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 創建線程對象sub = new QThread;// 創建工作的類對象// 千萬不要指定給創建的對象指定父對象// 如果指定了: QObject::moveToThread: Cannot move objects with a parentwork = new MyWork;// 將工作的類對象移動到創建的子線程對象中work->moveToThread(sub);// 啟動線程sub->start();// 讓工作的對象開始工作, 點擊開始按鈕, 開始工作connect(ui->pbStart, &QPushButton::clicked, work, &MyWork::working);// 顯示數據connect(work, &MyWork::curNumber, this, &Widget::setNum);}Widget::~Widget() {delete ui; }void Widget::on_pbStart_clicked() { // work->working(); //這個有點坑,下面重點講! }void Widget::setNum(int num) {ui->lb_time->setText(QString::number(num)); }

重點來了! 最主要的問題就是子對象的working()函數到底由誰來觸發的問題
對比原因在注釋寫的很清楚了

//正解,主線程點擊按鈕只是觸發信號,而working是由work自己來觸發的,并且在子線程執行 connect(ui->pbStart, &QPushButton::clicked, work, &MyWork::working); //錯誤示范?,原因在于下面兩個都是指定working由主線程來觸發,本質是執行主線程的槽函數 void Widget::on_pbStart_clicked() //本質上這是個槽函數,點擊按鈕就執行這個槽函數 {work->working(); //因為work對象在主線程里定義的,如此執行working也是在主線程 } //或者 connect(ui->pbStart,&QPushButton::clicked,[=](){work->working(); //這和上面on_pbStart_clicked()里被調用沒有區別 });

總結

以上是生活随笔為你收集整理的QT线程之 moveToThread() 只能用信号槽方式触发的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。