我想从 C++ 向 QML 公开一个枚举而不创建 QObject,但这对我不起作用。有什么想法吗?
为了进行比较,我使用包含
Q_ENUM()
和 Q_OBJECT
的 QObject 中的 QML_ELEMENT
将枚举公开给 QML。
我尝试使用包含
Q_GADGET
并使用 Q_ENUM()
的类。我还尝试使用带有 Q_NAMESPACE()
和 Q_ENUM_NS()
的命名空间。在这两种情况下,QML 都无法识别枚举。
完整的 QObject QML_ELEMENT 示例
#include <QObject>
#include <QtQml>
class MyFullQObject : public QObject {
Q_OBJECT
QML_ELEMENT
public:
using QObject::QObject;
enum MyEnum {
First,
Second,
Third
};
Q_ENUM(MyEnum)
};
Q_GADGET 示例
#include <QtQml>
class MyGadget {
Q_GADGET
public:
enum MyEnum {
First,
Second,
Third
};
Q_ENUM(MyEnum)
};
Q_NAMESPACE 示例
#include <QObject>
namespace MyNamespace {
Q_NAMESPACE
enum MyEnum {
First,
Second,
Third
};
Q_ENUM_NS(MyEnum)
}
QML 中的用法
import QtQuick
import MyModule
Item {
Component.onCompleted: {
console.log("MyFullQObject enum: " + MyFullQObject.First)
console.log("MyGadget enum: " + MyGadget.First)
console.log("MyNamespace enum: " + MyNamespace.First)
}
}
在 QML 中,第一条控制台线将起作用。第二个生成错误“ReferenceError:MyGadget 未定义”。对于第三个也是如此(如果第二个被注释掉以允许程序继续)。
在 CMake 中,类和命名空间都包含在同一个 CMake 模块中,我将生成的 MyModuleLibplugin 链接到可执行文件,这成功地使其可用于 QML
import
。
有一个简单的解决方案,仅使用宏,无需在 main.cpp 中手动注册任何内容。
通常,您可以将
QML_ELEMENT
与 Q_OBJECT
一起使用,如 MyFullQObject
中那样,使 QObject 可用于 QML。
但是,相同的宏可以与
Q_GADGET
或 Q_NAMESPACE
一起使用,这会导致它们的枚举在 QML 中可用。
--
出于好奇,虽然现在可以将以下内容放入 QML 中(没有错误,并且在 Qt Creator 中正常组件突出显示):
MyGadget { id: myGadget
Component.onCompleted: console.log('Made a MyGadget')
}
MyNamespace { id: myNamespace
Component.onCompleted: console.log('Made a MyNamespace')
}
它会生成运行时错误“元素不可创建”,如您所料。
好吧,对于只使用强制注册的我来说:
*.h:
class TestClass
{
Q_GADGET
public:
TestClass();
enum class Test
{
VALUE1,
VALUE2,
VALUE3,
};
Q_ENUM(Test)
};
main.cpp:
qmlRegisterUncreatableMetaObject(TestClass::staticMetaObject, "MyClasses", 1, 0, "TestClass", "Error: Cannot create instance");
QML:
import MyClasses 1.0
Window {
Component.onCompleted: {
console.log(TestClass.Test.VALUE3)
}
}
TestClass.VALUE3
也有效。
使用 Qt 6.4.3
进行测试