使用 QJSEngine 从 JavaScript 访问 Qt API

Posted

技术标签:

【中文标题】使用 QJSEngine 从 JavaScript 访问 Qt API【英文标题】:Accessing Qt API from JavaScript with QJSEngine 【发布时间】:2016-10-01 16:57:29 【问题描述】:

我正在使用QJSEngine 使应用程序可编写脚本。我希望 javascript 端能够修改用户界面。我现在的主要问题是从 JavaScript 访问 Qt API。

为了创建小部件,我添加了一个使用 QUILoadercreateWidget() 包装器:

// JavaScript
var w = helpers.createWidget("QPushButton");

// C++
QJSValue helpers::createWidget(QString type)

    QUILoader ld;
    return engine.newQObject(ld.createWidget(type));

我还注册了来自qt_getQtMetaObject() 的所有枚举,这似乎处理了来自qnamespace.h 的所有命名空间级枚举。不过,它看起来不像是公共 API 的一部分。

我真的应该手动处理这些东西还是我遗漏了什么?是不是有一个registerAllTheThings() 函数可以创建一个全局Qt 对象,Qt API 通过它可以使用?

如果没有,那我就有问题了。我可以用QUILoader 创建QWidgets,但我找不到创建其他对象的方法,例如QStandardItemModel。我认为所有 Qt 类都已经通过qRegisterMetaType() 注册,但它们不是:QMetaType::type("QStandardItemModel") 通过返回UnknownType 失败。再说一遍,我是否错过了一些注册所有内容的初始化函数调用?

【问题讨论】:

好吧,QStandardItemModelQStandardItem 中的成员函数都没有标记为Q_INVOKABLE,所以我什至不能调用它们。我可能只是高估了 Qt 的脚本能力。 如果您想要一个可编写脚本的应用程序,请使用 QML 而不是 QtWidgets。然后,您可以在整个 API 中原生使用 JS。您可以在核心中使用很少的 C++ 代码。用 QtWidgets 做这件事是完全突兀的。在 QML 中做这件事很容易。 QML 是在运行中“编译”的,因此使用代码生成可以在运行时创建全新的类型。 @ddriver 这实际上是我过去 4 小时一直在做的事情,但这仅适用于扩展。主要应用程序是 C++。我目前正在尝试在运行时加载 QML 文件,但我不确定它们将如何与 QtWidgets 进行交互。 你将不得不做一个loooooooot的接口...... 好吧,那些 C++ Qt 类早在 QML 之前就出现了,因此它们并非设计用于 QML 也就不足为奇了。另外,我已经说过,那是个坏主意。如果你的应用程序不是太大,移植到 QML 会更容易。 【参考方案1】:

我建议使用QQmlEngine 而不是QJSEngine

Is 是从 QJSEngine 派生的,所以它可以在同一个模块中做同样的事情,所以没有额外的依赖。

它提供了一种在 QML 中注册实例化类型的简单方法,具有插件加载机制(导入)等。

我在 2015 年 Qt 世界峰会上的演讲中介绍了这一点:https://www.youtube.com/watch?v=7LsKoVrb8C8

【讨论】:

玩了几个小时后,我的理解是 QML 是一种混合体,对于某些任务需要 C++,例如TreeView 的模型。这似乎不太适合编写扩展。我说的对吗? 基本上所有不属于 JavaScript 语言的类型在某些时候都由 C++ 代码支持。甚至 JavaScript 本身的类型也可能直接转换为 C++ 类型,但这隐藏在引擎内部。将 QML 用于 UI 时,例如使用 QtQuick、BB10 Cascades 或 DeclarativeWidgets,则模型通常直接在 C++ 中实现。但是也可以创建可以在脚本端扩展和/或填充的基本类型,例如QtQml.Model 的ListModel @KevinKrammer 我知道这是很久以前的事了,但是可以发布代码吗? @bibi 幻灯片和演示代码可从kdab.com/development-resources/kdab-qt-world-summit-2015 获得

以上是关于使用 QJSEngine 从 JavaScript 访问 Qt API的主要内容,如果未能解决你的问题,请参考以下文章

使用 QJSEngine 在 Qt 中执行 Javascript 的速度

如何从 Qt 5.12 中的 QJSEngine 获取标准输出?

如何在 QJSEngine 中注册 QList<quint64> 之类的类型?

如何使用 QJSEngine 构建 API?

如何将枚举类型注册到 QJSEngine 以从脚本环境中使用?

QJSEngine:打印到控制台