Qt Script之customclass

在自定义脚本类的例子展示了如何使用QScriptClass和QScriptClassPropertyIterator来实现自定义的脚本类。
使用ByteArray类
当ByteArray类可以在脚本环境中使用时,ByteArray对象可以像下面一样被构造
var ba = new ByteArray();
var ba2 = new ByteArray(10);
ByteArray对象的行为类似于普通的数组对象。每一个ByteArray对象有一个length属性。如果一个新值被赋值给length属性,数组将重新设置大小。
for(var i = 0; i < ba.length; ++ i)
ba[i] = 123;
当给数组元素赋值的时候,值将会被截断为8位
b[0] = 257;
print(ba[0]);//1
像普通数组对象一样,如果数组索引比数组当前长度大则数组重新改变大小。
var ba3 = new ByteArray();
print(ba3.length);//0
ba3[0] = 64;
print(ba3.length);//1
无效的数组索引将被像普通对象属性那样对待。
ba[“foo”] = “Hello”;
上面的赋值将不会影响数组内容但是将会给对象的属性foo赋值。
ByteArray对象有一组方法:chop(),equals(),left(),mid(),toBase64()等等。
ByteArray类接口
为了在C++中实现ByteArray脚本类,我们创建了一个叫做ByteArrayClass的QScriptClass子类。并且重新实现了QScriptClass的虚函数。我们提供了一个适合被添加到QScriptEngine环境的Qt Script构造函数。
ByteArrayClass::ByteArrayClass(QScriptEngine *engine)
: QObject(engine), QScriptClass(engine)
{
qScriptRegisterMetaType”<”QByteArray”>”(engine, toScriptValue, fromScriptValue);

 length = engine->toStringHandle(QLatin1String("length"));

 proto = engine->newQObject(new ByteArrayPrototype(this),
                            QScriptEngine::QtOwnership,
                            QScriptEngine::SkipMethodsInEnumeration
                            | QScriptEngine::ExcludeSuperClassMethods
                            | QScriptEngine::ExcludeSuperClassProperties);
 QScriptValue global = engine->globalObject();
 proto.setPrototype(global.property("Object").property("prototype"));

 ctor = engine->newFunction(construct);
 ctor.setData(qScriptValueFromValue(engine, this));

}
第一,构造函数注册两个转换函数,以便于C++ QByteArray对象并且Qt Script ByteArray对象可以无缝地在C++和脚本之间移动。例如,如果一个ByteArray对象被传递给一个带有QByteArray参数的C++槽,封装真实QByteArray的ByteArray将会被正确地传递。
第二,我们存储一个”length”字符串的句柄以便于我们可以很快地跟被给的属性名”length”比较。
第三,我们初始化标准的ByteArray原型,通过重新实现prototype()来返回。
第四,我们为ByteArray初始化一个构造函数,通过contructor()函数返回。我们设置构造函数的内部数据为一个指向ByteArrayClass对象的指针,当构造函数被调用的时候,可以提取指针并且使用它来创建一个新的ByteArray对象。
QScriptValue ByteArrayClass::newInstance(const QByteArray &ba)
{
QScriptValue data = engine()->newVariant(qVariantFromValue(ba));
return engine()->newObject(this, data);
}
construct是本地函数充当ByteArray在脚本中的构造函数。我们可以提取指向类的指针然后调用newInstance()重载带有一个初始的大小作为参数并且返回新的脚本对象。
QScriptClass::QueryFlags ByteArrayClass::queryProperty(const QScriptValue &object,
const QScriptString &name,
QueryFlags flags, uint *id)
{
QByteArray ba = qscriptvalue_cast”<”QByteArray“>”(object.data());
if (!ba)
return 0;
if (name == length) {
return flags;
} else {
qint32 pos = toArrayIndex(name);
if (pos == -1)
return 0;
*id = pos;
if ((flags & HandlesReadAccess) && (pos >= ba->size()))
flags &= ~HandlesReadAccess;
return flags;
}
}
无论何时任何人尝试访问ByteArray对象的属性,Qt Script都将调用queryPorperty()函数。首先我们得到一个指向QByteArray的指针.我们检查特殊的属性length是否被访问,如果是我们返回,表明我们将处理每种对这个属性的访问(读跟写)。否则我们尝试转换属性名到一个数组索引。如果失败,我们返回,表明我们不想处理这个属性,否则我们获得一个有效的数组索引并且在id参数中存储它,便于我们没有必要重新计算它在property()或者setProperty().如果索引是更大或者相同比QByteArray的大小,我们表明我们不想处理读访问(但是我们仍想处理写)
QScriptValue ByteArrayClass::property(const QScriptValue &object,
const QScriptString &name, uint id)
{
QByteArray ba = qscriptvalue_cast”<”QByteArray“>”(object.data());
if (!ba)
return QScriptValue();
if (name == length) {
return QScriptValue(engine(), ba->length());
} else {
qint32 pos = id;
if ((pos < 0) || (pos >= ba->size()))
return QScriptValue();
return QScriptValue(engine(), uint(ba->at(pos)) & 255);
}
return QScriptValue();
}
在property()重新实现中,我们做类似的检查如queryProperty()来查找被请求的属性并且返回属性值。
void ByteArrayClass::setProperty(QScriptValue &object,
const QScriptString &name,
uint id, const QScriptValue &value)
{
QByteArray ba = qscriptvalue_cast”<”QByteArray“>”(object.data());
if (!ba)
return;
if (name == length) {
ba->resize(value.toInt32());
} else {
qint32 pos = id;
if (pos < 0)
return;
if (ba->size() <= pos)
ba->resize(pos + 1);
(*ba)[pos] = char(value.toInt32());
}
}
setProperty()重新实现了一个类似于porperty()的结构。如果length属性被设置,我们改变QByteArray的大小根据被给的长度。否则我们抓取数组索引在queryProperty()函数中被重新计算的,如果需要扩大数组,并且将给定的值写入数组。
QScriptValue::PropertyFlags ByteArrayClass::propertyFlags(
const QScriptValue &/object/, const QScriptString &name, uint /id/)
{
if (name == length) {
return QScriptValue::Undeletable
| QScriptValue::SkipInEnumeration;
}
return QScriptValue::Undeletable;
}
propertyFlags()重新实现了指定的length属性不能被删除并且不可枚举。数组元素不能被删除
QScriptClassPropertyIterator *ByteArrayClass::newIterator(const QScriptValue &object)
{
return new ByteArrayClassPropertyIterator(object);
}
我们想要数组元素出现,当一个ByteArray对象在for-in语句中使用和QScriptValueIterator一起。因此我们重新实现newIterator()函数并且用它返回一个新的迭代器。
ByteArray Iterator Implementation
ByteArray迭代器实现
bool ByteArrayClassPropertyIterator::hasNext() const
{
QByteArray ba = qscriptvalue_cast”<”QByteArray“>”(object().data());
return m_index < ba->size();
}

