首页 > 解决方案 > 当 Q_GADGET 结构位于单独的头文件中时,在 QML 中出现“未注册的数据类型”错误

问题描述

我有一个自定义struct,我将其用作派生类Q_PROPERTY中的类型。QMediaPlayer但这里的代码:

struct VideoMeta
{
    Q_GADGET

    Q_PROPERTY(int width MEMBER width)
    Q_PROPERTY(...)
    ....

public:

    int width;
    ...
};

Q_DECLARE_METATYPE(VideoMeta)

class FrameProvider : public QMediaPlayer
{
    Q_OBJECT

    Q_PROPERTY(VideoMeta videoMeta READ getVideoMeta WRITE setVideoMeta NOTIFY videoLoaded)

    VideoMeta m_videoMeta;

    ...
}

我在一个Label

Label {
    text: "Cached frames: " + cacheLoaded + " / " + frameProvider.videoMeta.framecount
}

这有点像魅力,但这里有一个转折点:如果我将声明的声明复制并粘贴struct到宏的单独头文件中(并且显然包含它)Q_DECLARE_METATYPE,我会收到以下错误:

QMetaProperty::read: Unable to handle unregistered datatype 'VideoMeta' for property 'FrameProvider::videoMeta'

所以我有两个问题:

  1. 不太重要的:为什么我需要使用Q_DECLARE_METATYPE宏,如果文档说我不需要Q_GADGET宏,因为它会自动注册类型?
  2. 更重要的是:为什么我不能将声明移到另一个头文件中?我错过了什么?

提前致谢!

编辑:

这可能是相关的:我在 Visual Studio (MSVC v142) 项目中使用 Qt v5.15。(不在 Qt Creator 中。)

标签: c++qtstructqmlqgadget

解决方案


Q_GADGET主要用途是允许非 QObject 类型进行自省。

Q_GADGET 宏是 Q_OBJECT 宏的轻量级版本,适用于不从 QObject 继承但仍希望使用 QMetaObject 提供的某些反射功能的类。就像 Q_OBJECT 宏一样,它必须出现在类定义的私有部分中。

Q_GADGET 可以有 Q_ENUM、Q_PROPERTY 和 Q_INVOKABLE,但它们不能有信号或槽。

Q_GADGET 使类成员 staticMetaObject 可用。staticMetaObject 是 QMetaObject 类型,并提供对使用 Q_ENUMS 声明的枚举的访问。

它没有说明注册类型。

也不Q_DECLARE_METATYPE注册类型,但声明它。

要注册VideoMeta,您需要致电qRegisterMetaType<VideoMeta>()。Qt 文档特别指出qRegisterMetaType<T>()必须调用类型才能在 Qt 属性系统中工作。

此外,要将类型 T 与 QObject::property() API 一起使用,必须在使用之前调用 qRegisterMetaType(),通常在使用 T 的类的构造函数中或在 main() 函数中。

https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1


推荐阅读