首页 > 其他分享 >QT信号与槽使用自定义数据类型的参数引发的问题

QT信号与槽使用自定义数据类型的参数引发的问题

时间:2023-01-07 11:35:15浏览次数:47  
标签:info QVariant QT 自定义 数据类型 ProductInfoSign unsigned char

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

相关文章