Qt注册元类型(MetaType)

程序调试时出现:

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

其中FunctionDataClass只是我定义的一个类,在发送信号时就出现了上述警告。上面警告的大概意思是信号队列中无法使用FunctionDataClass类型,要使用qRegisterMetaType()注册该类型后方可使用。

      通常使用的connect,实际上最后一个参数使用的是Qt::AutoConnection类型:

bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * methodQt::ConnectionType type = Qt::AutoConnection )

Qt支持6种连接方式,其中3中最主要:

  • Qt::DirectConnection(直连方式)

      当信号发出后,相应的槽函数将立即被调用。emit语句后的代码将在所有槽函数执行完毕后被执行。(信号与槽函数关系类似于函数调用,同步执行

  • Qt::QueuedConnection(排队方式)

      当信号发出后,排队到信号队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕。(此时信号被塞到信号队列里了,信号与槽函数关系类似于消息通信,异步执行

  • Qt::AutoConnection(自动方式)

      Qt的默认连接方式,如果信号的发出和接收这个信号的对象同属一个线程,那个工作方式与直连方式相同;否则工作方式与排队方式相同。

      我的项目中的确跨线程使用了ERROR_LEVEL为参数类型的信号,因此使用的应当是排队方式的信号-槽机制,出现“队列中无法使用ERROR_LEVEL类型”的警告信息就可以理解了。放狗搜了一圈,有篇文章提供了个这样的解决方案:

connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)), 
            this,SLOT(sendRes(QUuid,QByteArray,bool))); 
改为: 
connect(cm, SIGNAL(sendLog(QUuid, QByteArray, bool)), 
            this,SLOT(sendRes(QUuid,QByteArray,bool)), Qt::DirectConnection);

这样做的确能使警告信息消失,因为Qt官方文档写了:

With queued connections, the parameters must be of types that are known to Qt's meta-object system, because Qt needs to copy the arguments to store them in an event behind the scenes.

即使用排队方式的信号-槽机制,Qt的元对象系统(meta-object system)必须知道信号传递的参数类型。这里手动改为直连方式,Qt的元对象系统就不必知道参数类型了,于是警告信息消失。但这样做是不安全的,见Qt官方文档:

Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.

      因此,咱还是老老实实地用qRegisterMetaType()注册类型吧,见代码:

头文件

/*! \file errorlevel.h*/
#ifndef ERRORLEVEL_H
#define ERRORLEVEL_H
/*! \enum ERROR_LEVEL
 * 错误等级的定义。通常用来在传递错误消息时标记错误的等级。
 */
enum ERROR_LEVEL
{
    NORMAL,  /*!< 普通错误,通常不需要处理,可以记录或者显示错误消息。*/
    CRITICAL /*!< 严重错误,需要紧急处理,如果没有妥善处理,可能导致后续操作失败。*/
};
#endif // ERRORLEVEL_H

cpp文件

/*! \file errorlevel.cpp*/
#include "errorlevel.h"
/*! 模板函数显式实例化,注册ERROR_LEVEL到元对象系统。这样才可以在信号-槽
 * 队列里使用ERROR_LEVEL类型参数。
 */
int i = qRegisterMetaType<ERROR_LEVEL>("ERROR_LEVEL");

参见http://www.cnblogs.com/codingmylife/archive/2010/04/30/1725139.html


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值