Qt:我什么时候应该使用Q_DECLARE_METATYPE?

时间:2016-10-10 12:26:06

标签: c++ qt

文档说我需要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才能使用信号槽?

3 个答案:

答案 0 :(得分:4)

  

何时使用Q_DECLARE_METATYPE?

当该类型与信号/广告位或QVariant 一起使用时,始终使用。

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

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

答案 1 :(得分:2)

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

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

请注意,此宏要求在使用它的位置完全定义类型;对于指针类型,指针也必须完全定义,因此理想情况下,您应该在类声明之后放置宏(再一次,如果要将类型对象存储在QVariant中,则只需要它)。

答案 2 :(得分:2)

根据我的经验,要在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注册属性(尽管没有通知信号)。

正如@SingerOfTheFall所指出的,

Q_DECLARE_METATYPE会将基于模板的类型注册到QVariant中(因此可以使用qvariant_cast<T>()检索它。)

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