• QT—动态属性系统


    目录

    一、创建动态属性

    二、Q_PROPERTY宏参数类型 

    三、演示

    四、通过基类读写动态属性 

    1.读属性

    2.改属性 


    一、创建动态属性

        在标准C++中,为了保证封装性,我们经常声明一个私有变量,然后声明两个公有函数,即set函数和get函数。在Qt中我们可以使用宏Q_PROPERTY()宏来实现这些。一个属性可以使用常规函数QObject::property()和QObject::setProperty()进行读写,不用知道属性所在类的任何细节,除了属性的名字。 

        Q_PROPERTY()原型: 

    1. // 中括号中的内容为可选项
    2. Q_PROPERTY(        
    3. type name            //属性的类型 名字
    4. (READ getFunction [WRITE setFunction] | MEMBER memberName [(READ getFunction |WRITE setFunction)])
    5. [RESET resetFunction]
    6. [NOTIFY notifySignal]    //通知的信号名
    7. [REVISION int]        //版本号
    8. [DESIGNABLE bool]      //当前该属性可不可以在设计模式设置
    9. [SCRIPTABLE bool]      //可以不可以被脚本访问
    10. [STORED bool]         //属性值是否存储
    11. [USER bool]          //是否提供给用户编辑权限
    12. [CONSTANT]          //常量
    13. [FINAL]            //不能被重写      
    14. )

    二、Q_PROPERTY宏参数类型 

    1. type name 

    属性类型可以是QVariant支持的任何类型,也可以是用户定义的类型;

    2. READ 和 MEMBER
    如果没有MEMBER,则必须要有READ。
    READ 后面定义获取属性值的函数,该函数是const;
    WRITE 设置属性值,是可选的;
    MEMBER 如果一个属性不需要 READ ,但又想使用属性系统,可以使用MEMBER来注册,MEMBER后面是成员变量的名字;

    3. RESET

    可选,将属性设置为默认值,该RESET函数必须返回void并且不带参数。

    4. NOTIFY

    可选,NOTIFY 后面跟该类中已经定义的一个信号函数,只要该属性的值发生更改,就会发出该信号。这个信号函数必须采用零个或一个参数,该参数必须与属性的类型相同。

    5. REVISION int
    可选,版本信息(通常用于QML)。

    6. DESIGNABLE bool
    可选,表示属性是否能在GUI设计工具的属性编辑器中可见(例如,Qt Designer)。大多数属性是DESIGNABLE(默认为true)。

    7. SCRIPTABLE bool
    可选,SCRIPTABLE属性表示脚本引擎是否应该可以访问此属性(默认为true)

    8. STORED bool
    可选,该属性是单独存在还是从其他值中获取的。大部分是true,一个反例是QWidget::minimumWidth()的值从QWidget::minimumSize()中获取,因此它的STORED为false。

    9. USER bool
    可选,表示是否可以被用户所编辑。

    10. CONSTANT
    可选,CONSTANT表明属性值是常量,不可更改,因此不能有WRITE方法或NOTIFY信号。对于给定的对象实例,常量属性的READ方法每次调用时都必须返回相同的值。对于对象的不同实例,该常数值可以是不同的。

    11. FINAL
    可选,FINAL表示属性不会被派生类覆盖,在某些情况下,这可用于性能优化。

    三、演示

    示例: 

    1.新建桌面应用程序Widget,新建一个C++类MyPropertyClass,并声明Q_PROPERTY宏

    1. #include
    2. class MyPropertyClass : public QObject
    3. {
    4. Q_OBJECT
    5. //声明1_PROPERTY宏
    6. Q_PROPERTY(QString mask READ mask WRITE setMask NOTIFY maskChanged)
    7. public:
    8. explicit MyPropertyClass(QObject *parent = nullptr);
    9. //只读
    10. QString mask() const;
    11. //只写
    12. void setMask(QString strMaskNum);
    13. signals:
    14. void maskChanged(QString strMaskNum);
    15. private:
    16. //用来保存mask的值
    17. QString m_mask;
    18. };

    读写函数的实现:

    1. QString MyPropertyClass::mask() const
    2. {
    3. return m_mask;
    4. }
    5. void MyPropertyClass::setMask(QString strMaskNum)
    6. {
    7. m_mask=strMaskNum;
    8. emit maskChanged(strMaskNum);
    9. }

    4.在widget.h中声明一个槽方法

    1. public slots:
    2. void maskChanged(QString str); //槽方法与信号保持一致

    槽方法实现 

    1. void Widget::maskChanged(QString str)
    2. {
    3. qDebug()<<"新的值为:"<
    4. }

    在Widget.cpp文件中,在构造函数里将槽方法与MyPropertyClass类的动态属性的信号连接,并动态属性赋值

    1. Widget::Widget(QWidget *parent) :
    2. QWidget(parent),
    3. ui(new Ui::Widget)
    4. {
    5. ui->setupUi(this);
    6. MyPropertyClass *myPc=new MyPropertyClass;
    7. connect(myPc,SIGNAL(maskChanged(QString)),this,SLOT(maskChanged(QString)));
    8. myPc->setMask("1000个");
    9. }

    执行结果:

    四、通过基类读写动态属性 

    1.读属性

     调用动态属性写函数将属性赋值为“1000个”,属性值被更改就会发送了maskChanged信号,我们又在Widget程序中将一个槽方法与该信号连接,在槽方法中输出修改的属性值。

    也可以使用父类的property和setproperty方法获取修改属性值

    1. Widget::Widget(QWidget *parent) :
    2. QWidget(parent),
    3. ui(new Ui::Widget)
    4. {
    5. ui->setupUi(this);
    6. MyPropertyClass* mypC=new MyPropertyClass;
    7. mypC->setMask("10000个口罩");//调用写方法
    8. //通过基类查看动态属性值
    9. QObject*obj=mypC;
    10. qDebug()<<"QObject读取的属性值"<property("mask").toString()
    11. }

    执行结果

    2.改属性 

    1. Widget::Widget(QWidget *parent) :
    2. QWidget(parent),
    3. ui(new Ui::Widget)
    4. {
    5. ui->setupUi(this);
    6. MyPropertyClass *myPc=new MyPropertyClass;
    7. connect(myPc,SIGNAL(maskChanged(QString)),this,SLOT(maskChanged(QString)));
    8. myPc->setMask("1000个");
    9. QObject *obj=myPc;
    10. //父类调用property读属性
    11. qDebug()<<"obj读属性:"<property("mask").toString();
    12. //父类调用setProperty修改属性
    13. obj->setProperty("mask","2000个");
    14. qDebug()<<"obj读取修改后属性:"<property("mask").toString();
    15. }

     执行结果:

    动态属性系统优点在于其继承自QObject,我们只需要一个QObject和子类的类名,便可以操作不同类的动态属性 

  • 相关阅读:
    AI实战 | 手把手带你打造校园生活助手
    vue中通过js控制scss变量
    《 机器人基础 》期末试卷(A)
    【如何看待Unity收费】对标中小公司的待就业者的该如何做
    Jenkins自动化部署前后端分离项目 (svn + Springboot + Vue + maven)有图详解
    docker的简单操作
    English语法_不定代词 -some & any
    04、GO模块与包、结构体
    AWS China Elastic Beanstalk 填坑记(Python Flask)
    重学设计模式之 装饰者模式
  • 原文地址:https://blog.csdn.net/qq_54169998/article/details/126016501