首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用QJSEngine构建应用程序接口?

如何使用QJSEngine构建应用程序接口?
EN

Stack Overflow用户
提问于 2013-10-04 08:11:18
回答 4查看 4.5K关注 0票数 3

我从Qt开始,我的一个项目是使用QJSEngine来评估javascript,我想为脚本提供完整的API,包括类和全局函数。

现在,我的程序只提供了ECMAScript默认内容(eval、encodeURI、parseInt等),但我需要向代码公开一些自定义类,比如浏览器API (WebSocket类、图像类、文档对象)。例如:

代码语言:javascript
复制
var obj = new CustomClass("", 0);
var ret = obj.customClassMethod("[...]!");
customFunction(ret);

我需要在C++中定义类的行为,这无助于评估类的定义并让用户代码运行。

EN

回答 4

Stack Overflow用户

发布于 2016-06-02 02:11:21

QScriptEngine不同的是,您可以使用Q_SCRIPT_DECLARE_QMETAOBJECT宏来添加从QObject继承的自定义类,而QJSEngine不直接提供此功能。

您仍然可以使用Qt元对象系统为Javascript提供接口,但您必须在C++中实例化该对象并将其添加到Javascript上下文中。然后,它的插槽、用Q_INVOKABLE定义的方法和用Q_PROPERTY定义的属性都可以从Javascript运行时中访问。

现在,您可以创建一个工厂,它为包装为Javascript对象的给定QJSEngine创建自定义类CustomClass的实例:

代码语言:javascript
复制
class CustomClassFactory : public QObject
{
    Q_OBJECT
public:
  CustomClassFactory(QJSEngine* engine) : m_engine(engine) {}
  Q_INVOKABLE QJSValue createInstance() {
      // The engine takes ownership and destroys the object if no longer required.
      return m_engine->newQObject(new CustomClass());
  }
private:
    QJSEngine* m_engine;
}

需要构造工厂实例并将其添加到Javascript运行时的全局对象中:

代码语言:javascript
复制
QJSEngine engine;
QJSValue factoryObj = engine.newQObject(new CustomClassFactory());
engine.globalObject().setProperty("_customClassFactory", factoryObj);

现在我们可以在Javascript中使用以下命令构造对象:

代码语言:javascript
复制
var obj = _customClassFactory.createInstance()

到目前为止,让我们另外将自定义类的构造函数注入到Javascript运行时中:

代码语言:javascript
复制
QJSEngine engine;
// Again, the QJSEngine will take ownership of the created object.
QJSValue factoryObj = engine.newQObject(new CustomClassFactory());
engine.globalObject().setProperty("_customClassFactory", factoryObj);
engine.evaluate(
    "function CustomClass() {"
    "    return _customClassFactory.createInstance()"
    "}");

好了,现在你可以在Javascript中构造C++对象,就像你定制Javascript类一样:

代码语言:javascript
复制
var obj = new CustomClass()

对于前面提到的WebSocket应用程序接口,您可以为此目的包装QtWebSocket,- that正是我在提出建议方法时所需要的。

请注意,为了简单起见,我省略了构造函数的参数,但也可以简单地添加它们。

注:我会在官方文档中添加更多的链接,但由于缺乏声誉,我不被允许这样做。

票数 9
EN

Stack Overflow用户

发布于 2020-05-07 22:09:57

在Qt 5.8中,QJSEngine添加了一个新功能:newQMetaObject

您只需使用上面的函数将静态元对象(例如&MyQObjectDerivedClass::staticMetaObject )添加到JSEngine。

然后,您将能够从QML中在Javascript中new这些对象。我发现这是一个非常好的解决方案。

正如文档所说,您必须将构造函数标记为Q_INVOKABLE,否则将无法实例化您的类的对象。

属性系统(setters/getters)和插槽一样正常工作。

https://doc.qt.io/qt-5/qjsengine.html#newQMetaObject

下面是我的测试代码--首先是添加元对象的C++部分

代码语言:javascript
复制
QQmlApplicationEngine engine;
QJSValue jsMetaObject = engine.newQMetaObject(&MyClassOfObject::staticMetaObject);
engine.globalObject().setProperty("MyClassOfObject", jsMetaObject);

我现在可以编写JS来设置该类型的对象并使用news /getter等。这段代码实际上存在于用于手动测试的MouseArea onClicked处理程序中。

代码语言:javascript
复制
var bob = new MyClassOfObject();
print(bob.x);
bob.x = 918264;
print(bob.x);
print(bob.words);

这是类的定义..。

代码语言:javascript
复制
class MyClassOfObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int x READ getX WRITE setX)
    Q_PROPERTY(int y READ getY WRITE setX)
    Q_PROPERTY(QStringList words READ getWords)    
public:
    Q_INVOKABLE explicit MyClassOfObject(QObject *parent = nullptr);
public slots:
    int getX() const { return x; }
    int getY() const { return y; }
    void setX(int x) { this->x = x; }
    void setY(int y) { this->y = y; }
    QStringList getWords() const;
private:
    int x = -113;
    int y = 616;
    QStringList stringList;
};
票数 3
EN

Stack Overflow用户

发布于 2019-08-24 05:32:55

从Qt5.5开始,QScriptEngine已经被弃用,所以未来应该只使用QJsEnginehttps://wiki.qt.io/New_Features_in_Qt_5.5#Deprecated_Functionality

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19171139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档