c++ 如何将不属于QObject的枚举暴露给QJSEngine?

wljmcqd8  于 2022-12-15  发布在  其他
关注(0)|答案(1)|浏览(174)

我正在为我的软件编写脚本 Package 器,这样我就可以通过脚本控制我的软件。 Package 器类的目的是将脚本接口与实际类分开,因为我可能不想暴露类的所有信号和插槽。我使用Qt 5.13和QJSEngine。
我的问题是,基于我所读到的和我所做的,似乎要能够暴露一个枚举,它需要在一个继承QObject的类中,并通过newQObject()/setProperty()暴露。然而,我不想在下面的例子中暴露类Foo,但我仍然想向脚本环境暴露枚举Foo::Bar。我该怎么做呢?Q_ENUM似乎假设枚举在一个QObject中,QObject在脚本环境中暴露(属性)。下面是一个简短的例子(我想能够从脚本环境调用FooWrapper::slot 1()):

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;
};
hgncfbus

hgncfbus1#

好吧,这对达戈来说显然已经很晚了,OP(抱歉!)。万一还有人碰到这个...
其中一个选项与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

嘿,

  • 麦克斯
    参考文献:
    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
    我 * 不能 * 找到一个直接引用注册名称空间 meta对象,就像我刚刚描述的那样...我向你保证它是有效的(并且已经在相当多的版本中)。
    在这一节的结尾,有一个模糊的参考。https://doc.qt.io/qt-5/qqmlengine.html#QML_ELEMENT
    另一个甚至不太相关(但可能有趣):https://doc.qt.io/qt-6/qqmlengine.html#QML_EXTENDED_NAMESPACE

相关问题