[C++Qt] 槽函数收不到信号问题(信号的注册)

  • 📢博客主页:https://loewen.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨

文章预览:

      • 一. 需要注册信号参数的情况
      • 二. 不注册可能引发的问题
      • 三. 如何注册自定义类型
      • 四. 示例:跨线程信号槽的正确用法
      • 五. 为什么“仅用 qRegisterMetaType 也能工作”?


一. 需要注册信号参数的情况

1、跨线程的信号槽连接(使用 QueuedConnection)

当信号和槽位于不同线程,且连接方式为 Qt::QueuedConnectionQt::BlockingQueuedConnection 时,参数类型必须注册

原因:跨线程通信时,Qt 需要将参数序列化到接收线程的事件队列中,这要求类型必须能被 Qt 的元对象系统识别。

2、使用 QVariant 传递自定义类型

如果信号参数是自定义类型,且需要与 QVariant 结合使用,必须注册类型。


二. 不注册可能引发的问题

1、运行时警告或错误

如果未注册自定义类型,Qt 会在运行时输出类似以下警告:

QObject::connect: Cannot queue arguments of type 'MyCustomType'
(Make sure 'MyCustomType' is registered using qRegisterMetaType().)

后果:跨线程的信号槽调用会失败,槽函数不会执行,程序可能无响应或崩溃。

2、参数无法正确传递

未注册的类型无法被 Qt 序列化/反序列化,导致槽函数接收到的参数是无效或未初始化的值。

3、无法与 QVariant 交互

自定义类型无法通过 QVariant 存储或传递,导致相关功能(如属性系统、模型/视图)失效。


三. 如何注册自定义类型

1、使用 Q_DECLARE_METATYPE 宏

#include <QMetaType>// 自定义类型定义
struct MyCustomType {int id;QString name;
};// 声明元类型支持(放在头文件末尾)
Q_DECLARE_METATYPE(MyCustomType)

Q_DECLARE_METATYPE 的作用

1)编译时元信息生成

Q_DECLARE_METATYPE 宏会为类型生成编译时的元信息(如类型名称、大小、对齐方式等),使得以下功能可用:

  • QVariant 的构造和类型转换(例如 QVariant::fromValue 和 QVariant::value)。
  • 类型在模板和宏中的静态识别(例如 QMetaType 的静态接口)。

2)隐式要求

如果未使用 Q_DECLARE_METATYPE,即使通过 qRegisterMetaType 注册了类型,以下操作可能失败:

MyCustomType data;
QVariant variant = QVariant::fromValue(data); // 编译错误!

2、使用 qRegisterMetaType 注册类型

在程序启动时(如 main 函数、构造函数等中)注册类型:

#include <QMetaType>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 注册自定义类型qRegisterMetaType<MyCustomType>("MyCustomType");// 如果类型有默认构造函数,可以简写为:qRegisterMetaType<MyCustomType>();return app.exec();
}

四. 示例:跨线程信号槽的正确用法

// 自定义类型
struct MyCustomType {int id;QString name;
};
Q_DECLARE_METATYPE(MyCustomType)// 发送者类
class Sender : public QObject {Q_OBJECT
public:void sendData() {MyCustomType data{1, "Test"};emit signalData(data); // 发送信号}
signals:void signalData(const MyCustomType& data);
};// 接收者类
class Receiver : public QObject {Q_OBJECT
public slots:void onDataReceived(const MyCustomType& data) {qDebug() << "Received:" << data.id << data.name;}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);qRegisterMetaType<MyCustomType>(); // 注册类型Sender sender;Receiver receiver;QThread thread;// 跨线程连接QObject::connect(&sender, &Sender::signalData,&receiver, &Receiver::onDataReceived,Qt::QueuedConnection);//将接受者移至线程中,这样与发送者即分属于不同的线程中receiver.moveToThread(&thread);thread.start();sender.sendData();return app.exec();
}

五. 为什么“仅用 qRegisterMetaType 也能工作”?

场景 1:跨线程信号槽通信

  • 如果仅在跨线程信号槽中使用自定义类型,且未直接操作 QVariant,程序可能正常执行。
  • 原因
    qRegisterMetaType 在运行时注册了类型,使得 Qt 能正确序列化参数。
    Q_DECLARE_METATYPE 的缺失在此场景下可能不会立即暴露问题。

