Qt属性系统-Property

时间:2025-03-26 07:01:50

Qt属性系统-Property

1. Q_PROPERTY的概念

  Q_PROPERTY是Qt中的一个宏,用于在类中声明属性,使这些属性可以在QML中使用。它基于Qt的元对象系统,提供了信号槽机制,用于对象间通信。Q_PROPERTY的主要作用是将类的成员变量或成员函数与属性关联起来,从而实现属性的自动化处理,如绑定、序列化和动态属性设置。(我们本次不讲QML,所以会忽略QML的使用部分)

2. Q_PROPERTY的语法和使用

Q_PROPERTY的基本语法如下:

Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
  • type:属性的数据类型。
  • name:属性的名称。
  • READ getFunction:用于读取属性值的成员函数。
  • WRITE setFunction:用于写入属性值的成员函数(可选)。
  • RESET resetFunction:用于重置属性值的成员函数(可选)。
  • NOTIFY notifySignal:属性值改变时发出的信号(可选)。
  • REVISION int:属性的版本号(可选)。
  • DESIGNABLE bool:属性是否在Qt设计器中可见(可选)。
  • SCRIPTABLE bool:属性是否可以在Qt脚本中使用(可选)。
  • STORED bool:属性是否应该被存储(可选)。
  • USER bool:是否是用户属性(可选)。
  • CONSTANT:属性值是否恒定不变(可选)。
  • FINAL:属性是否是最终属性,不能被子类重写(可选)

3. Property相关函数

bool QObject::setProperty(const char* name, const QVariant& value);
QVariant QObject::property(const char* name) const;

  setProperty 该函数用于设置类的属性,其中name参数为属性名称,value表示属性值,当name属性存在且设置成功时,返回为true,否则返回为false,若name属性不存在,函数会为对象创建一个动态属性,且返回false,动态属性是在运行时定义的,它只属于正在运行的类的实例;propert 函数为返回属性值,name参数为属性名称;

4. 属性程序示例

// .h
#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ GetName WRITE SetName NOTIFY SignalNameChanged)
    Q_PROPERTY(int age READ GetAge WRITE SetAge NOTIFY SignalAgeChanged)

public:
    explicit Student(QObject *parent = nullptr);
    ~Student() = default;

public:
    void SetName(QString strName);
    QString GetName();

    void SetAge(int nAge);
    int GetAge();


public slots:
    void SlotNameChanged(QString strName);
    void SlotAgeChanged(int nAge);

signals:
    void SignalNameChanged(QString);
    void SignalAgeChanged(int);

private:
    QString m_strName;
    int m_nAge;
};

#endif // STUDENT_H

// .cpp
#include "Student.h"
#include <QDebug>

Student::Student(QObject *parent) : QObject(parent), m_nAge(15)
{

}

void Student::SetName(QString strName)
{
    m_strName = strName;
    emit SignalNameChanged(strName);
}

QString Student::GetName()
{
    return m_strName;
}

void Student::SetAge(int nAge)
{
    m_nAge = nAge;
    emit SignalAgeChanged(nAge);
}

int Student::GetAge()
{
    return m_nAge;
}

void Student::SlotNameChanged(QString strName)
{
    qDebug() << "Name changed = " << strName;
}

void Student::SlotAgeChanged(int nAge)
{
    qDebug() << "Age changed = " << nAge;
}

// 类属性测试
void TestProperty()
{
    Student stu;
    QObject::connect(&stu, &Student::SignalNameChanged, &stu, &Student::SlotNameChanged);

    // 下面两行代码的操作意义一样,都能达到设置 Student 成员变量 m_strName 的效果
    stu.SetName(QString("zhangsan"));
    bool bRtn = stu.setProperty("name", QString("Zhangsan"));       // 也会调用 Student 的 SetName 成员函数

    // 下面两行代码的操作意义一样,都能达到获取 Student 成员变量 m_strName 的值的效果
    QString strName = stu.property("name").toString();
    strName = stu.GetName();

    // 动态属性是在运行时定义的,它只属于正在运行的类的实例
    // 动态设置属性,该属性本身不存在, 此时返回值为 false
    bRtn = stu.setProperty("height", 180);
    int nHeight = stu.property("height").toInt();
}

代码解析:

Q_PROPERTY(QString name READ GetName WRITE SetName NOTIFY SignalNameChanged)
Q_PROPERTY(int age READ GetAge WRITE SetAge NOTIFY SignalAgeChanged)

上述两行代码定义了 Student 类的两个属性:name, age

stu.SetName(QString("zhangsan"));
bool bRtn = stu.setProperty("name", QString("Zhangsan"));

上面两行代码的操作意义一样,都能达到设置 Student 成员变量 m_strName 的效果,调用 stu.setProperty(“name”, QString(“Zhangsan”)) 时也会调用 Student 的 SetName 成员函数,因为name属性是存在的,所以 bRtn 的值会为 true;

QString strName = stu.property("name").toString();
strName = stu.GetName();

上面两行代码的操作意义一样,都能达到获取 Student 成员变量 m_strName 的值的效果;

bRtn = stu.setProperty("height", 180);
int nHeight = stu.property("height").toInt();

上述动态属性是在运行时定义的,它只属于正在运行的类的实例,动态设置属性,该属性本身不存在, 此时返回值为 false,所以 bRtn 值会为 false;

5. 总结

Q_PROPERTY在Qt中有多种重要用途:

  • 属性绑定:在QML和Qt Quick中,使用Q_PROPERTY声明的属性可以实现属性绑定,即当属性值改变时,相关联的UI元素会自动更新;
  • 序列化:Q_PROPERTY使得属性可以通过Qt的元对象系统进行序列化和反序列化,便于保存和加载对象的状态;
  • 动态属性设置:可以在运行时动态地设置和获取属性值,提高了程序的灵活性和动态性;

通过使用Q_PROPERTY,可以充分利用Qt的强大功能,实现更高效的开发、更清晰的代码结构和更灵活的应用程序行为。