当前位置: 首页 > news >正文

QThread 与QObject::moveToThread在UI中的应用

1. QThread的两种用法

第一种用法就是继承QThread,然后覆写 virtual void run(), 这种用法的缺点是不能利用信号槽机制。

第二种用法就是创建一个线程,创建一个对象,再将对象moveToThread, 这种可以充分利用信号槽机制,与UI框架完美融合。这与std::thread也是不一样的地方。

2. moveToThread用法讲解

示例地址:MultiThread/QThreadDemo · 沁明/QtDemo - 码云 - 开源中国 (gitee.com)

直接调用 QObject::moveToThread() 函数,将继承自 QObject 的对象移到线程里面。此时该对象的 槽函数运行在另一个线程里面。 也就是说,当有信号绑定到该对象的槽函数的时候,并发送信号,该槽函数就运行在另一个线程里,否则该函数仍然运行在对象所在的线程中。

1)先创建一个QObject的子类。

它要运行的函数都可以在子线程中运行。

worker.h

#ifndef WORKER_H
#define WORKER_H#include <QObject>class Worker : public QObject
{Q_OBJECT
public:explicit Worker(QObject *parent = nullptr);public slots:void workSlot();void msg1Slot(const QString &m1);void msg3Slot(const QString &m3);signals:void msg1(const QString &m1);void msg2(const QString &m2);
};#endif // WORKER_H

 worker.cpp

#include "worker.h"#include <QDebug>
#include <QThread>Worker::Worker(QObject *parent) : QObject{parent} {connect(this, &Worker::msg1, this, &Worker::msg1Slot);
}void Worker::workSlot() {qDebug() << "QThread begin";qDebug() << "child thread id" << QThread::currentThreadId();qDebug() << "QThread end";// 线槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过// quit() 退出线程exec()。
}void Worker::msg1Slot(const QString &m1) {qDebug() << QThread::currentThreadId() << "receive msg1 " << m1;
}void Worker::msg3Slot(const QString &m3) {qDebug() << QThread::currentThreadId() << "receive msg3 " << m3;
}

2)创建worker对象

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow), thread(nullptr) {ui->setupUi(this);worker = new Worker;qDebug() << "主线程" << QThread::currentThreadId();connect(worker, &Worker::msg2, this, &MainWindow::msg2Slot);connect(this, &MainWindow::msg3, worker, &Worker::msg3Slot);
}

直接在窗口构造函数中创建worker对象,程序运行期间这个对象不会被析构。

由于要使用moveToThread函数,所以worker不能设置父对象的,必须为空。

绑定了两个槽函数,分别用来响应消息2和消息3, 但是消息2的槽在窗口对象上,消息3的槽函数在worker对象上。

3)如果不创建子线程,看看3条消息的执行线程在哪?

 如果没有启用子线程的时候,3条消息执行函数都在主线程上。

4)启用子线程之后,3条消息的执行线程是什么?

void MainWindow::on_pushButtonStart_clicked() {qDebug() << "on_pushButtonStart_clicked线程" << QThread::currentThreadId();if (thread)return;thread = new QThread;worker->moveToThread(thread);QObject::connect(thread, &QThread::started, worker, &Worker::workSlot);QObject::connect(thread, &QThread::finished, this,&MainWindow::workerDetach);thread->start();
}

 这里创建了子线程,然后将worker对象移动线程内执行。 

workSlot()执行完毕之后其实线程并没有结束,它会执行exec()进入线程的消息循环

void Worker::workSlot() {qDebug() << "QThread begin";qDebug() << "child thread id" << QThread::currentThreadId();qDebug() << "QThread end";// 线槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过// quit() 退出线程exec()。
}

后面在worker上的信号或者槽绑定的触发都会进行响应。

 使用QThread启动子线程之后,消息1和消息3 的槽函数在子线程上执行了。

但是消息2的槽函数仍在主线程上。

重新复习一下信号槽绑定

Worker::Worker(QObject *parent) : QObject{parent} {connect(this, &Worker::msg1, this, &Worker::msg1Slot);
}

  connect(worker, &Worker::msg2, this, &MainWindow::msg2Slot);connect(this, &MainWindow::msg3, worker, &Worker::msg3Slot);

可以看出槽函数的执行线程就是对象所在的线程。

在创建了子线程之后,worker的执行线程已经发生了变化,所以消息1、3执行线程也变成了子线程。

