动态属性和元类型的声明和注册

动态属性

前面我们知道使用Q_PROPERTY宏可以为类创建变量,但是那只是静态变量。在QObject中加载和存储一些属性也是可能的,即添加动态属性。
到现在位置,我们已经对用Q_PROPERTY宏定义的那些属性进行了专门处理。这些属性对该类的QMetaObject是可知,且有对应的QMetaProperty与之对应。同一个类的所有对象会共享同一个metaObject,因而会有相同的元属性组。另一方面,在运行时获得动态属性的情况下,同一个类的两个对象会具有相同的元属性列表,但对于动态属性可以有不同动态属性列表。

class DynoProps : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString someString READ someString WRITE setSomeString )
public:
    QString someString() {return m_someString;}
    void setSomeString(QString ss) {m_someString = ss;}
    QString propsInventory();

private:
    QString m_someString;
};


QString DynoProps::propsInventory()
{
    static const QMetaObject* meta = metaObject();//该函数由moc生成
    QStringList res;
    res << "Fixed Properties:";
    for (int i = 0; i < meta->propertyCount(); ++i) {
        res << QString("%1\t%2").arg(QString(meta->property(i).name()))/*Returns this property's name.*/
               .arg(meta->property(i).read(this).toString());//(read):Reads the property's value from the given object. Returns the value if it was able to read it; otherwise returns an invalid variant.
    }
    res << "Dynamic Properties:";
    foreach (QByteArray dpname, dynamicPropertyNames()) {
        res << QString("%1\t%2").arg(QString(dpname))             .arg(property(dpname).toString());
    }

    return res.join("\n");

}

以上函数给出了一种显示固定属性和动态属性的方法。固定属性的清单来自QMetaObject。使用QMetaProperty::read()或者QObject::property()可以查询属性的值。propertyCount()函数会设置对QMetaProperty清单进行遍历的条件。
QMetaObject无法知道动态属性。那么,如果要知道动态属性必须得使用QObject的一些方法。可以对利用QObject::dynamicPropertyNames()返回的QList清单中的名称进行遍历,并可用QObject::property()获得其值。

使用和输出:


int main(int argc, char *argv[])
{
    QTextStream cout (stdout);
    DynoProps d1,d2;
    d1.setObjectName("d1");
    d2.setObjectName("d2");
    d1.setProperty("intprop",42);
    d1.setProperty("realProp",3.1415926);
    cout << d1.propsInventory() << endl<<endl;
    cout << d2.propsInventory() << endl;
    return 0;
}

运行结果

Fixed Properties:
objectName	d1
someString
Dynamic Properties:
intprop	42
realProp	3.1415926
 
Fixed Properties:
objectName	d2
someString
Dynamic Properties:

元类型的声明和注册

QMetaType是一个用于值类型的辅助类(helper class)。对于内置60多种数据类型,QMetaType为每个类型ID都关联了一个类型名,从而使构造和析构可用在运行时动态发生。有一个名称为QMetaType::Type的公共枚举,它有所有QVariant兼容类型的值。即QMetaType::Type中的枚举值与QVariant::Type中的枚举值一样。
通过使用Q_ENUMS宏,我们可以在QVariant系统中加入一些自定义的枚举类型。使用Q_DECLARE_METATYPE(MyType)宏把自己定义的值类型加到QMetaType列表中。它需要提供一个公共的默认构造函数,公共的拷贝构造函数和公共的析构函数。ps:编译器默认的即可

-----------------------h-----------------
class Computer {
public:
    Computer(int aa ) :
        a(aa) {}
    int a;
};

Q_DECLARE_METATYPE(Computer)				Tag1
-----------------------cpp-----------------

    int fracType = QMetaType::type("Computer");//Returns a handle to the type called typeName, or 0 if there is no such type.
    [...]
    Computer com(2);
    QVariant var;
    var.setValue(com);
    cout << var.value<Computer>().a <<endl;
----------------------output------------------
258
2

如果将Tag1行注释掉,则输出为报错。error: 'qt_metatype_id' is not a member of 'QMetaTypeId<Computer>'

qRegisterMetaType()

要注册的元类型必须已经用Q_DECLARE_METATYPE声明过。模板函数qRegisterMetaType<T>()会注册类型T并返回由QMetaType使用的内部ID。这个函数有一个重载版本,qRegisterMetaType<T>(const char* name),同样也是用来注册类型并返回ID 。在使用类型T作为信号和槽的参数时,qRegisterMetaType<T>()必须在第一个连接之前调用。即在连接信号和槽之前调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值