• Qt 自定义属性 Q_PROPERTY


     Qt提供了一个绝妙的属性系统。跟那些由编译器提供的属性差不多。然而,作为一个独立于编译器和平台的库,Qt不依赖于非标准的编译特性,比如__property 或[property]。Qt可以在任何平台上的标准编译器下编译。Qt属性系统基于元数据对象系统--就是那个提供了对象内置信号和槽通讯机制的家伙。

        Q_PROPERTY()是一个宏,用来在一个类中声明一个属性property,由于该宏是qt特有的,需要用moc进行编译,故必须继承于QObject类。

     1 Q_PROPERTY(type name
     2    READ getFunction
     3    [WRITE setFunction]
     4    [RESET resetFunction]
     5    [NOTIFY notifySignal]
     6    [DESIGNABLE bool]
     7    [SCRIPTABLE bool]
     8    [STORED bool]
     9    [USER bool]
    10    [CONSTANT]
    11    [FINAL])

    下面是一些典型的声明属性的示例:

    1 Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
    2 Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
    3 Q_PROPERTY(QColor barColor READ getBarColor WRITE setBarColor)
    • 一个属性的行为就像类的数据成员,但是它还具有附加的特性,这些特性可以被元数据对象系统操作。这些特性是:
      需要一个READ访问器函数。用于读属性的值。理想情况下,有一个不变的函数用于此目的,并且它必须返回属性的类型的值或指针或引用。例如,QWidget::focus是一个只读的属性,它对应一个读函数:QWidget::hasFocus()。
    • 一个可选的WRITE访问器函数。它用于设置属性的值。它必须返回空并且至少具有一个参数,参数是属性类型的值或指针或引用。例如:QWidget::enabled具有WRITE函数QWidget::setEnable()。只读属性不需要写函数。例如,QWidget::focus没有对应的写函数。
    • 一个可选的RESET函数。用于设置属性的值到它的默认值。例如:QWidget::cursor具有典型的READ和WRITE函数,QWidget::cursor()和QWidget::setCursor(),并且它也具有一个RESET函数,QWidget::unsetCursor()。RESET函数必须返回void并且不带有任何参数。
    • 一个可选的NOTIFY信号。如果被定义了,信号将在属性的值改变时发出。信号必须带有一个参数,这个参数的类型必须与属性相同;参数保存的是属性的新值。
    • 一个DESIGNABLE变量表明此属性是否在界面设计器的属性编辑器中出现。大多数属性是可见的,除了为这个变量传入true或false,你还可以指定一个bool型的成员函数。
    • SCRIPTABLE变量表明这个属性是否可以被一个脚本引擎操作(默认是true)。你也可以赋予它true或false或bool型函数。
    • STORED变量表明了属性是否被认为是独立存在还是依赖于其它的值而存在。它也表明是否在保存对象状态时保存此属性的值。大多数属性都是需要保存的,但是,如QWidget::minimumWidth()就是不被保存的,因为它的值是从另一个属性QWidget::minimumSize()得来的。
    • USER变量表明属性是否被设计为面向用户的或用户可修改的类属性。通常,每个类只有一个USER属性。例如,QAbstractButton::checked是按钮类的用户可修改属性。注意QItemDelegate获取和设置widget的USER属性。
    • CONSTANT的出现表明属性的值是不变的。对于一个object实例,常量属性的READ方法在每次被调用时必须返回相同的值。此常量值可能在不同的object实例中不相同。一个常量属性不能具有WRITE方法或NOYIFY信号。
    • FINAL变量的出现表明属性不能被派生类所重写。有些情况下,这可以用于效率优化,但不是被moc强制的。程序员必须永远注意不能重写一个FINAL属性。

     

    READ,WRITE和RESET函数都可以被继承。它们也可以是虚函数。当它们在被多重继承中被继承时,它们必须出现在第一个被继承的类中。

         属性的类型可以是被QVariant支持的所有类型,也可以是用户定义的类型。在下面的例子中,类QDate被当作用户自定义类型。

    Q_PROPERTY(QDate data READ getDate WRITE setDate)

    因为QDate是用户定义的,你必须包含<QDate>头文件。

        对于QMap,QList和QValueList属性,属性的值是一个QVariant,它包含整个list或map。注意Q_PROPERTY字符串不能包含逗号,因为逗号会划分宏的参数。因此,你必须使用QMap作为属性的类型而不是QMap<QString,QVariant>。为了保持一致性,也需要用QList和QValueList而不是QList<QVariant>和QValueList<QVariant>。

    代码调用的例子:

     1 class Test : public QObject {  
     2   
     3 Q_OBJECT  
     4   
     5 Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)  
     6   
     7 public:  
     8   
     9 Test(QObject *parent = 0) : QObject(parent) {}  
    10   
    11 virtual ~Test(){}  
    12   
    13 void setEnabled(bool e) { enabled = e; }  
    14   
    15 bool isEnabled() const { return enabled; }  
    16   
    17 private:  
    18   
    19 bool enabled;  
    20   
    21 };  

    然后在主函数中添加:

    1 Test *test = new Test;  
    2   
    3 test->setProperty("enabled", true);  
    4   
    5 //test->setEnabled(true);        //ok also work  
    6   
    7 if(test->property("enabled").toBool()) ..... 

    Qt Creator Designer插件的 例子:

     

    头文件中定义了一个minValue 的属性,如下:

     1 class BarRuler : public QWidget
     2 {
     3     Q_OBJECT    
     4     Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
     5 
     6 public:
     7     explicit BarRuler(QWidget *parent = 0);
     8     ~BarRuler();
     9 
    10 private:    
    11     double minValue;
    12 
    13 public:    
    14     double getMinValue()            const;
    15 
    16 public slots:
    17     void setRange(double minValue, double maxValue);
    18 };

    cpp文件实现如下:

     1 #include "barruler.h"
     2 
     3 BarRuler::BarRuler(QWidget *parent) : QWidget(parent)
     4 {    
     5     minValue = 0;
     6 }
     7 
     8 BarRuler::~BarRuler()
     9 {
    10 }
    11 
    12 double BarRuler::getMinValue() const
    13 {
    14     return this->minValue;
    15 }
    16 
    17 void BarRuler::setMinValue(double minValue)
    18 {
    19     this->minValue = minValue;
    20     update();
    21 }

    在设计模式界面调用如下:

     

    1、先拖入一个widget控件

    2、在其上右键选择“提升为”BarRuler

    3、点击属性栏的加号,选择其它类型,如图

    4、类型和名称都要和头文件里定义的相同,如图

    5、在属性栏就会出现对应的动态属性,如图

    6、修改数值,就会改变相对应定义的属性了

  • 相关阅读:
    Python基础(二)之数据类型和运算(6)——元组
    Python基础(二)之数据类型和运算(5)——字符串操作汇总
    Python基础(二)之数据类型和运算(4)—— 列表
    Python基础(二)之数据类型和运算(3)——其他运算算符
    Python 基础(三)——流程控制之break 、continue 、else
    Python 基础(三)之流程控制(3)——for
    Python 基础(三)之流程控制(2)——while
    Python 基础(三)之流程控制(1)——if…else
    python------迭代器与生成器
    Python基础(四)
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13900682.html
Copyright © 2020-2023  润新知