Qt 中的枚举 属性
Enum in Qt property
我有一个代码,适用于 Qt 5.5,不适用于 Qt 5.2。问题出在这个 enum:
#include <QtCore/QMetaType>
enum Area
{
Area_A,
Area_B,
Area_C
};
Q_DECLARE_METATYPE(Area)
然后我有一个对象,暴露了这个区域 属性:
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(Area area READ area WRITE setArea NOTIFY areaChanged)
public:
explicit MyClass(QObject *parent = 0)
: QObject(parent), m_area(Area_A){}
Area area() const { return m_area; }
void setArea(Area area) {
m_area = area;
emit areaChanged(area);
}
signals:
void areaChanged(Area area);
private:
Area m_area;
};
和main.cpp:
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlApplicationEngine>
#include <QtQml/QQmlContext>
#include <QtQml/QtQml>
#include "MyClass.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<MyClass>("GLib", 1, 0, "MyClass");
MyClass controller;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("controller", &controller);
engine.load("./main.qml");
controller.setArea(Area_B);
return app.exec();
}
编译通过,一切正常。但是当我尝试在 qml:
中使用区域 属性 时
import QtQuick 2.0
import QtQuick.Window 2.0
import GLib 1.0
Window {
visible: true
id: root
property int area: controller.area
Text {
id: name
text: "Test"
x: area * 30
y: area * 30
}
}
如果使用 Qt 5.2 (Linux, x64),我有 运行 时间错误:
QMetaProperty::read: Unable to handle unregistered datatype 'Area' for
property 'MyClass::area'
file:///home/yech844/devel/test_qml/main.qml:10:24: Unable to assign
[undefined] to int QMetaProperty::read: Unable to handle unregistered
datatype 'Area' for property 'MyClass::area'
file:///home/yech844/devel/test_qml/main.qml:10:24: Unable to assign
[undefined] to int
这是 Qt 中的错误吗?为什么我不能使用声明在 Class 范围之外的枚举?
我不知道为什么代码在 Qt 5.5 中可以工作,但我知道为什么它不能在 Qt 5.2 中工作。
Q_DECLARE_METATYPE(...)
仅使类型在 static(已编译)上下文中可用。例如,如果要使用 QVariant::fromValue(...)
中的类型。在这里,您传递给函数的类型可以在编译时处理,为此,Q_DECLARE_METATYPE
就足够了。
但是,如果您想在纯 运行时 上下文中使用类型,例如在 QML 文档中,Qt 运行时不知道用 Q_DECLARE_METATYPE
。为此,需要进行函数调用(在运行时评估),qRegisterMetatype
是实现此目的的工具:
qRegisterMetaType<Area>("Area");
我对 Qt 5.5 不需要该行的猜测是 qmlRegisterType
可能检测到 属性 中元类型的使用并自动为您调用上述函数。
Qt 5.5 引入了 Q_ENUM 宏,不再需要使用 Q_DECLARE_METATYPE。在这里阅读更多相关信息:https://woboq.com/blog/q_enum.html
我有一个代码,适用于 Qt 5.5,不适用于 Qt 5.2。问题出在这个 enum:
#include <QtCore/QMetaType>
enum Area
{
Area_A,
Area_B,
Area_C
};
Q_DECLARE_METATYPE(Area)
然后我有一个对象,暴露了这个区域 属性:
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(Area area READ area WRITE setArea NOTIFY areaChanged)
public:
explicit MyClass(QObject *parent = 0)
: QObject(parent), m_area(Area_A){}
Area area() const { return m_area; }
void setArea(Area area) {
m_area = area;
emit areaChanged(area);
}
signals:
void areaChanged(Area area);
private:
Area m_area;
};
和main.cpp:
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlApplicationEngine>
#include <QtQml/QQmlContext>
#include <QtQml/QtQml>
#include "MyClass.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<MyClass>("GLib", 1, 0, "MyClass");
MyClass controller;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("controller", &controller);
engine.load("./main.qml");
controller.setArea(Area_B);
return app.exec();
}
编译通过,一切正常。但是当我尝试在 qml:
中使用区域 属性 时import QtQuick 2.0
import QtQuick.Window 2.0
import GLib 1.0
Window {
visible: true
id: root
property int area: controller.area
Text {
id: name
text: "Test"
x: area * 30
y: area * 30
}
}
如果使用 Qt 5.2 (Linux, x64),我有 运行 时间错误:
QMetaProperty::read: Unable to handle unregistered datatype 'Area' for property 'MyClass::area' file:///home/yech844/devel/test_qml/main.qml:10:24: Unable to assign [undefined] to int QMetaProperty::read: Unable to handle unregistered datatype 'Area' for property 'MyClass::area' file:///home/yech844/devel/test_qml/main.qml:10:24: Unable to assign [undefined] to int
这是 Qt 中的错误吗?为什么我不能使用声明在 Class 范围之外的枚举?
我不知道为什么代码在 Qt 5.5 中可以工作,但我知道为什么它不能在 Qt 5.2 中工作。
Q_DECLARE_METATYPE(...)
仅使类型在 static(已编译)上下文中可用。例如,如果要使用 QVariant::fromValue(...)
中的类型。在这里,您传递给函数的类型可以在编译时处理,为此,Q_DECLARE_METATYPE
就足够了。
但是,如果您想在纯 运行时 上下文中使用类型,例如在 QML 文档中,Qt 运行时不知道用 Q_DECLARE_METATYPE
。为此,需要进行函数调用(在运行时评估),qRegisterMetatype
是实现此目的的工具:
qRegisterMetaType<Area>("Area");
我对 Qt 5.5 不需要该行的猜测是 qmlRegisterType
可能检测到 属性 中元类型的使用并自动为您调用上述函数。
Qt 5.5 引入了 Q_ENUM 宏,不再需要使用 Q_DECLARE_METATYPE。在这里阅读更多相关信息:https://woboq.com/blog/q_enum.html