我正在为我的软件编写脚本包装器,这样我就可以通过脚本控制我的软件。包装类的目的是将脚本接口与实际类分开,因为我可能不想公开类的所有信号和插槽。我正在使用Qt 5.13和QJSEngine。
我的问题是,根据我所阅读的内容和我的实验,似乎为了能够公开枚举,它需要在继承 QObject 并通过 newQObject((/setProperty(( 公开的类中。但是,我不想在下面的示例中公开类 Foo,但我仍然想向脚本环境公开枚举 Foo::Bar。我该怎么做?Q_ENUM似乎假设枚举在 QObject 中,并且 QObject 在脚本环境中公开(属性(。下面是我正在做的一个简短的例子(我希望能够从脚本环境中调用 FooWrapper::slot1((:
class Foo : public QObject
{
Q_OBJECT
public:
Foo(QJSEngine& engine)
{
auto wrapper = new FooWrapper(this, engine);
}
enum class Bar
{
VAL1,
VAL2
};
public slots:
void slot1(Bar bar);
void slot2();
};
class FooWrapper : public QObject
{
Q_OBJECT
public:
Foo(Foo& foo, QJSEngine& engine)
: foo(&foo)
{
QJSValue obj = engine.newQObject(this);
auto gObj = engine.globalObject();
gObj.setProperty("foo", obj);
}
public slots:
void slot1(Bar bar)
{
foo->slot1(bar);
}
private:
Foo* foo;
};
好吧,对于 OP 的 Dago(对不起!万一其他人遇到这种情况...
一个选项与一般的 QML 相同,即可以从命名空间注册枚举和标志。使用 Q_ENUM_NS()
和 Q_FLAG_NS()
(对于标志,Q_DECLARE_FLAGS()
调用保持不变,也Q_DECLARE_OPERATORS_FOR_FLAGS()
命名空间外部,与类相同,如果需要的话(。
这里有我的相关答案: 如何从 QML 访问C++枚举?
但是对于纯JSEngine
使用,只需将命名空间的QMetaObject
设置为引擎中的属性就足够了......不需要qmlRegisterUncreatableMetaObject...
的东西。
所以总结一下...
#include <QObject> // required for the macros below
namespace MyNamespace
{
Q_NAMESPACE // required for meta object creation
enum class Bar {
VAL1,
VAL2,
};
Q_ENUM_NS(Bar) // register the enum in meta object data
}
// declare the enum's meta type (required if enum will be used in
// methods/functions exposed to JS.
Q_DECLARE_METATYPE(MyNamespace::Bar)
稍后在某处的QJSEngine
初始化例程中...
QJSEngine *jse = new QJSEngine();
...
// Register the namespace's meta object as a property of the global
// object (or any other object's property for that matter).
// The property name doesn't have to match the namespace name.
jse->globalObject().setProperty(
"MyNamespace",
jse->newQMetaObject(&MyNamespace::staticMetaObject)
);
然后在 JS 环境中,枚举可用作命名空间本身的属性。
QJSValue v = jse->evaluate("MyNamespace.VAL2"); // v.toInt() == 1
或在脚本中...
console.log('>>', MyNamespace.VAL2); // output: >> 1
另一种选择可能是将枚举保留在类中,并将类的QMetaObject
注册为引擎的属性......只是不要将构造函数(或任何其他静态方法(标记为Q_INVOKABLE
。
HTH,
-Max
参考资料:
https://doc.qt.io/qt-6/qjsengine.html#newQMetaObject
https://doc.qt.io/qt-6/qobject.html#Q_NAMESPACE
https://doc.qt.io/qt-6/qobject.html#Q_ENUM_NS
我找不到对注册命名空间元对象的直接引用,正如我刚才描述的那样...... 我向你保证它可以工作(并且有很多版本(。
在本节末尾,这里模糊地引用了它。 https://doc.qt.io/qt-5/qqmlengine.html#QML_ELEMENT
另一个更不相关(但可能很有趣(:https://doc.qt.io/qt-6/qqmlengine.html#QML_EXTENDED_NAMESPACE