1. 发现问题
今天使用信号与槽遇到一个这样的问题,我自定义了一个信号类型:
signals: void update_product_info(int, ProductInfoSign);
ProductInfoSign的定义:
struct Version_info { unsigned char m_ver; unsigned char s_ver; unsigned char year_h; unsigned char year_l; unsigned char month; unsigned char day; }; union ProductInfoSign { unsigned int calendarinfo; Version_info versioninfo; };
自定义槽函数,在里面打印info.calendarinfo的值:
void ProductInfo::update_product_info_data(int read_mode, ProductInfoSign info) { qDebug("info.calendarinfo = %#x", info.calendarinfo); }
连接信号与槽:
connect(serialsign, SIGNAL(update_product_info(int, ProductInfoSign)), this, SLOT(update_product_info_data(int, ProductInfoSign)));
使用emit发出信号,并且在发送信号之前用qDebug打印info.calendarinfo的值,代码如下:
qDebug("info.calendarinfo = %#x", info.calendarinfo); emit update_product_info(temp, info);
这样编译没有问题,但是运行的时候却出了问题,最后两次打印的结果如下:
info.calendarinfo = 0x88776655 info.calendarinfo = 0xdb3d9b80
第一行是发送信号之前打印的,这个结果是正确的,第二行是在槽函数中打印的,这个结果是不对的,而且看上去好像两个数之间没有任何联系,并且每次软件重启之后第二个数都不一样,因此我意识到可能是QT信号与槽的机制的问题。
2. 解决问题
2.1 首先需要用Q_DECLARE_METATYPE宏声明自定义的数据类型
struct Version_info { unsigned char m_ver; unsigned char s_ver; unsigned char year_h; unsigned char year_l; unsigned char month; unsigned char day; }; union ProductInfoSign { unsigned int calendarinfo; Version_info versioninfo; }; Q_DECLARE_METATYPE(ProductInfoSign)
比如我想将ProductInfoSign类型的参数作为信号与槽的参数,那么我就在定义了ProductInfoSign之后用Q_DECLARE_METATYPE(ProductInfoSign)声明一下,不过虽然ProductInfoSign中又包含了另外一个自定义的数据类型, 另外的自定义的数据类型是不需要声明的。
2.2 自定义的参数类型要使用QVariant类型
虽然我们想传递的参数类型是ProductInfoSign,但是不能直接传递ProductInfoSign类型,而是要借助QVariant类型,最后类似于将ProductInfoSign中的内容放到了QVariant中去。好像还是不能传递自定义的类型,但是问题不大,我们关注的不是数据类型,而是数据内容。
于是信号与槽的相关部分代码改成这样:
自定义信号类型:
signals: void update_product_info(int, QVariant);
自定义槽函数:
void ProductInfo::update_product_info_data(int read_mode, QVariant dataVar);
连接信号与槽:
connect(serialsign, SIGNAL(update_product_info(int, QVariant)), this, SLOT(update_product_info_data(int, QVariant)));
2.3 对QVariant进行注册
在connect之前要调用这个函数:
qRegisterMetaType<QVariant>("QVariant");
这是因为信号和槽的参数类型并不认识QVariant。
那么问题来了,既然注册了QVariant之后信号与槽就认识QVariant了,那么直接注册自己定义的数据类型不就完了吗?比如我想要传递的数据类型是ProductInfoSign,那我直接注册ProductInfoSign不就完了吗?为什么非得用QVariant类型?事实上网上查到的资料确实有按照这个想法去弄的,但问题是我按照这个方法试了结果是不行。
2.4 发出信号时将自己的数据转变为QVariant类型
QVariant DataVar; DataVar.setValue(info); emit update_product_info(temp, DataVar);
上面代码中要先定义一个QVariant类型的数据,然后调用DataVar.setValue(info); info就是自己定义的数据,最后发出信号的时候传递的参数是QVariant类型的数据。
2.5 接收信号时将QVariant类型的数据转变为自定义的数据类型
槽函数这么写:
void ProductInfo::update_product_info_data(int read_mode, QVariant dataVar) { ProductInfoSign info = dataVar.value<ProductInfoSign>(); qDebug("info.calendarinfo = %#x", info.calendarinfo); }
这样一来发出的数据就和接收的数据一致了。
标签:info,QVariant,QT,自定义,数据类型,ProductInfoSign,unsigned,char From: https://www.cnblogs.com/Suzkfly/p/17032272.html