5)停止子线程之后,恢复原来线程

QObject::connect(thread, &QThread::finished, this,&MainWindow::workerDetach);void MainWindow::workerDetach() {qDebug() << "workerDetach线程" << QThread::currentThreadId();worker->moveToThread(QThread::currentThread());
}

设置在线程退出之后重新移动对象到主线程。

相关文章:

QThread 与QObject::moveToThread在UI中的应用

1. QThread的两种用法 第一种用法就是继承QThread&#xff0c;然后覆写 virtual void run()&#xff0c; 这种用法的缺点是不能利用信号槽机制。 第二种用法就是创建一个线程&#xff0c;创建一个对象&#xff0c;再将对象moveToThread, 这种可以充分利用信号槽机制&#xff…...

安卓逆向案例——X酷APP逆向分析

X酷APP逆向分析 这里介绍一下两种不同的挂载证书的方法。 chls.pro/ssl无法在浏览器中下载证书是什么原因解决方法&#xff1a; 法一 1. 挂载系统分区为读写 使用正确的挂载点来挂载系统分区为读写&#xff1a; su mount -o remount,rw /dev/uijISjR/.magisk/block/syste…...

创新案例|星巴克中国市场创新之路: 2025目标9000家店的挑战与策略

星巴克创始人霍华德舒尔茨&#xff1a;“为迎接中国市场的全面消费复苏&#xff0c;星巴克2025年推进9000家门店计划&#xff0c;将外卖、电商以及家享和外出场景咖啡业务纳入中国新一轮增长计划中。”在面临中国市场同店增长大幅下滑29%背景下&#xff0c;星巴克通过DTC用户体…...

计算机网络 MAC地址表管理

一、理论知识 1.MAC地址表&#xff1a;交换机使用MAC地址表来记录各MAC地址对应的端口&#xff0c;用于帧转发的目的。 2.老化机制&#xff1a;交换机会为每一条MAC地址表项设置老化时间&#xff0c;老化时间到期后未收到该MAC地址报文的表项将被删除&#xff0c;释放资源。 …...

【免费API推荐】:各类API资源免费获取【11】

欢迎来到各类API资源的免费获取世界&#xff01;幂简集成为您提供了一个集合了各种免费API接口的平台。无论您是开发者、数据分析师还是创业者&#xff0c;都可以通过我们的平台轻松免费获取所需的API资源。幂简精心整理了各类API接口&#xff0c;涵盖了不同领域的需求&#xf…...

技术驱动会展:展位导航系统的架构与实现

随着会展行业的快速发展&#xff0c;大型会展中心面临着如何提升参展者体验、提高招商效率的挑战。针对客户反馈的展馆面积大、展位查找困难等问题&#xff0c;维小帮提出一套智慧会展导航解决方案&#xff0c;旨在通过先进的室内导航技术提升会展中心的运营效率和参展者的满意…...

适用于轨道交通专用的板卡式网管型工业以太网交换机

是网管型 CompactPCI板卡式冗余环网交换机。前面板带有6个 10/100/1000Base-T(X)M12接口。后面的CPCI接口有 8个10/100/1000Base-T (X) 以太网接口。 是特别为轨道交通行业EN50155标准要求而设计的坚固型交换机。它同时具有以下特性&#xff1a; ● 支持2线以太网距离扩展端口&…...

excel基本操作

excel 若要取消在数据表中进行的所有筛选 步骤操作&#xff1a; 单击“数据”选项卡。在“排序和筛选”组中&#xff0c;找到“清除”按钮。点击“清除”按钮。 图例&#xff1a; 将文本文件的数据导入到Excel工作表中进行数据处理 步骤&#xff1a; 在Excel中&#xff0c…...

C++系统相关操作2 - 获取系统环境变量

1. 关键词2. sysutil.h3. sysutil.cpp4. 测试代码5. 运行结果6. 源码地址 1. 关键词 C 系统调用 环境变量 getenv 跨平台 2. sysutil.h #pragma once#include <cstdint> #include <string>namespace cutl {/*** brief Get an environment variable.** param na…...

适合小白学习的项目1906java Web智慧食堂管理系统idea开发mysql数据库web结构java编程计算机网页源码servlet项目

一、源码特点 java Web智慧食堂管理系统是一套完善的信息管理系统&#xff0c;结合java 开发技术和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 前段主要技术 bootstra…...