void ByteArrayClassPropertyIterator::next()
{
m_last = m_index;
++m_index;
}

bool ByteArrayClassPropertyIterator::hasPrevious() const
{
return (m_index > 0);
}

void ByteArrayClassPropertyIterator::previous()
{
–m_index;
m_last = m_index;
}

void ByteArrayClassPropertyIterator::toFront()
{
m_index = 0;
m_last = -1;
}

void ByteArrayClassPropertyIterator::toBack()
{
QByteArray ba = qscriptvalue_cast”<”QByteArray“>”(object().data());
m_index = ba->size();
m_last = -1;
}

QScriptString ByteArrayClassPropertyIterator::name() const
{
return QScriptString();
}

uint ByteArrayClassPropertyIterator::id() const
{
return m_last;
}
The ByteArrayClassPropertyIterator class is simple. It maintains an index into the underlying QByteArray, and checks and updates the index in hasNext(), next() and so on.
ByteArrayClassPropertyIterator类是简单的。它维护一个到QByteArray的索引并且检查和更新索引在hasNext()和next()
ByteArray Prototype Implementation
ByteArray原型实现
The prototype class, ByteArrayPrototype, implements the ByteArray functions as slots.
ByteArrayPrototype原型类实现了ByteArray函数当作槽
class ByteArrayPrototype : public QObject, public QScriptable
{
Q_OBJECT
public:
ByteArrayPrototype(QObject *parent = 0);
~ByteArrayPrototype();

public slots:
void chop(int n);
bool equals(const QByteArray &other);
QByteArray left(int len) const;
QByteArray mid(int pos, int len = -1) const;
QScriptValue remove(int pos, int len);
QByteArray right(int len) const;
QByteArray simplified() const;
QByteArray toBase64() const;
QByteArray toLower() const;
QByteArray toUpper() const;
QByteArray trimmed() const;
void truncate(int pos);
QString toLatin1String() const;
QScriptValue valueOf() const;

private:
QByteArray *thisByteArray() const;
};
There is a small helper function, thisByteArray(), that returns a pointer to the QByteArray being operated upon:
这有一个小的有帮助的函数,thisByteArray()返回一个在QByteArray上操作的指针
QByteArray *ByteArrayPrototype::thisByteArray() const
{
return qscriptvalue_cast”<”QByteArray*”>”(thisObject().data());
}
The slots simply forward the calls to the QByteArray. Examples:

