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的强大功能,实现更高效的开发、更清晰的代码结构和更灵活的应用程序行为。