场景 2:低版本 Qt 的宽松处理

  • 某些旧版 Qt(如 Qt4)对类型注册的要求较为宽松,可能允许未声明 Q_DECLARE_METATYPE。
  • 风险:
    这种行为是未定义的,可能因 Qt 版本或平台不同而失效。

下雨天,最惬意的事莫过于躺在床上静静听雨,雨中入眠,连梦里也长出青苔。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/897889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零开始用AI开发游戏(一)

1. 核心玩法设计 核心目标&#xff1a;玩家需在随机生成的3D迷宫中寻找出口&#xff0c;躲避陷阱、收集道具、解开谜题。核心机制&#xff1a; 随机生成迷宫&#xff1a;每次游戏生成不同结构的迷宫&#xff08;递归分割算法或深度优先搜索&#xff09;。第一人称视角&#xf…

基于ssm的宠物医院信息管理系统(全套)

一、系统架构 前端&#xff1a;html | layui | vue | element-ui 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.8 | mysql | maven | tomcat | idea | nodejs 二、代码及数据库 三、功能介绍 01. web端-首页1 02. web端-首页…

【CXX】6.7 SharedPtr<T> — std::shared_ptr<T>

std::shared_ptr 的 Rust 绑定称为 SharedPtr。 限制&#xff1a; SharedPtr 不支持 T 为不透明的 Rust 类型。对于在语言边界上传递不透明 Rust 类型的所有权&#xff0c;应改用 Box&#xff08;C 中的 rust::Box&#xff09;。 示例 // src/main.rsuse std::ops::Deref; …

利用python生成excel中模板范围对应的shape文件

利用python生成excel中模板范围对应的shape文件 # -*- coding: utf-8 -*- import os.pathimport pandas as pd from shapely.geometry import Polygon from shapely.wkt import dumps import argparse# 创建解析器 parser argparse.ArgumentParser(description"这是一个…

cursor使用

