文章目录
- Qt Script
-
- 什么是ECMAScript
- Qt 中JavaScript
- class 详解
- Basic Usage
-
- QObject对脚本引擎可用
- 使用信号槽
- connect 三种模式
- 访问属性, 子对象
- 使c++对象可用于用Qt Script编写的脚本
-
- C++ 类成员函数可用于脚本
- C++ 类属性可用于脚本
- 对脚本中的c++对象信号的反应
- 函数对象和本机函数
-
- 从c++调用Qt脚本函数
- this object
- 包装本机函数
- 形式形参和参数对象
- 访问参数对象
- 构造函数
- 将数据与函数关联
- 原生函数作为函数的参数
- 总结
Qt Script
Qt为使用ECMAScript编写应用程序脚本提供了支持. ,可用于实现 C++应用程序和JavaScript代码之间的相互调用
还需要注意的是:
:此模块尚未积极开发。它只提供了与Qt 4的向后兼容性。对于新代码,请使用QJSEngine和Qt QML模块中的相关类。
Qt Script在Qt公司的商业许可下可用。此外,它在自由软件许可下可用。从Qt 5.4开始,这些自由软件许可证是GNU Lesser General Public License, version 3,或GNU General Public License, version 2。
此外,Qt 5.15.17中的Qt Script在以下许可许可下包含第三方模块:
JavaScriptCore, version Snapshot from 2011-01-27 GNU Library General Public License v2 or later
什么是ECMAScript
ECMAScript 是一个语言规范(Language Specification),可以理解为一种脚本语言规范。目前这个语言规范由Ecma International 这个组织在维护 。
而JavaScript 是ECMAScript 这种语言规范的一种具体实现。当前存在几种JavaScript实现,比如Apple的JavaScriptCore,Google的[v8] (https://v8.dev/)这两种是比较有名气的。
Qt 中JavaScript
QT框架中推荐使用的JavaScript引擎是JavaScriptCore,QML模块使用的JavaScript引擎就是这个版本。
class 详解
项目 | Value |
---|---|
QScriptClass | 用于定义(一类)Qt脚本对象的自定义行为的接口 |
QScriptClassPropertyIterator | 自定义Qt脚本对象的迭代器接口 |
QScriptContext | 表示一个Qt脚本函数调用 |
QScriptContextInfo | 关于QScriptContext的附加信息 |
QScriptEngine | 评估或者说是执行Qt脚本代码环境 |
QScriptEngineAgent | 用于报告与QScriptEngine执行有关的事件接口 |
QScriptEngineDebugger | QScriptEngine debugger |
QScriptProgram | 封装一个Qt脚本程序 |
QScriptString | 在qscriptenengine中充当“内部”字符串的句柄 |
QScriptSyntaxCheckResult | 脚本语法检查的结果 |
QScriptValue | 作为Qt脚本数据类型的容器 |
QScriptValueIterator | QScriptValue的java风格迭代器 |
QScriptable | 从Qt c++成员函数访问Qt Script环境中 |
Basic Usage
要计算脚本代码,需要创建一个QScriptEngine并调用它的evaluate()函数,将脚本代码作为参数传递给evaluate。
QScriptEngine engine;
qInfo() << "the magic number is:" << engine.evaluate("1 + 2").toNumber();
通过在脚本引擎中注册自定义属性,可以使脚本可用。这是通过设置脚本引擎的全局对象的属性最容易做到的:
engine.globalObject().setProperty("foo", 123);
qDebug() << "foo times two is:" << engine.evaluate("foo * 2").toNumber();
QObject对脚本引擎可用
- 任何基于qobject的实例都可以与脚本一起使用。
- 当一个QObject被传递给QScriptEngine::newQObject()函数时,一个Qt Script包装器对象被创建,它可以用来使QObject的信号、槽、属性和子对象对脚本可用。
QScriptEngine engine;
QObject *someObject = new MyObject; //inherited from QObject
QScriptValue objectValue = engine.newQObject(someObject);
engine.globalObject().setProperty("myObject", objectValue);
这将在脚本环境中创建一个名为myObject的全局变量。变量充当底层c++对象的代理。
注意,脚本变量的名字可以是任何东西;也就是说,它不依赖于QObject::objectName()。
newQObject()函数接受两个额外的可选参数:一个是所有权模式,另一个是一个选项集合,它允许您控制包装QObject的QScriptValue应该如何表现的某些方面。
使用信号槽
-
Hybrid C++/script:
c++应用程序代码将信号连接到脚本函数。例如,脚本函数可以是用户输入的函数,也可以是从文件中读取的函数。如果你有一个QObject,但不想将对象本身暴露给脚本环境,这种方法很有用;您只是希望脚本能够定义应该如何响应信号,并将其留给应用程序的c++端来建立连接。 -
Hybrid script/C++
脚本可以连接信号和插槽,以在应用程序向脚本环境公开的预定义对象之间建立连接。在这个场景中,插槽本身仍然是用c++编写的,但是连接的定义是完全动态的(脚本定义的)。 -
Purely script-defined
一个脚本既可以定义信号处理函数(有效地“插槽写在Qt脚本”),并建立利用这些处理程序的连接。例如,脚本可以定义一个函数来处理QLineEdit::returnPressed()信号,然后将该信号连接到脚本函数。
使用qScriptConnect()函数将c++信号连接到脚本函数。
QScriptEngine eng;
QLineEdit *edit = new QLineEdit(...);
QScriptValue handler = eng.evaluate("(function(text) { print('text was changed to', text); })");
qScriptConnect(edit, SIGNAL(textChanged(const QString &)), QScriptValue(), handler);
//qScriptConnect()的前两个参数与传递给QObject::connect()以建立普通c++连接的参数相同。
//第三个参数是脚本对象,它将在调用信号处理程序时充当this对象;在上面的例子中,我们传递了一个无效的脚本值,所以这个对象将是全局对象。
//第四个参数是脚本函数(“slot”)本身
QLineEdit *edit1 = new QLineEdit(...);
QLineEdit *edit2 = new QLineEdit(...);
QScriptValue handler = eng.evaluate("(function() { print('I am', this.name); })");
QScriptValue obj1 = eng.newObject();
obj1.setProperty("name", "the walrus");
QScriptValue obj2 = eng.newObject();
obj2.setProperty("name", "Sam");
qScriptConnect(edit1, SIGNAL(returnPressed()), obj1, handler);
qScriptConnect(edit2, SIGNAL(returnPressed()), obj2, handler);
//我们创建了两个QLineEdit对象,并定义了一个信号处理函数。连接使用相同的处理程序函数,但是根据触发哪个对象的信号,将使用不同的this对象调用该函数,因此print()语句的输出对于每个连接都是不同的。
//在脚本代码中,Qt脚本使用与熟悉的c++语法不同的语法来连接和断开信号;也就是说,QObject:: connect()。要连接到信号,需要将相关信号作为发送方对象的属性引用,并调用其connect()函数。
connect 三种模式
- connect(function)
function myInterestingScriptFunction() {
// ...
}
// ...
myQObject.somethingChanged.connect(myInterestingScriptFunction);
// myQObject.somethingChanged.connect(myOtherQObject.doSomething);
//对应disconnect
myQObject.somethingChanged.disconnect(myInterestingFunction);
myQObject.somethingChanged.disconnect(myOtherQObject.doSomething);
- connect(thisObject, function)
var obj = {
x: 123 };
var fun = function()