Получение ошибки незарегистрированного типа данных в QML, когда структура Q_GADGET находится в отдельном файле заголовка - PullRequest
0 голосов
/ 18 июня 2020

У меня есть собственный 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. Важнее: почему я не могу переместить объявление в другой файл заголовка? Что мне не хватает?

Заранее спасибо!

EDIT:

Это может быть актуально: я использую Qt v5.15 в Visual Studio (MSV C v142) проект. (Нет в Qt Creator.)

1 Ответ

0 голосов
/ 19 июня 2020

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

...