QT属性系统

1 介绍

        Qt中的属性系统是用于为对象添加自定义属性管理这些属性的一种机制。它允许开发者在不修改类定义的情况下,动态地为Qt对象添加新的属性,并且能够对这些属性进行读取设置监听

        属性系统在Qt中是通过Q_PROPERTY宏QObject的元对象系统来实现的。开发者可以通过在QObject派生类中使用Q_PROPERTY宏,将新的属性添加到对象中,并为这些属性定义读取(getter)和设置(setter)方法。

1.1 主要作用总结

        a)自定义属性:通过属性系统,开发者可以向Qt对象中添加自定义的属性,以便存储和访问特定的数据。

        b)属性读写:属性系统允许开发者为属性定义读取和设置方法,使得外部代码可以读取和修改对象的属性值。

        c)属性通知:当属性的值发生变化时,属性系统可以发出信号通知其他代码,从而实现属性的监听和响应。

        d)Qt的元对象系统:属性系统是建立在Qt的元对象系统之上的,这使得属性可以在运行时进行反射操作,比如查询对象的属性列表、获取属性的类型等。

1.2 使用步骤

        步骤1:在QObject派生类中定义属性

        首先,在QObject派生类中使用`Q_PROPERTY`宏来定义属性。`Q_PROPERTY`宏的语法如下:

 Q_PROPERTY(type name
            (READ getFunction [WRITE setFunction] |
             MEMBER memberName [(READ getFunction | WRITE setFunction)])
            [RESET resetFunction]
            [NOTIFY notifySignal]
            [REVISION int | REVISION(int[, int])]
            [DESIGNABLE bool]
            [SCRIPTABLE bool]
            [STORED bool]
            [USER bool]
            [BINDABLE bindableProperty]
            [CONSTANT]
            [FINAL]
            [REQUIRED])

        其中,`type`是属性的数据类型,`name`是属性的名称,`getFunction `是读取属性值的方法,`setFunction`是设置属性值的方法,`notifySignal`是当属性值发生变化时发送的信号。

        例如,定义一个名为`myProperty`的属性,数据类型为`int`:

```cpp
class MyObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int myProperty READ getMyProperty WRITE setMyProperty NOTIFY myPropertyChanged)

public:
    int getMyProperty() const;
    void setMyProperty(int value);

signals:
    void myPropertyChanged();
};
```

        步骤2:实现属性的读取和设置方法

        接下来,在类的实现文件中实现属性的读取和设置方法:

```cpp
int MyObject::getMyProperty() const
{
    return m_myProperty;
}

void MyObject::setMyProperty(int value)
{
    if (m_myProperty != value) {
        m_myProperty = value;
        emit myPropertyChanged();
    }
}
```

        步骤3:连接属性变化信号到槽函数(可选)

        如果希望在属性值发生变化时执行一些操作,可以将属性变化信号连接到槽函数:

```cpp
MyObject obj;
connect(&obj, &MyObject::myPropertyChanged, someSlotFunction);
```

        步骤4:使用属性

```cpp
obj.setMyProperty(42);
int value = obj.getMyProperty();
```

        属性系统提供了可以像操作普通的数据成员一样操作这些自定义属性的方法,同时也可以利用Qt的信号槽系统来监听属性值的变化。这为Qt对象的数据管理提供了一种便捷的方式,并且使得代码更加灵活和可维护。

2 Q_PROPERTY与Meta_Object_system(元对象系统)使用示例

        tperson.h:

#ifndef TPERSON_H
#define TPERSON_H

#include <QObject>

class TPerson : public QObject
{
    Q_OBJECT
    Q_CLASSINFO("author", "luo")
    Q_CLASSINFO("institution", "Foreland")
    Q_CLASSINFO("version", "0.10")

    Q_PROPERTY(int age READ age WRITE setAge NOTIFY ageChanged)
    Q_PROPERTY(QString name MEMBER m_name)
    Q_PROPERTY(int score MEMBER m_score)
public:
    explicit TPerson(QString name, QObject *parent = nullptr);
    ~TPerson();
    int age();//输出年龄的函数
    void setAge(quint8 age);//设置年龄
    void increaseAge();  //增加年龄
signals:
    void ageChanged(int ageValue);
private:
    QString m_name;
    int m_age=10;
    int m_score=79;
};

#endif // TPERSON_H

        tperson.cpp:

#include "tperson.h"

TPerson::TPerson(QString name, QObject *parent)
    :QObject{parent}, m_name{name}
{
//    this->m_name = name;
}

TPerson::~TPerson()
{
    qDebug("TPerson对象被删除");
}

int TPerson::age()
{
    return m_age;
}

void TPerson::setAge(quint8 ageValue)
{
    if(ageValue != m_age){
        m_age = ageValue;
        emit ageChanged(m_age);
    }

}