QByteArray ByteArrayPrototype::mid(int pos, int len) const
{
return thisByteArray()->mid(pos, len);
}

QScriptValue ByteArrayPrototype::remove(int pos, int len)
{
thisByteArray()->remove(pos, len);
return thisObject();
}
The remove() function is noteworthy; if we look at QByteArray::remove(), we see that it should return a reference to the QByteArray itself (i.e. not a copy). To get the same behavior in scripts, we return the script object (thisObject()).
remove函数是值得注意的如果我们查看QByteArray::remove(),我们看它应该返回一个QByteArray的引用。为了获得跟脚本中一样的行为,我们返回脚本对象。

virtual QString name() const
返回脚本类的名字。Qt Script使用这个名字形成一个代表对象的默认字符串,以防你不提供一个toString函数。
virtual QScriptClassPropertyIterator * newIterator(const QScriptValue & object)
返回一个遍历所给对象自定义属性的迭代器。默认实现是返回0表示没有可遍历的自定义属性。重新实现这个函数如果你的脚本类对象有一个或者多个自定义属性。当枚举一个对象的属性时,你想要出现的被queryProperty()处理。
virtual QScriptValue property(const QScriptValue & object, const QScriptString & name, uint id)
返回被给对象的属性名的值。id参数只是有用的,如果你在queryProperty()中为它赋值了。
virtual QScriptValue::PropertyFlags propertyFlags(const QScriptValue & object, const QScriptString & name, uint id)
返回属性标志。
virtual QScriptValue prototype() const
返回被用来作为原型的这个类的新实例。默认返回一个无效的QScriptValue,意味着使用了标准的Object原型,重新实现这个函数提供你自定义的原型。通常在你的构造汉书里初始化你的原型对象然后返回它。
virtual QueryFlags queryProperty(const QScriptValue & object, const QScriptString & name, QueryFlags flags, uint * id)
查询这个脚本类如何处理访问被给对象属性名。对给定的flags指定感兴趣的flags.这个函数应该返回一个flags的子集合属性访问的哪些方面应该被脚本类进一步处理
virtual void setProperty(QScriptValue & object, const QScriptString & name, uint id, const QScriptValue & value)
设置属性,id参数是有用的如果你在queryProperty()中给它赋值。
翻译原文http://lefloo.free.fr/Documentations/Qt/script-customclass.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值