属性系统

属性基础

c.h文件:

#ifndef C_H
#define C_H

#include<QObject>

class A:public QObject{ 
    Q_OBJECT
public: /*通常,若属性名为 a,则相应的读取函数通常命名为 geta,设置函数命名为 seta,本例并未使用这种命名
            规则*/
    
    //声明一个类型为 int,名称为 a 的属性,并使用函数 f 读取属性值,使用函数 g 设置属性值。
    Q_PROPERTY(int a READ f WRITE g)
    
    //声明一个类型为 int,名称为 b 的属性,并把该属性与成员变量 m_b 相关联,该属性未设置存取函数。
    Q_PROPERTY(int b MEMBER m_b)
    
    //声明一个只读属性 c,本例没有设置该属性值的函数,因此该属性是只读的。
    Q_PROPERTY(int c READ getc)
    
    /*在存取函数中可把属性与成员变量相关联,方法如下所示。对存取函数的返回类型和参数类型及数量在本
        例影响不大,在后文会讲解其影响。*/
    int f(){return m_a;} //属性 a 的读取函数。
    void g(int i){m_a=i;} //属性 a 的设置函数。
    int getc(){m_c=3; return m_c;} /*成员变量也可以不与属性相关联,本函数也可直接返回数值 3。
                                    从此处可看到,属性可以不与数据成员相关联。*/
    int m_a,m_b; //属性若命名为 a,则与其相对应的成员变量习惯上应命名为 m_a。
private://成员变量通常都应声明为私有的,这样可提高程序的封装性。
    int m_c; 
};

#endif // C_H

main.cpp文件:

void fun_3()
{
    A ma;
    
    //像普通成员变量一样存取属性值
    ma.m_a=1;
    cout<<ma.m_a<<endl; //输出 1
    
    //因为属性 b 没有存取函数,本例暂时只使用普通成员变量的方式存取该属性值。
    ma.m_b=2;
    cout<<ma.m_b<<endl; //输出 2
    
    ma.g(4); //使用属性 a 的设置函数修改属性值。
    cout<<ma.f()<<endl; // 输出 4,使用属性 a 的读取函数读取属性值。
    cout<<ma.getc()<<endl; /*输出 3,属性 c 是只读的,只能通过他的读取函数访问其值,因为没有设置
                              函数,因此无法改变属性 c 的值。*/
}

QVariant:基础

class C{}; // 自定义类型
void fun_4(){
    QVariant v('a'); /*QVariant 没有专门的 char 构造函数,此处的字符 a 会被转换为 int 型,因此 v
                       中存储的是数值 97,而不是字符 a 。*/
    cout<<v.value<int>()<<endl; //输出 97
    cout<<v.value<char>()<<endl; //输出 a,将 97 转换为 char 型,并输出转换后的值。
    cout<<v.toChar().toLatin1()<<endl; /*输出 a,原因同上,注意 toChar 返回的类型是 QChar 而不
                                         是 char。*/
    cout<<v.toString().toStdString()<<endl; /*输出 97,把存储在 v 中的值转换为 QString,然后以字
                                              符串形式输出。*/
    cout<<v.typeName()<<endl; //输出 int,可见存储在 v 中的值的类型为 int
    cout<<v.typeToName(v.type())<<endl; /*输出 int,其中 type 返回存储值的枚举形式表示的类型,而
                                          typeToName 则以字符串形式显示该枚举值所表示的类型。*/
    char c='b';
    v.setValue(c);
    cout<<v.toString().toStdString()<<endl; //输出 b
    cout<<v.typeName()<<endl; /*输出 char,若是使用 QVariant 构造函数和直接赋值 char 型字符,此
                                处会输出 int,这是 setValue 与他们的区别。*/
    C mc; //自定义类型 C 的对象 mc
    //QVariant v1(mc); //错误,没有相应的构造函数。
    QVariant v2;
    //v2=mc; //错误,没有与类型 C 匹配的赋值运算符函数。
    //v2.setValue(mc); //错误,自定义类型 C 未使用宏 Q_DECLARE_METATYPE 声明。
}

QVariant:声明与注册用户自定义类型