void TPerson::increaseAge()
{
    ++m_age;
    emit this->ageChanged(m_age);
}

       widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "tperson.h"
#include <QMetaProperty>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    TPerson *boy;
    TPerson *girl;
private slots:
    void do_ageChanged(int value);
    void do_spinChanged(int arg1);
    void on_growAYearBoy_clicked();
    void on_growAYearGirl_clicked();
    void on_pushButton_4_clicked();
    void on_showMetaInfo_clicked();
    void on_showMetaInfoGirl_clicked();
};
#endif // WIDGET_H

        widget.cpp:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    boy = new TPerson("傲天",this);
    girl = new TPerson("夙玉",this);
    //动态属性定义
    boy->setProperty("sex", "boy");
    girl->setProperty("sex", "girl");

    boy->setAge(15);
    girl->setAge(20);


    ui->spinBoxBoy->setProperty("isBoy", true);
    ui->spinBoxGirl->setProperty("isBoy", false);


    connect(boy, SIGNAL(ageChanged(int)), ui->spinBoxBoy, SLOT(setValue(int)));
    connect(girl, SIGNAL(ageChanged(int)), ui->spinBoxGirl, SLOT(setValue(int)));
    connect(boy, SIGNAL(ageChanged(int)), this, SLOT(do_ageChanged(int)));
    connect(girl, SIGNAL(ageChanged(int)), this, SLOT(do_ageChanged(int)));

    connect(ui->spinBoxBoy, SIGNAL(valueChanged(int)), this, SLOT(do_spinChanged(int)));
    connect(ui->spinBoxGirl, SIGNAL(valueChanged(int)), this, SLOT(do_spinChanged(int)));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::do_ageChanged(int value)
{
    //先用sender查看信号的发送者
    TPerson *person = qobject_cast<TPerson *>(sender());
    //获取年龄并打印到ptext中
    QString str = QString("name:%1,sex=%2,年龄=%3")
            .arg(person->property("name").toString())
            .arg(person->property("sex").toString())
            .arg(value);
    ui->plainTextEdit->appendPlainText(str);
}

void Widget::do_spinChanged(int arg1)
{
//    Q_UNUSED(arg1)
    QSpinBox *spBox = qobject_cast<QSpinBox*>(sender());//这里的sender指信号的发送者,在connect函数中,sender肯定是一个QSpinBox对象
    if(spBox->property("isBoy").toBool())
        boy->setAge(arg1);
    else
        girl->setAge(arg1);
}


void Widget::on_growAYearBoy_clicked()
{
    boy->increaseAge();
}


void Widget::on_growAYearGirl_clicked()
{
    girl->increaseAge();
}


void Widget::on_pushButton_4_clicked()
{
    ui->plainTextEdit->clear();
}


void Widget::on_showMetaInfo_clicked()
{
    const QMetaObject *meta = boy->metaObject();
    ui->plainTextEdit->appendPlainText(QString("类名称:%1\n").arg(meta->className()));

    ui->plainTextEdit->appendPlainText("属性:");
    for(int i=meta->propertyOffset();i<meta->propertyCount();i++)
    {
        const char* propName = meta->property(i).name();
        QString propValue = boy->property(propName).toString();
        ui->plainTextEdit->appendPlainText(QString("属性名称=%1,属性值=%2").arg(propName).arg(propValue));
    }

    ui->plainTextEdit->appendPlainText("\n类信息(classInfo):");
    for(int i=meta->classInfoOffset();i<meta->classInfoCount();i++)
    {
        QMetaClassInfo classInfo = meta->classInfo(i);
        ui->plainTextEdit->appendPlainText(
                    QString("Name=%1,Value=%2").arg(classInfo.name()).arg(classInfo.value()));
    }
}


void Widget::on_showMetaInfoGirl_clicked()
{
    const QMetaObject *meta = girl->metaObject();
    ui->plainTextEdit->appendPlainText(QString("类名称:%1\n").arg(meta->className()));

    ui->plainTextEdit->appendPlainText("属性:");
    for(int i=meta->propertyOffset();i<meta->propertyCount();i++)
    {
        const char* propName = meta->property(i).name();
        QString propValue = girl->property(propName).toString();
        ui->plainTextEdit->appendPlainText(QString("属性名称=%1,属性值=%2").arg(propName).arg(propValue));
    }

    ui->plainTextEdit->appendPlainText("\n类信息(classInfo):");
    for(int i=meta->classInfoOffset();i<meta->classInfoCount();i++)
    {
        QMetaClassInfo classInfo = meta->classInfo(i);
        ui->plainTextEdit->appendPlainText(
                    QString("Name=%1,Value=%2").arg(classInfo.name()).arg(classInfo.value()));
    }
}

        界面展示:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值