找了半天关于QtScript的中文文档很少,只能查看英文文档,顺便翻译一下。
Qt对基于ECMAScript的脚本提供了支持,下面的指导和参考涵盖了ECMAScript和Qt的各个方面。
脚本类
下面的类将脚本的功能添加到Qt应用程序当中。
QScriptClass 用于定义自定义的Qt脚本对象的接口
QScriptClassPropertyIterator 用于遍历自定义脚本对象的接口
QScriptContext 一个Qt脚本函数的调用上下文
QScriptContextInfo 关于QScriptContext的额外信息
QScriptEngine 执行Qt脚本代码的环境
QScriptEngineAgent QScriptEngine执行相关事件的接口
QScriptEngineDebugger QScriptEngine调试环境
QScriptProgram 封装了Qt脚本程序
QScriptString 表示QScriptEngine中字符串的句柄??
QScriptSyntaxCheckResult 存储脚本语法检查的结果
QScriptValue 表示Qt脚本数据类型的容器
QScriptValueIterator QScriptValue遍历器
QScriptable QtC++程序访问Qt脚本环境
语言概述
Qt脚本基于ECMAScript脚本语言,使用ECMA-262标准。微软的JScript和网景的javascript也是基于ECMAScript标准,有关 ECMAScript的概述,可以查看ECMAScript标准。如果你不熟悉ECMAScript语言,有一些指导和书籍,例如JavaScript: The Definitive Guide.
基本用法
为执行脚本代码,你可以创建一个QScriptEngine,然后调用它的evaluate()方法,传入脚本代码作为evaluate()的参数。
QScriptEngine engine;
qDebug() << "the magic number is:" << engine.evaluate("1 + 2").toNumber();
返回值是evaluate()执行的结果,这个结果可以转换为标准C++和Qt类型。
通过设置脚本引擎的全局对象,将自定义属性注册到脚本引擎当中变的很容易。
engine.globalObject().setProperty("foo", 123);
qDebug() << "foo times two is:" << engine.evaluate("foo * 2").toNumber();
以上代码是将属性放到脚本引擎当中,这样的脚本代码是有效的。
使QObject对象在QScript Engine中有效
在脚本当中任何基于QObject实例是有效的。
将QObject对象传入QScriptEngine::newQObject()函数当中,这样Qt脚本的封装基于QObject的对象将会被创建,被创建的脚 本对象可以使用QObject的信号、槽、属性、和子对象列表。
下面是一个Qobject子类化的例子,该对象在脚本代码中的名字是"myObject"。
QScriptEngine engine;
QObject *someObject = new MyObject;
QScriptValue objectValue = engine.newQObject(someObject);
engine.globalObject().setProperty("myObject", objectValue);
上面的例子,在脚本环境中创建一个全局的"myObject"变量,这个变量是一个c++对象的代理。C++对象在脚本中可以用任何的名称代指,不依赖上面的QObject::objectName().
newQObject()函数接收两个额外的可选参数:一个是所有权模式,另一个是可选的允许你控制QScriptValue封装QObject的行为的容器,我们以后再回顾这些参数。
使用信号和槽
Qt脚本适用Qt核心的信号和槽特性,在Qt脚本当中有三种主要方式使用信号和槽。
-
混合C++/Script:C++应用程序代码连接信号到一个脚本函数,例如,脚本函数可以使用户打字输入或者从文件读入的。如果你有一个QObject但是不想导出这个对象到脚本环境当中,只是想脚本中定义怎样响应
一个信号,并且把在c++中建立连接。
- 混合Script/C++: 对于应用程序导出到脚本环境中的对象,脚本能在该对象上建立信号和槽的连接,在这种情况下,槽仍然写在C++端,但是连接完全是脚本动态定义的。
- 完全脚本定义:脚本即能定义信号处理函数(相当于在Qt脚本中定义槽),也能设置这些处理程序的连接,例如,脚本能定义处理QLineEdit::returnPressed()信号的函数, 然后连接信号与这个脚本处理函数。
用qScriptConnect()函数连接c++信号与脚本函数,下面的例子是定义了一个连接到QLineEdit::textChanged()信号的脚本处理函数:
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::connnect()。您将相关信号引用为发送器对象的属性,并调用其connect()。有三个connect()的重载,每个都有一个相应的disconnect()过载。下面的小节描述了这三种形式。
- 函数连接的是信号(信号连接信号)
connect(function)
这种连接情况下,connect()的参数是连接到信号的处理函数
function myInterestingScriptFunction() {
// ...
}
// ...
myQObject.somethingChanged.connect(myInterestingScriptFunction);
参数可以是脚本函数,例如上面的例子。也可以是一个QObject对象的slot函数,像下面的例子:
myQObject.somethingChanged.connect(myOtherQObject.doSomething);
当参数是一个QObject对象的slot函数时,信号和槽的参数类型可以不兼容。如果必要,Qt Script将执行信号参数的转换,以匹配时隙的参数类型。
取消信号的连接,你可以调用这个信号的disconnect()函数,传递取消连接的参数:
myQObject.somethingChanged.disconnect(myInterestingFunction);
myQObject.somethingChanged.disconnect(myOtherQObject.doSomething)
当connect()只有一个参数时,this对象将是 Global Object。
- 信号连接到成员函数
connect(thisObject, function)
在这种连接方式下,第一个参数是绑定到this变量,第二个参数是被调用的函数。
在这种方式下,如果你有一个push button,你通常想在button的点击信号触发是做一些事情,在这种情况下,作为该对象传递窗体是有意义的。
var obj = { x: 123 };
var fun = function() { print(this.x); };
myQObject.somethingChanged.connect(obj, fun);
取消信号的连接,将同样的参数传递到disconnect()中:
myQObject.somethingChanged.disconnect(obj, fun);
- 命名成员函数连接的信号
connect(thisObject, functionName)
在这种连接方式下,第一个参数是绑定到this的变量,当信号的响应函数是被调用的,第二个参数指定信号的处理函数,这种情况下涉及到处理函数是第一个参数的成员函数。
注意这种情况下处理函数在连接时已经被确定了,而不是在信号触发是动态决定的。
var obj = { x: 123, fun: function() { print(this.x); } };
myQObject.somethingChanged.connect(obj, "fun");
取消信号连接用同样的参数 传递到disconnect() 中:
myQObject.somethingChanged.disconnect(obj, "fun");