Qt元类型(MetaType)注册门(使用qRegisterMetaType注册错误等级)
昨天调试项目时,突然发现如下消息:
QObject::connect: Cannot queue arguments of type 'ERROR_LEVEL'
(Make sure 'ERROR_LEVEL' is registered using qRegisterMetaType().)
其中ERROR_LEVEL只是我定义的枚举类型即enum ERROR_LEVEL。然后在Qt的信号-槽函数的参数中使用了这个枚举型,在发送信号时就出现了上述警告。上面警告的大概意思是信号队列中无法使用ERROR_LEVEL类型,要使用qRegisterMetaType()注册该类型后方可使用。
通常使用的connect,实际上最后一个参数使用的是Qt::AutoConnection类型:
bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::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
Qt元类型(MetaType)注册门(使用qRegisterMetaType注册错误等级)的更多相关文章
- Qt元类型(MetaType)注册入门(附一些官方文档的关键摘录)
昨天调试项目时,突然发现如下消息: QObject::connect: Cannot queue arguments of type 'ERROR_LEVEL' (Make sure 'ERROR_L ...
- QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类
一般情况下信号槽直接连接方式不会出现问题,但是如果信号与槽在不同线程或Qt::QueuedConnection方式连接,可能会在连接期间报以下类似问题,如: QObject::connect: Can ...
- 解析Qt元对象系统(五) Q_INVOKABLE与invokeMethod(automatic connection从Qt4.8开始的解释已经与之前不同,发送对象驻足于哪一个线程并不重要,起到决定作用的是接收者对象所驻足的线程以及发射信号(该信号与接受者连接)的线程是不是在同一个线程)good
概述查看Qt源码可知,Q_INVOKABLE是个空宏,目的在于让moc识别. 使用Q_INVOKABLE来修饰成员函数,目的在于被修饰的成员函数能够被元对象系统所唤起. Q_INVOKABLE与QMe ...
- Qt——元对象和属性机制
http://www.cnblogs.com/hellovenus/p/5582521.html 一.元对象 元对象(meta object)意思是描述另一个对象结构的对象,比如获得一个对象有多少成员 ...
- Qt 元对象系统(Meta-Object System)(不管是否使用信号槽,都推荐使用)
Qt 元对象系统(Meta-Object System) Qt的元对象系统基于如下三件事情: 类:QObject,为所有需要利用原对象系统的对象提供了一个基类. 宏:Q_OBJECT,通常可以声明在类 ...
- CLR:基元类型、引用类型和值类型
最新更新请访问: http://denghejun.github.io 前言 今天重新看了下关于CLR基元类型的东西,觉得还是有必要将其记录下来,毕竟这是理解CLR成功 之路上的重要一步,希望你也 ...
- 《CLR via C#》读书笔记--基元类型、引用类型和值类型
编程语言的基元类型 编译器直接支持的数据类型称为基元类型.基元类型直接映射到Framework类库中存在的类型.例如:C#中的int直接映射到System.Int32类型.下表给出了C#基元类型与对应 ...
- CLR via C#(02)-基元类型、引用类型、值类型
http://www.cnblogs.com/qq0827/p/3281150.html 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架 ...
- 《CLR via C#》读书笔记(5)基元类型、引用类型和值类型
5.1 基元类型 编译器直接支持的数据类型称为基元类型(primitive type). 以下4行到吗生成完全相同的IL int a = 0; //最方便的语法 System.Int32 b = 0; ...
随机推荐
- Robot Framework初步使用
第一步,新建一个Project:
- 阅读笔记——Servlet
什么是Servlet Servlet是用java编写的运行在web服务器中的程序,因此它可以调用服务器端的类,它也可以被调用,它本身就是一个类. Servlet的工作原理 servlet由web服务器 ...
- Http协议的断点续传下载器,使用观察者模式监视下载进度,使用xml保存下载进度。
下载使用Http协议,为了做到断点续传,在点击暂停后,将已下载的大小等数据通过Json存入xml中,当继续传输的时候从xml文件中读取大小继续下载(好几个月前写的,真的想不起来了) bool CHtt ...
- 修改tomcat小猫图标,设置项目的favicon图标
修改tomcat小猫图标,设置项目的favicon图标,方式有两种:全局方式和局部方式 1.全局方式: 进入tomcat服务器\webapps\ROOT,然后用自己项目的favicon.ico替换to ...
- Apache/Tomcat/JBOSS/Nginx区别(转)
先说Apache和Tomcat的区别: Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一. ...
- JQuery的index()函数
1.index(),这里的索引从0开始计数. jQueryObject.index( [ object ] ):1.1 如果没有指定参数object,则返回当前元素在其所有同辈元素中的索引位置.1.2 ...
- document.write的注意点
如果给button点击事件添加document.write会消除页面所有元素,包括button按钮 <!DOCTYPE html> <html> <head> &l ...
- uiautomator_python使用汇总
1.判断按钮状态 if d(resourceId="id",enabled=False): #判断当前按钮是否为未激活状态,为True则为激活状态2.获取toast提示语 d.to ...
- 4、python基本知识点及字符串常用方法
查看变量内存地址 id(变量名) ni = 123 n2 = 123 ni和n2肯定是用的两份内存,但是python对于数字在-5~257之间的数字共用一份地址,范围可以修改 name = ‘李璐 ...
- WebClient 请求返回的是Gbk编码解决方案
WebClient client = new WebClient(); client.Headers.Clear(); client.Hea ...