Qt 5.5 中Qt Script翻译 (二)

接着上一章的讲解

当connect()或者disconnect()成功调用,将返回undefined;否则,将投递一个脚本异常,你可以从结果Error  object中获取error信息,例如:

try {
    myQObject.somethingChanged.connect(myQObject, "slotThatDoesntExist");
} catch (e) {
    print(e);
}

  脚本触发信号

   在脚本中触发信号,你可以简单的调用信号函数,并传递相关的参数:

myQObject.somethingChanged("hello");

   在脚本中不支持定义信号,信号必须在c++中定义。

重载信号和槽

当信号和槽被重载时,Qt脚本将尝试根据QScriptValue的类型选择被调用的函数,例如,如果你的类中有myOverloadedSlot(int) 和myOverloadedSlot(QString)两种槽函数,下面的脚本代码将合理运行:

myQObject.myOverloadedSlot(10);   // will call the int overload
myQObject.myOverloadedSlot("10"); // will call the QString overload

用array-style属性你也能指定一个详细的重载函数,array-style使用C++函数的归一化签名作为属性名称:

myQObject['myOverloadedSlot(int)']("10");   // call int overload; the argument is converted to an int
myQObject['myOverloadedSlot(QString)'](10); // call QString overload; the argument is converted to a string

如果重载的函数有不同数量的参数,Qt将选择重载函数通过参数数量最符合被要求槽的参数数量。

重载信号,如果你尝试通过名字连接信号,Qt脚本会触发一个错误,您必须使用要连接的特定过载的完整规范化签名来引用信号。

访问属性

QObject对象的属性在Qt脚本对象中对应相应的属性,当你再脚本中操作一个属性时,C++中的属性的get/set方法将自动被调用,例如,如果你的C++类中声明了一个属性,向下面这样:

Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)

脚本代码中可以做下面的事情:

myQObject.enabled = true;

// ...

myQObject.enabled = !myQObject.enabled;

访问子对象列表

QObject中每一个命名的孩子在脚本封装的对象中是默认有效的,例如,如果你有一个QDialog,QDialog有一个子Widget对象的objectName属性是“okButton”,你可以通过下面的表达式在脚本中访问子对象:

myDialog.okButton

因为objectName是它自己的一个Q_PROPERTY,你能在脚本中操作这个名字,例如,重命名这个对象:

myDialog.okButton.objectName = "cancelButton";
// from now on, myDialog.cancelButton references the button

你也能用findchild()和findChildren()查找children,这两个函数的行为是定义的 QObject::findChild() 和 QObject::findChildren(),例如,我们可以这些函数或正则表达式查找Objects:

var okButton = myDialog.findChild("okButton");
if (okButton != null) {
   // do something with the OK button
    okButton.text='hello'; 
}

var buttons = myDialog.findChildren(RegExp("button[0-9]+"));
for (var i = 0; i < buttons.length; ++i) {
   // do something with buttons[i]
}

You typically want to use findChild() when manipulating a form that uses nested layouts; that way the script is isolated from the details about which particular layout a widget is located in。

上面的英文我的理解是: 当操作一个窗口时,通常想用findChild()查找布局下的窗口,并更改窗口,使窗口更加美观。

控制QObject的所有权

Qt脚本适用垃圾收集器回收不在需要的脚本对象的内存;在脚本环境中一个对象如果不在被使用,它的内存能被自动回收。当脚本封装的C++对象被回收时Qt脚本让你控制C++ QObject会做什么。当你通过传递ownership modeQScriptEngine::newQObject()的第二个参数来创建一个脚本对象时。

了解Qt脚本处理ownership是很重要的,因为它能帮助你避免内存泄漏。

Qt Ownership

     将QScriptEngine::ScriptOwnership指定为所有权模式将导致脚本引擎获得QObject的完全所有权,并在确定这样做是安全的时删除它(即,当脚本代码中不再有对它的引用时)。如果QObject没有父对象,和/或QObject是在脚本引擎的上下文中创建的,并且不打算超过脚本引擎,则此所有权模式是适当的。

例如,    构造函数构造仅在脚本环境中使用的QObjects是很好的候选项(脚本中创建的QObject对象,只在脚本中使用):

QScriptValue myQObjectConstructor(QScriptContext *context, QScriptEngine *engine)
{
  // let the engine manage the new object's lifetime.
  return engine->newQObject(new MyQObject(), QScriptEngine::ScriptOwnership);
}

Auto-Ownership

QScriptEngine::AutoOwnership是基于QObject是否有父对象,如果QObject没有父对象,并且在脚本中不在被使用,那么Qt脚本收集器将回收该内存。

如果其他人也删除了这个QObejct将会发生什么?

在脚本外没有注意到所有权而删除一个封装的QObject对象是有可能的,在这种情况下,封装的对象将仍然是一个对象(不像C++指针,脚本对象不会变成null),任何访问脚本属性的尝试将触发一个异常。

注意即使删除一个QObject对象QScriptValue::isQObject()将仍然返回true,因为这样仅仅是测试脚本对象的类型,不是内部指针是否为非空。换句话说,如果QScriptValue::isQObject()返回true,但是QScriptValue::toQObject()返回null,则QObject已经在Qt脚本外被删除。

自定义访问QObject对象

QScriptEngine::newQObject()可以带三个参数,这些参数允许你控制访问QObject的很多种情况。

QScriptEngine::ExcIncludeChildObjects指定QObject的子对象不应该作为一个脚本对象的属性存在。

QScriptEngine::ExcIncludeSuperClassProperties和QScriptEngine::ExcIncludeSuperClassMethods能用来允许导出QObject的父类的成员,这对于定义“纯”接口非常有用,从脚本的角度来看,继承的成员没有意义。您不希望脚本作者能够更改对象的objectName属性或调用deleteLater()槽。

QScriptEngine::AutoCreateDynamicProperties指定应该将QObject中不存在的属性创建为QObject的动态属性,而不是Qt Script包装器对象的属性。如果希望新属性真正成为QObject的持久属性,而不是与包装器对象一起销毁的属性(如果QObject多次用QScriptEngine::newQObject()包装,则不共享这些属性),则应该使用此选项。

QScriptEngine::SkipMethodsInEnumeration指定在for-in脚本语句中枚举QObject包装器的属性时应跳过信号和插槽。这在定义原型对象时很有用,因为根据约定,原型的属性不应该是可枚举的。

从脚本中创建一个新的基于QObjor的类

QScriptEngine::newQObject()函数用来封装一个已经存在的QObject对象的实例,以便脚本可以使用它。一个不同的情况是你想在脚本中构建一个新的对象,而不是仅仅访问一个已经存在的对象。

Qt meta-type 系统不支持基于QObject类的构造函数的动态绑定,如果你想在脚本中创建一个新对象,Qt脚本可以为您生成一个合理的脚本构造函数,查看QScriptEngine::scriptValueFromQMetaObject().

你也能用QScriptEngine::newFunction()封装你自己的的工厂函数,然后添加到脚本环境当中,查看QScriptEngine::newQMetaObject() 相关的例子.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值