接着上一章的讲解
枚举值
用Q_ENUMS声明的枚举值不能作为单个封装对象的属性使用,然而,如果他们是QMetaObject封装的对象就可以通过用QScriptEngine::newQMetaObject()创建。
Qt C++类型与脚本类型之间的转换
Qt脚本能执行脚本到C++端的类型转换,例如,当一个C++信号触发一个脚本函数时,当你在脚本中调用一个QObject属性时
当你在C++中调用QScriptEngine::toScriptValue()或者QScriptEngine::fromScriptValue()时, Qt提供了很多内建的类型转换操作,你也能用qScriptRegisterMetaType()为自己的类型注册转换操作。
默认的Qt脚本到C++的转换
下面的表描述了默认的Qt脚本到C++的转换
C++ Type Default Conversion
bool QScriptValue::toBool()
int QScriptValue::toInt32()
uint QScriptValue::toUInt32()
float float(QScriptValue::toNumber())
double QScriptValue::toNumber()
short short(QScriptValue::toInt32())
ushort QScriptValue::toUInt16()
char char(QScriptValue::toInt32())
uchar unsigned char(QScriptValue::toInt32())
long long(QScriptValue::toInteger())
ulong ulong(QScriptValue::toInteger())
qlonglong qlonglong(QScriptValue::toInteger())
qulonglong qulonglong(QScriptValue::toInteger())
QString QScriptValue::toString() 如果QScriptValue 是null或者undefined则字符串是空的;
QDateTime QScriptValue::toDateTime()
QDate QScriptValue::toDateTime().date()
QRegExp QScriptValue::toRegExp()
QObject* QScriptValue::toQObject()
QWidget* QScriptValue::toQObject()
QVariant QScriptValue::toVariant()
QChar If the QScriptValue is a string, the result is the first character of the string, or a null QChar if the string is empty; otherwise, the result is a QChar constructed from the unicode obtained by converting the QScriptValue to a ushort.
QStringList If the QScriptValue is an array, the result is a QStringList constructed from the result of QScriptValue::toString() for each array element; otherwise, the result is an empty QStringList.
QVariantList If the QScriptValue is an array, the result is a QVariantList constructed from the result of QScriptValue::toVariant() for each array element; otherwise, the result is an empty QVariantList.
QVariantMap If the QScriptValue is an object, the result is a QVariantMap with a (key, value) pair of the form (propertyName, propertyValue.toVariant()) for each property, using QScriptValueIterator to iterate over the object's properties.
QObjectList If the QScriptValue is an array, the result is a QObjectList constructed from the result of QScriptValue::toQObject() for each array element; otherwise, the result is an empty QObjectList.
QList<int> If the QScriptValue is an array, the result is a QList<int> constructed from the result of QScriptValue::toInt32() for each array element; otherwise, the result is an empty QList<int>.
另外,Qt脚本也执行下面的操作:
- 如果QScriptValue是一个QObject,目标类型名称是指针,可以用qobject_cast()转换。
- 如果QScriptValue是一个QVariant,目标类型名称是指针,QVariant的userType()是目标类型的指针类型,转换结果是一个QVarient数据的指针。
- 如果QScriptValue是一个QVariant,并且能通过QVariant::canConvert()知道可以进行转换,可以用qvaraint_cast()转换。
默认的从C++到脚本的转换
C++ Type Default Construction
void QScriptEngine::undefinedValue()
bool QScriptValue(engine, value)
int QScriptValue(engine, value)
uint QScriptValue(engine, value)
float QScriptValue(engine, value)
double QScriptValue(engine, value)
short QScriptValue(engine, value)
ushort QScriptValue(engine, value)
char QScriptValue(engine, value)
uchar QScriptValue(engine, value)
QString QScriptValue(engine, value)
long If the input fits in an int, QScriptValue(engine, int(value)); otherwise, QScriptValue(engine, double(value)). Note that the latter conversion can be lossy.
ulong If the input fits in a uint, QScriptValue(engine, uint(value)); otherwise, QScriptValue(engine, double(value)). Note that the latter conversion can be lossy.
qlonglong QScriptValue(engine, qsreal(value)). Note that the conversion may lead to loss of precision, since not all 64-bit integers can be represented using the qsreal type.
qulonglong QScriptValue(engine, qsreal(value)). Note that the conversion may lead to loss of precision, since not all 64-bit unsigned integers can be represented using the qsreal type.
QChar QScriptValue(this, value.unicode())
QDateTime QScriptEngine::newDate(value)
QDate QScriptEngine::newDate(value)
QRegExp QScriptEngine::newRegExp(value)
QObject* QScriptEngine::newQObject(value)
QWidget* QScriptEngine::newQObject(value)
QVariant QScriptEngine::newVariant(value)
QStringList A new script array (created with QScriptEngine::newArray()), whose elements are created using the QScriptValue(QScriptEngine *, QString) constructor for each element of the list.
QVariantList A new script array (created with QScriptEngine::newArray()), whose elements are created using QScriptEngine::newVariant() for each element of the list.
QVariantMap A new script object (created with QScriptEngine::newObject()), whose properties are initialized according to the (key, value) pairs of the map.
QObjectList A new script array (created with QScriptEngine::newArray()), whose elements are created using QScriptEngine::newQObject() for each element of the list.
QList<int> A new script array (created with QScriptEngine::newArray()), whose elements are created using the QScriptValue(QScriptEngine *, int) constructor for each element of the list.
其他的类型(包括自定义类型)用 QScriptEngine::newVariant()封装,任何类型的空指针用QScriptEngine::nullValue()封装。
如何设计和实现一个应用程序对象
本节解释如何实现应用程序对象,并提供必要的技术背景材料。
在脚本中创建一个C++对象
让C++类和对象在脚本语言中可用是没有意义的,因为脚本语言更具有动态性,并且必须能够在运行时自查对象(查询函数信息,例如函数名、函数签名、属性等)。标准C++没有为此提供特性。
我们可以通过扩展C++来实现我们想要的功能,使用C++自己的功能,所以我们的代码仍然是标准的C++。Qt元对象系统提供必要的附加功能。它允许我们使用扩展的C++语法编写,但是使用一个称为MOC(元对象编译器)的小型实用程序将其转换成标准C++。希望利用元对象工具的类是QObject的子类,或者使用Q_OBJECT宏。QT多年来一直使用这种方法,并且已经证明是可靠的。Qt脚本使用这个元对象技术为脚本提供了对C++类和对象的动态访问。
要完全理解如何使C++对象可以用于QT脚本,对QT元对象系统的一些基本知识是非常有帮助的。我们建议您阅读 Object Model 和 Meta-Object System,这对于理解如何实现应用程序对象很有用。
然而,在最简单的情况下,这种知识并不重要。要使对象在Qt脚本中可用,必须从QObject派生。从QObject派生的所有类都可以自查,并且可以在运行时提供脚本引擎所需的信息;例如,类名、函数、签名。因为我们在运行时动态地获得关于类所需的信息,所以不需要为QObject派生类编写包装器。
c++的成员函数在脚本中可用
元对象系统还使有关信号和槽的信息在运行时动态可用。默认情况下,对于QObject子类,只有信号和插槽自动对脚本可用。这是非常方便的,因为在实践中,我们通常只希望对脚本程序提供指定的函数。创建QObject子类时,请确保要向Qt Script公开的函数是公共插槽。
例如,下面的类定义仅为某些函数启用脚本
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject( ... );
void aNonScriptableFunction();
public slots: // these functions (slots) will be available in Qt Script
void calculate( ... );
void setEnabled( bool enabled );
bool isEnabled() const;
private:
....
};
上面的例子,aNonScriptableFunction()函数没有申明为slot,所以它在脚本中是不可用的,其他的三个函数在脚本中是可用的,因为他们被声明为public slots。
如果想任何函数在脚本中可用,必须将函数指定为Q_INVOKABLE。(这样就会将该函数加入到meta-object中)
class MyObject : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void thisMethodIsInvokableInQtScript();
void thisMethodIsNotInvokableInQtScript();
...
};
一旦用Q_INVOKABLE声明,就可以从Qt脚本代码调用该方法,就像它是一个插槽一样。尽管这样的方法不是插槽,但是您仍然可以在脚本代码中将指定为connect()的目标函数;connet()接受本机函数和非本机函数作为目标。
正如默认的从Qt脚本到C++的转换所讨论的,Qt脚本处理许多C++类型的转换。如果函数接受Qt Script不处理转换的参数,则需要提供转换函数。这是使用qScript TrestMyTyType()函数完成的。