Qt:我什么时候使用Q_DECLARE_METATYPE ?

Qt: When shall I use Q_DECLARE_METATYPE?

本文关键字:DECLARE METATYPE 什么时候 Qt      更新时间:2023-10-16

文档说我需要Q_DECLARE_METATYPE一个自定义结构,这样它就可以在信号槽中正常工作。

但是我已经尝试了下面的代码,似乎工作得很好?

#include <QMainWindow>
namespace Ui {
class MainWindow;
}
struct MyStruct
{
        int a;
        int b;
};
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
signals:
    void test(MyStruct);
public slots:
    void tested(MyStruct);
private slots:
    void on_pushButton_clicked();
};
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
//------------------------CPP-------------------------------
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(this, SIGNAL(test(MyStruct)),this,SLOT(tested(MyStruct)));
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::tested(MyStruct t)
{
    qDebug()<<t.a<<t.b;
}
void MainWindow::on_pushButton_clicked()
{
    MyStruct t;
    t.a=1;
    t.b=2;
    emit test(t);
}

信号槽正常工作,但在以下情况下:

struct SoundType 
{
    enum Type
    {
        Bip = 0,
        LowBatt, 
        LowSat,
        FarAway,
        LostLink
    };
};
Q_DECLARE_METATYPE(SoundType::Type)

似乎我必须调用声明才能使用

SoundType:类型

在信号槽。

那么在什么情况下我必须使用Q_DECLARE_METATYPE才能使用信号槽?

何时使用Q_DECLARE_METATYPE?

当该类型用于信号/槽位或QVariant 时总是

您的测试用例是不完整的:一旦您将其中一个连接的对象移动到另一个线程,它就会中断。

您可能还需要qRegisterMetatype<YourType>(),例如在main

与信号和插槽没有任何关系。当您希望能够在QVariant

中存储自己的类型时,需要使用Q_DECLARE_METATYPE

注意,这个宏要求类型在使用时被完全定义;对于指针类型,指针也必须是完全定义的,所以理想情况下,您应该将宏放在类声明之后(同样,只有当您想将类型对象存储在QVariant中时才需要它)。

根据我的经验,要在Qt元对象系统中注册自定义枚举,您需要在其范围内使用Q_ENUM标记枚举,例如:

struct SoundType 
{
    enum Type
    {
        Bip = 0,
        LowBatt, 
        LowSat,
        FarAway,
        LostLink
    };
    Q_ENUM(Type);
};
例如,这将使我们能够在QML中使用枚举(尽管父类型必须首先在QML中注册)。在许多情况下,包括Qt本身(例如QAbstractItemModel::data(..., int role)),使用普通的int会更方便。

还有其他的宏。一般来说,不从QObject派生的自定义结构可以通过在结构的开头键入Q_GADGET来注册(就像Q_OBJECT宏一样)。请注意,这样的结构不能有信号或槽,但它可以像往常一样使用Q_PROPERTY注册属性(尽管没有通知信号)。

Q_DECLARE_METATYPE,正如@SingerOfTheFall指出的那样,将基于模板的类型注册到QVariant(因此可以使用qvariant_cast<T>()检索)。

一些结构需要注册,以便在使用qRegisterMetaType<T>(name)的异步信号中排队,例如通过QVector<int>的信号