Qt信号槽机制-传递自定义数据类型(qRegisterMetaType)

Qt信号槽机制-传递自定义数据类型qRegisterMetaType

  • 前言

前言

通过Qt内置的数据类型进行信号与槽参数传递很方便;如果是自己定义的类型如果想使用signal/slot来传递的话,则没有这么简单。直接使用的话,会产生下面这种错误:

QObject::connect: Cannot queue arguments of type ‘MyClass’ (Make sure ‘MyClass’ is registed using qRegisterMetaType().)
原因:当一个signal被放到队列中(queued)时,它的参数(arguments)也会被一起一起放到队列中(queued起来),这就意味着参数在被传送到slot之前需要被拷贝、存储在队列中(queue)中;为了能够在队列中存储这些参数(argument),Qt需要去construct、destruct、copy这些对象,而为了让Qt知道怎样去作这些事情,参数的类型需要使用qRegisterMetaType来注册(如错误提示中的说明)

步骤:(以自定义MyClass类型为例)

自定一种类型,在这个类型的顶部包含:#include

在类型定义完成后,加入声明:Q_DECLARE_METATYPE(MyClass);

在main()函数中注册这种类型:qRegisterMetaType(“MyClass”);

如果还希望使用这种类型的引用,可同样要注册:qRegisterMetaType(“MyClass&”);

#include      
//必须包含QMetaType,否则会出现下面错误:     
//error: expected constructor, destructor, or type conversion before ‘;’ token     
#include      
class MyClass {     
public:     
    MyClass();     
    MyClass(int, QString);     
    int count();     
    QString text();     
private:     
    int _count;     
    QString _text;     
};     
Q_DECLARE_METATYPE(MyClass); //在自定义类或者结构体等声明后紧接着用宏Q_DECLARE_METATYPE声明自定义自定义数据类型   
#endif

示例二

#ifndef MEASCOMPONENT_H
#define MEASCOMPONENT_H

#include 
#include 

class MeasComponent : public QObject
{
    Q_OBJECT
public:
    explicit MeasComponent(QObject *parent = nullptr);
    MeasComponent(const MeasComponent& obj);
signals:

public:
    QString _name; //组份名称
    QString _unit; //组份单位
    float _value; //组份实测值
    float _upperLimit; //组份上限
    float _lowLimit; //组份下限
    quint8 _status; //组份状态
};
Q_DECLARE_METATYPE(MeasComponent);
#endif // MEASCOMPONENT_H
qRegisterMetaType<MeasComponent>("MeasComponent"); //在main函数一开始的地方注册自定义类型
qRegisterMetaType<MeasComponent>("MeasComponent&"); //在main函数一开始的地方注册自定义类型
void MainWindow::on_pBtn_DeliverPara_clicked()
{
    _meas_1._name = ui->lineEdit_name->text();
    _meas_1._unit = ui->lineEdit_unit->text();
    _meas_1._value = ui->lineEdit_value->text().toFloat();
    _meas_1._status = ui->lineEdit_status->text().toUtf8().toShort();
    _meas_1._lowLimit = ui->lineEdit_lowLimit->text().toFloat();
    _meas_1._upperLimit = ui->lineEdit_upperLimit->text().toFloat();

    emit sigDeliver(_meas_1);

    if(dlg1.isHidden())
        dlg1.show();
}

一、第一种模式,直接用在信号槽中使用自定义数据类型

int main(int argc, char *argv[])     
{     
    QApplication app(argc, argv); 
    qRegisterMetaType<MyClass>("MyClass"); //在main函数一开始的地方注册自定义类型    
    qRegisterMetaType<MyClass>("MyClass&"); //在main函数一开始的地方注册自定义类型     
    
    QObject::connect(&obj1, SIGNAL(writeText(MyClass&)), &obj2, SLOT(write(MyClass&)));     
    QObject::connect(&obj1, SIGNAL(writeText(MyClass&)), &obj2, SLOT(write(MyClass&)));    

}

参考:https://blog.csdn.net/m0_37624078/article/details/82738183?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.essearch_pc_relevant&spm=1001.2101.3001.4242

二、第二种模式,通过QVariant类型中转

定义一个结构体

struct myStruct
{
  int a;
  float b;
};

通过信号槽传递该结构体

connect(this, SIGNAL(m_signal(myStruct)), this, SLOT(m_slot(myStruct)));

这样做是行不通的,正确的做法:
通过Q_DECLARE_METATYPE声明自定义的结构体

struct myStruct
{
  int a;
  float b;
};
Q_DECLARE_METATYPE(myStruct);

然后以QVariant代替自定义的结构体

connect(this, SIGNAL(m_signal(QVariant)), this, SLOT(m_slot(QVariant)));

在发射信号前,将自定义结构体打包为QVariant

myStruct mstruct;
QVariant data;
data.setValue(mstruct);
emit signal_child(data);

在槽函数中,解析QVariant

myStruct mstruct = data.value<myStruct>();

你可能感兴趣的:(Qt经验总结,Linux)