Получение ошибки незарегистрированного типа данных в QML, когда структура Q_GADGET находится в отдельном файле заголовка
У меня есть обычай 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'
Итак, у меня есть два вопроса:
- Менее важно: зачем мне использовать
Q_DECLARE_METATYPE
макрос, если в документации написано, что он мне не нужен сQ_GADGET
макрос, потому что он автоматически регистрирует тип? - Более важно: почему я не могу переместить объявление в другой файл заголовка? Что мне не хватает?
Заранее спасибо!
РЕДАКТИРОВАТЬ:
Это может быть актуально: я использую Qt v5.15 в проекте Visual Studio (MSVC v142). (Нет в Qt Creator.)
1 ответ
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 с API QObject::property(), перед его использованием необходимо вызвать qRegisterMetaType(), обычно в конструкторе класса, использующего T, или в функции main ().