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() 只能用信号槽方式触发相关推荐
- 【QT开发笔记-基础篇】| 第一章 QT入门 | 1.7 如何连接信号槽
本节对应的视频讲解:B_站_链_接 https://www.bilibili.com/video/BV1mN4y137H6 信号和槽要建立连接,本质上是通过 `connect` 函数来连接实现的. 但 ...
- Qt线程之QRunnable的使用详解
概述 说到线程通常会想到QThread,但其实Qt中创建线程的方式有多种,这里主要介绍其中一种QRunnable,QRunnable和QThread用法有些不同,并且使用场景也有区别.接下来就来看看Q ...
- 安全云盘项目(三):3.1 Qt的工具_MVD架构和信号槽原理分析
一:关于Qt程序整体内容: 二:项目结构模式 (1)MVC:这个已经优点过时,现在前端界面开发最常用的事第二种方式MVD (2)MVD 代码如下: main.cpp #include "xd ...
- QT中connect、disconnect和信号槽实现原理
connect connect用于连接信号和槽函数,但是我们经常忽略最后一个参数,本人在写代码时遇到了bug,选择一个符号进行多次标绘,再选择其他符号时,会将上一次选择的符号也进行标绘,主要时conn ...
- 在Qt中使用回调函数替代信号槽
前言 在Qt中传数据,我们使用了一个信号和槽系统,但这并不意味着不能使用旧的经过验证的方法,即使用 CallBack回调函数功能. 事实上使用 CallBack 功能比信号和槽要快一些.并且当发送信号 ...
- Qt信号阻塞和断开信号槽
Qt信号阻塞和断开信号槽 Qt程序中有时候不希望信号槽的触发,在某段流程结束之后,又需要继续回复信号槽状态,这时候可以用阻塞或者断开信号槽的方法来处理. 1. 阻塞方法 bool QObject::b ...
- 13.QT信号槽的连接方式
QT的信号槽机制和线程的启动方式已经在前面的文章中写过了,本文主要是对信号槽的连接方式进行解读,信号槽的连接方式一共有5种: 1.Qt::DirectConnection 发出信号后立即调用槽函数. ...
- Qt学习笔记-----信号槽
Qt提供signals and slots mechanism(信号槽机制)来保证两个对象之前的关联(connection). 所谓信号槽,简单理解就是两部分,一个是某对象发出的信号,一个是某对象接收 ...
- Qt学习之路(9):深入了解信号槽
信号槽机制是Qt编程的基础.通过信号槽,能够使Qt各组件在不知道对方的情形下能够相互通讯.这就将类之间的关系做了最大程度的解耦. 槽函数和普通的C++成员函数没有很大的区别.它们也可以使virtual ...
最新文章
- 安装部署中的数据库打包和快捷方式启动浏览器
- 计划策略-10-净需求计划
- Python学习笔记:Day13 提升开发效率
- Java-二分查找算法
- SQL注入(SQL注入(SQLi)攻击)攻击-联合注入
- 易度甘特图的功能介绍和开发手册
- 【学习笔记】【C语言】结构体
- 清华学霸被Facebook开除了
- php 截取www后面的目录,php-如何从字符串路径中获取最后一个目录
- ubuntu下安装最新 版jre 7
- Idea中找不到Java Application 的xml配置文件问题研究
- 不加群就可以提取QQ群成员
- 震惊!!【微信拼图红包】继微信语音红包后又一新技能
- 在线画图工具ProcessOn
- 电力拖动自动控制系统_专插本专业全面分析:电子工程及其自动化
- 【高效学数据库】第一范式、第二范式、BCNF范式、第三范式、第四范式概念及举例
- 统计学 参数估计 之 总体均值的估计
- 十二载征程犹未止,看今朝星光尽闪耀丨万字长文回顾2023数据技术嘉年华
- bboss ioc快速入门教程
- 延边大学计算机专业考研,计算机专业考研成功经验谈
热门文章
- 第三方支付机构是如何产生的?有着怎样的历史背景?它的未来又该如何去走得更加辉煌?
- 第十二届蓝桥杯省赛JAVA B组杨辉三角形个人题解
- [JavaScript] JS求闭区间[min,max]的和
- IP归属地查询(基于本地IP库实现)
- linux d14 Apache、 Vsftpd
- 按键精灵移动端系列 - IOS(苹果版)安装1.3.8 deb
- php实现独立模块,poscms独立模块URL规则
- 让图片动起来——Real_Time_Image_Animation
- Singularity 快速上手, 带你飞
- 解决缺少 SHA256.h文件