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 ...
最新文章
- 2015年12月书单推荐
- case when mysql_mysql条件语句case when的实例
- linux 查看防火墙对应的进程,Linux系统防火墙进程查看的实用方法
- HDU 3949 XOR (线性基第k小)题解
- ORACLE数据库新增表空间的数据存储文件
- python连接pymysql主机目标无响应_Python 解析pymysql模块操作数据库的方法
- WinCE开发流媒体播放器--MPEG4
- iOS中唯一一款不带开屏广告的日历
- 有效利用GRE红宝书
- win10删除开机密码_win10老是自动更新怎么办?如何完全禁止win10自动更新?
- 绘制奥林匹克五环旗。
- RAFT共识算法学习
- 百兆宽带是怎么个一百兆?
- Xming(windows下的X Server)的使用,在windows下运行你的终端和所有基于XWindow的程序
- 单向链表与双向链表的区别
- 机器人操作系统ROS 编程开发--详细总结
- SODA-大型活动大规模人群的识别和疏散:从公交2.0到公交3.0
- “记忆力争夺战”走向尾声,“潜意识记忆营销”将成破局利器
- 2012智能手机发展格局解析
- java 方麦子_南方麦子什么时候成熟?小麦有什么营养价值呢?
热门文章
- NodeJs ES6 写简单爬虫 爬小说网站《我当方士那些年》
- 三千繁华,感情在日子里
- 借助于栈结构将一个单链表逆置
- 五子棋网络对战 java实现
- 曾經的文字﹐曾經的歲月
- UE4 UMG多行文本
- 语音识别(ASR)论文优选:关注语音识别系统Fairness问题Towards Measuring Fairness in Speech Recognition
- 算法笔记_110:第四届蓝桥杯软件类省赛真题(JAVA软件开发高职高专组部分习题)试题解答...
- http 代理服务器搭建 tinyProxy
- IDEA包下不能建包问题