引入私有文档 设置-> Features->下滑找到Docs url后边多加一个 / 可以拉取url下所有的页面(子页面&#xff0c;子目录)&#xff0c;不加只拉取url当前页面 使用 选择 Docs 回车 选择 文档 直接解析链接 链接 回车 搜索引擎 web 对比git版本差异 git 选择其中一个 g…

达梦数据库中插入导出图片的方法与应用

达梦数据库中插入导出图片的方法与应用 在数据库的实际应用场景中&#xff0c;图片存储是一项常见且重要的需求。以电商平台为例&#xff0c;商品展示图片是吸引消费者的关键元素&#xff1b;而在社交软件里&#xff0c;用户头像更是个人形象的直观体现。针对达梦数据库&#…

【云原生】动态资源分配(DRA)深度洞察报告

1. DRA 的发展与设计灵感 Kubernetes 早期通过 Device Plugin&#xff08;设备插件&#xff09;机制支持 GPU、NIC 等特殊硬件&#xff0c;将节点上可用设备数量上报给 kubelet 和调度器。但设备插件模式存在局限&#xff1a;调度器只能根据节点标签等属性粗粒度筛选&#xff…

嵌入式八股ARM篇

前言 ARM篇主要介绍一下寄存器和中断机制,至于汇编这一块…还请大家感兴趣自行学习 1.寄存器 R0 - R3 R4 - R11 寄存器 R0 - R3一般用作函数传参 R4 - R11用来保存程序运算的中间结果或函数的局部变量 在函数调用过程中 注意在发生异常的时候 cortex-M0架构会自动将R0-R3压入…

Python 实现的采集诸葛灵签

Python 实现的采集诸葛灵签 项目介绍 这是一个基于 Python 开发的诸葛灵签数据采集和展示项目。通过爬虫技术获取诸葛神签的签文和解签内容&#xff0c;并提供数据存储和查询功能。 项目结构 zhuge/├── zhuge_scraper.py # 爬虫主程序├── zhuge_pages/ # 数据存储目录…

【C++项目实战】校园公告搜索引擎:完整实现与优化指南

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长&#xff0c;行则将至 目录 &#x1f4da;一、项目概述 &#x1f4d6;1.项目背景 &#x1f4d6;2.主要功能 &#x1f4d6;3.界面展…

代理(Delegate)、闭包(Closure)、Notification(通知中心) 和 swift_event_bus适用场景和工作方式

在 Swift 开发中&#xff0c;在 Swift 开发中&#xff0c;代理&#xff08;Delegate&#xff09;、闭包&#xff08;Closure&#xff09;、Notification&#xff08;通知中心&#xff09; 和 swift_event_bus 主要用于 组件之间的通信&#xff0c;但它们的适用场景和工作方式有…

设计模式--单例模式(Singleton)【Go】

引言 在设计模式中&#xff0c;单例模式&#xff08;Singleton Pattern&#xff09;是一种非常常见且实用的模式。它的核心思想是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。这种模式在需要全局唯一对象的场景中非常有用&#xff0c;比如配置管理、日志记录、数…

MySQL数据库复制

文章目录 MySQL数据库复制一、复制的原理二、复制的搭建1.编辑配置文件2.在主库上创建复制的用户3.获取主库的备份4.基于从库的恢复5.建立主从复制6.开启主从复制7.查看主从复制状态 MySQL数据库复制 MySQL作为非常流行的数据库&#xff0c;支撑它如此出彩的因素主要有两个&am…

Sourcetree——使用.gitignore忽略文件或者文件夹

一、为何需要文件忽略机制&#xff1f; 1.1 为什么要会略&#xff1f; 对于开发者而言&#xff0c;明智地选择忽略某些文件类型&#xff0c;能带来三大核心优势&#xff1a; 仓库纯净性&#xff1a;避免二进制文件、编译产物等污染代码库 安全防护&#xff1a;防止敏感信息&…

基于yolov8+streamlit实现目标检测系统带漂亮登录界面

【项目介绍】 基于YOLOv8和Streamlit实现的目标检测系统&#xff0c;结合了YOLOv8先进的目标检测能力与Streamlit快速构建交互式Web应用的优势&#xff0c;为用户提供了一个功能强大且操作简便的目标检测平台。该系统不仅具备高精度的目标检测功能&#xff0c;还拥有一个漂亮且…

分享vue好用的pdf 工具实测

vue3-pdf-app&#xff1a; 带大纲&#xff0c;带分页&#xff0c;带缩放&#xff0c;带全屏&#xff0c;带打印&#xff0c;带下载&#xff0c;带旋转 下载依赖&#xff1a; yarn add vue3-pdf-appornpm install vue3-pdf-app 配置类&#xff1a; 创建文件 pdfConfig.ts /…

基于微信小程序开发的宠物领养平台——代码解读

项目前端 一、项目的技术架构概况 一句话概括&#xff1a;该项目是基于微信小程序开发的宠物领养平台&#xff0c;采用原生小程序框架进行用户界面的构建&#xff0c;使用 wx.request 进行 API 请求&#xff0c;并通过 getApp() 和本地存储来管理全局状态和用户信息。 一&am…

最完美的WPF无边框设计!

常规的无边框方法设计 常规的WPF无边框设计方法都是通过AllowsTransparency="True"和WindowStyle=“None”,并且使用WindowChrome样式来实现,但是这样会有问题就是,窗体最大化的时候将底部任务栏给挡住了,另外最大化的时候不能拖动窗体。参考这个大佬的设计@ 若…

【区块链】btc

学习视频源链接&#xff1a; https://www.bilibili.com/video/BV1Vt411X7JF/ 本文是根据肖老师的视频进行的笔记记录 一、 cryptographic hash function 1.1. collision resistance抗碰撞性 &#xff1a; collision 指的是hash碰撞 抗碰撞性 (Collision Resistance) 是密码…

C语言【数据结构】:时间复杂度和空间复杂度.详解

引言 详细介绍什么是时间复杂度和空间复杂度。 前言&#xff1a;为什么要学习时间复杂度和空间复杂度 算法在编写成可执行程序后&#xff0c;运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏&#xff0c;一般是从时间和空间两个维度来衡量的&#xff0c;即时…