class A{public: int i;};
class B{public:int i;};
class D{public:D(int){}};//该类无 public 默认构造函数
class E{ };
class F:public QObject{};
//声明类型
Q_DECLARE_METATYPE(A)
Q_DECLARE_METATYPE(B)
//Q_DECLARE_METATYPE(D) //错误,类 D 没有公有的默认构造函数
//Q_DECLARE_METATYPE(F) //错误,因为父类 QObject 的复制构造函数、赋值运算符等是私有的。
void fun_5()
{
    //注册类型
    qRegisterMetaType<B>();
    // qRegisterMetaType<E>(); //错误,类型 E 未使用宏 Q_DECLARE_METATYPE(T)声明
    // qRegisterMetaType<F>(); //错误,因为父类 QObject 的复制构造函数、赋值运算符等是私有的
    
    A ma; ma.i=1;
    B mb; mb.i=2;
    
    //QVariant v1(ma); //错误,没有相应的构造函数。
    QVariant v;
    v.setValue(ma); //将对象 ma 存储在 v 之中
   
    cout<<v.value<A>().i<<endl; //输出 1。
    cout<<v.typeName()<<endl; //输出 A
    cout<<v.toString().toStdString()<<endl; //输出一个空字符,因为 ma 是一个对象,不是一个值。
    
    //自定义类型需要使用 userType 才能返回正确的类型 ID。
    cout<<v.typeToName(v.userType())<<endl; //输出 A
    cout<<v.typeToName(v.type())<<endl; //不一定输出 A。
    
    A ma1;
    ma1=v.value<A>(); //把存储在 v 之中的对象 ma 赋值给 ma1
    cout<<ma1.i<<endl; //输出 1,可见赋值成功。
    
    B mb1;
    //mb1=v.value<A>(); //错误,类型不相同。
    mb1=v.value<B>(); //失败,由类型 A 转换到类型 B 失败,此时 value 会返回一个默认构造的值。
    cout<<mb1.i<<endl; //输出 0。
}

使用 QObject 类中的成员函数存取属性值与动态属性

d.h文件:

#ifndef D_H
#define D_H
#include<QObject>
class B{public:int i;};
class C{public:int i;};
class D{public:int i;};
Q_DECLARE_METATYPE(B)
Q_DECLARE_METATYPE(C)
class Z:public QObject{ 
    Q_OBJECT
public: Z(){}
    Q_PROPERTY(B b READ fb WRITE gb)
    Q_PROPERTY(C c READ fc WRITE gc)
    Q_PROPERTY(D d READ fd WRITE gd)
    B fb(){return m_mb;} void gb(B x){m_mb=x;}
    C fc(){return m_mc;} void gc(C x){m_mc=x;}
    D fd(){return m_md;} void gd(D x){m_md=x;}
    B m_mb; C m_mc; D m_md; 
};
#endif // D_H

main.cpp文件:

void fun_6(){
    qRegisterMetaType<B>();
    qRegisterMetaType<C>();

    B mb; C mc; D md; Z mz;
    mb.i=2; mc.i=3; md.i=4;
    mz.gb(mb); mz.gc(mc); mz.gd(md);

    //使用 porperty 和 setProperty 存取属性值。
    //mz.property("d"); //错误,不能使用 property 函数访问属性 d,因为属性 d 的类型 D 未注册。
    mz.property("MMM"); /*这是正确的,因为属性 MMM 不存在,所以,返回的是一个空的 QVariant 对象,
                          可见,属性不存在与属性的类型未注册是不同的。*/
    cout<<mz.fd().i<<endl; /*输出 4。虽然不能使用 property 函数访问属性 d,但仍可使用存取函数
                             访问该属性的值。*/
    QVariant v; B mb1;
    mb1.i=6; v.setValue(mb1);
    //mz.setProperty("b",mb1); //错误,第二个参数的类型不匹配。
    mz.setProperty("b",v); //正确设置属性 b 的值的方法,把属性 b 的值设置为 v 中存储的值 mb1。
    mz.setProperty("c",v); /*正确,但是属性 c 的类型与 v 中存储的值的类型不兼容,因此属性 c 不
                             会被更改*/
    mz.setProperty("c",7); //原因同上。
    cout<<mz.property("b").typeName()<<endl; //输出 B,输出属性 b 的类型
    cout<<mz.property("c").typeName()<<endl; //输出 C,输出属性 c 的类型
    cout<<mz.property("b").value<B>().i<<endl; //输出 6。输出的是 mb1.i 的值。
    cout<<mz.property("c").value<C>().i<<endl; //输出 3,属性 c 的值并未被更改。
    //动态属性
    mc.i=7; v.setValue(mc);
    // mz.setProperty("w",mc); //错误,第二个参数的类型不匹配。
    mz.setProperty("x",v); //动态属性,新增加属性 x,并设置其值为 v 中存储的值(即 mc)
    cout<<mz.property("x").typeName()<<endl; //输出 C,即动态属性 x 的类型。
    cout<<mz.property("x").value<C>().i<<endl; //输出 7。
    Z mz1;
    //cout<<mz1.property("x").typeName()<<endl; //错误,动态属性 x 是基于对象 mz 的。
    cout<<mz1.property("b").typeName()<<endl; //输出 B,属性 b 不是动态属性。
}

使用反射机制获取属性的信息

class Z:public QObject{ 
    Q_OBJECT
public:
    Q_PROPERTY(int b READ gb WRITE sb)
    int gb(){return m_mb;} void sb(int x){m_mb=x;}
    int m_mb; 
};
void fun_7(){

    Z mz;
    const QMetaObject *p=mz.metaObject();
    QMetaProperty pe=p->property(p->indexOfProperty("b")); //获取属性 b 的元数据。
    cout<<pe.name()<<endl; //输出属性的名称 b
    cout<<pe.typeName()<<endl; //输出属性 b 的类型 int
    pe.write(&mz,47); //把值 47 写入属性 b
    cout<<pe.read(&mz).value<int>()<<endl; //输出属性 b 的值 47。
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柔弱胜刚强.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值