AI通用大模型不及垂直大模型?各有各的好

​​​​​​​AI时代&#xff0c;通用大模型和垂直大模型&#xff0c;两者孰优孰劣&#xff0c;一直众说纷纭。 通用大模型&#xff0c;聚焦基础层&#xff0c;如ChatGPT、百度文心一言&#xff0c;科大讯飞星火大模型等&#xff0c;都归属通用大模型&#xff0c;它们可以解答…...

农产品价格信息系统小程序

一键掌握市场脉动 &#x1f33e; 引言&#xff1a;为何关注农产品价格&#xff1f; 在当今社会&#xff0c;农产品价格的波动直接关系到农民的收入和消费者的生活成本。因此&#xff0c;及时、准确地掌握农产品价格信息&#xff0c;对于农民合理安排生产、消费者做出购买决策都…...

【LLM-多模态】高效多模态大型语言模型综述

一、结论写在前面 模型规模的庞大及训练和推理成本的高昂&#xff0c;限制了MLLMs在学术界和工业界的广泛应用。因此&#xff0c;研究高效轻量级的MLLMs具有巨大潜力&#xff0c;特别是在边缘计算场景中。 论文深入探讨了高效MLLM文献的领域&#xff0c;提供了一个全面的视角…...

ASP .Net Core创建一个httppost请求并添加证书

ASP .Net Core创建一个httppost请求并添加证书 创建.net Core程序&#xff0c;使用自签名证书&#xff0c;可以处理https的get和post请求。 创建证书 创建自签名证书的流程可以在这里查看&#xff1a; https://blog.csdn.net/GoodCooking/article/details/139815278创建完毕…...

Redis入门篇

目录 传送门一、前言二、NoSQL1、ont only sql&#xff0c;特点&#xff1a;2、NoSQL的四大分类&#xff1a; 三、Redis概念四、五大数据类型: 传送门 SpringMVC的源码解析&#xff08;精品&#xff09; Spring6的源码解析&#xff08;精品&#xff09; SpringBoot3框架&#…...

变电站智能巡检机器人解决方案

我国拥有庞大的电网体系&#xff0c;变电站数量众多&#xff0c;且近年来快速增长。然而目前我国变电站巡检方式仍以人工为主&#xff0c;存在效率低下、监控不全面等问题。变电站通常是一个封闭的系统空间&#xff0c;设备种类繁多、占地面积广阔&#xff0c;这对巡检人员实时…...

Linux Kernel入门到精通系列讲解(QEMU-虚拟化篇) 2.5 Qemu实现RTC设备

1. 概述 上一章节起(5.4小节),我们已经把整个Naruto Pi都跑通了,从BL0到kernel再到Rootfs都通了,目前可以说已经具备学习Linux得基础条件,剩下得都只是添砖加瓦,本小节我们将添加RTC,如果你还没有添加RTC,你可以试试不添加RTC时,Linux的时间戳会很奇怪,加了RTC后,…...

【自动驾驶】通过下位机发送的加速度、角速度计算机器人在世界坐标系中的姿态

文章目录 原始代码全局变量定义逆平方根函数四元数解算函数理论解释四元数加速度计数据归一化计算方向余弦矩阵的第三行计算误差计算并应用积分反馈应用比例反馈积分陀螺仪数据,更新四元数归一化四元数更新姿态数据整体流程原始代码 #define SAMPLING_FREQ 20.0f // 采样频率…...

Python 设计模式(第2版) -- 第四部分(其他设计模式)

Python 设计模式(第2版) 最后介绍下其他设计模式。 模型—视图—控制器&#xff08;MVC&#xff09;-- 复合模式 根据 GoF 的定义&#xff0c;“复合模式将两个或更多模式组合成解决常见或普遍性问题的解决方案”。复合模式不是同时使用的一组模式&#xff0c;而是一个问题的…...

gitlab升级16.11.3-ee

背景 这是事后一段时间补充记录的博客。 升级目的&#xff1a;修补漏洞CVE-2024-4835 未经认证的威胁攻击者能够利用该漏洞在跨站脚本 (XSS) 攻击中&#xff0c;轻松接管受害者账户。 gitlab版本为14.6.2-ee升级至16.11.3-ee 思路 翻阅文档找升级方法及升级版本路径。使用…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...