第三代软件开发-Qt属性系统
文章目录
关键字: Qt
、 Qml
、 Q_PROPERTY
、 setProperty
、 属性
项目介绍
欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。
在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。
在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资源消耗,以确保我们的项目在各种平台和设备上都能够高效运行。
无论您是对 QML 和 C++ 开发感兴趣,还是需要我们为您构建复杂的用户界面和后端逻辑,我们都随时准备为您提供支持。请随时联系我们,让我们一同打造现代化、高性能的 QML & C++ 项目!
重要说明☝
☀该专栏在第三代软开发更新完将涨价
Qt属性系统
其实Qt 属性系统 我也是第一次在项目中大量的成系统的使用,要说元对象系统,那我们都是知道是Qt的根基,但是这个Qt 属性系统我也不知道该如何形容,我用下的感觉总结就是如果是纯QWidget系列代码,那不如不用,如果是和Qml一起使用,真香。
Qt 的属性系统是一种机制,用于在 Qt 对象中定义、访问和管理属性。它提供了一种方便的方式来定义对象的属性,并允许通过属性名称进行访问、修改和监视。
以下是 Qt 属性系统的详细介绍:
属性(Properties):
- 属性是 Qt 对象的特征或状态,可以是任何数据类型,例如整数、字符串等。
- 属性可以通过
Q_PROPERTY
宏在类的头文件中进行定义。访问器函数(Accessor Functions):
- 对于每个属性,Qt 提供了自动生成的访问器函数,用于获取和设置属性的值。
- 访问器函数遵循命名约定:
propertyName()
用于获取属性值,setPropertyName(value)
用于设置属性值。反射(Reflection):
- Qt 属性系统基于反射机制,允许在运行时获取和操作对象的属性信息。
- 可以使用
QObject::metaObject()
函数获取对象的元对象(QMetaObject),然后使用元对象的方法来访问属性。元对象系统(Meta-Object System):
- 元对象系统是 Qt 的核心部分,用于支持属性系统、信号与槽等功能。
- QMetaObject 是一个描述对象的结构和行为的元对象,包括属性、方法、信号和槽等。
动态属性(Dynamic Properties):
- Qt 的属性系统还支持动态属性,允许在运行时为对象添加新的属性。
- 可以使用
QObject::setProperty(propertyName, value)
方法来设置动态属性,使用QObject::property(propertyName)
方法来获取动态属性值。信号与槽(Signals and Slots):
- 属性系统与信号与槽机制密切相关。当属性的值发生变化时,可以使用信号和槽来通知其他部分进行相应的处理。
- 可以通过属性的
notify
信号来触发属性值变化的通知。总结:Qt 的属性系统提供了一种方便而强大的方式来管理对象的属性。它支持静态属性和动态属性,并与元对象系统、反射和信号与槽机制紧密集成,使得开发者可以轻松地定义、访问和操作对象的属性。
目的
最近越写越迷茫了,就Qt 的属性系统而言,目前仅仅是会用,但是真的很想知道当初Qt 设计这个东西的初衷是什么,是为了C++与 Qml 交互的方便吗?带着这个问题找了百度,也找了Google,终究大家都是清一色如何使用,却没有一个人说说的他的由来,所以以下是GPT 给出的答案
问:开发 Qt 属性系统的目的是什么
答:Qt 属性系统的目的是为了提供一种方便和灵活地管理对象属性的方式。它允许开发人员在 Qt 应用程序中定义和操作对象的属性,包括读取、写入、通知、验证以及与其他属性之间建立关联等操作。
以下是开发 Qt 属性系统的一些主要目的:
简化属性管理:Qt 属性系统使开发人员能够以一致的方式管理对象的属性。通过使用属性系统,可以将属性的读取、写入和通知功能集成到对象中,而不需要手动编写大量的代码。
支持元对象系统:属性系统与 Qt 的元对象系统紧密集成。这意味着属性可以在运行时通过名称进行访问,并且支持信号和槽机制。
可扩展性:Qt 属性系统是可扩展的,开发人员可以根据自己的需求定义自定义属性类型。这使得开发人员能够创建适合特定应用程序需求的灵活的属性。
与界面框架的集成:Qt 属性系统与 Qt 的界面框架(如 Qt Widgets 和 Qt Quick)无缝集成。这意味着可以轻松地将属性与用户界面元素绑定,实现属性值的即时更新和交互。
总的来说,Qt 属性系统旨在提供一种简单、灵活和可扩展的方式来管理对象的属性,从而帮助开发人员更高效地构建 Qt 应用程序。
属性与类成员
我特意去帮助文档搜索了Q_PROPERTY
,它是这么描述的
This macro is used for declaring properties in classes that inherit QObject. Properties behave like class data members, but they have additional features accessible through the Meta-Object System.
该宏用于声明继承 QObject 的类中的属性。 属性的行为类似于类数据成员,但它们具有可通过元对象系统访问的附加功能。
所以我理解看来,我可以把属性当做类成员,但是不能类成员当做属性。是可以这么理解吧。
使用
这个就是网上清一色的内容,这里咱们搬运一下大佬一去、二三里的博客内容
https://blog.csdn.net/liang19890820/article/details/52022714
声明属性的要求
要声明一个属性,在继承QObject的类中使用Q_PROPERTY()宏。
C++
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
MEMBER memberName [(READ getFunction | WRITE setFunction)])
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
下面的示例,展示了如何使用MEMBER关键字将类成员变量导出为Qt属性。注意:NOTIFY信号必须被指定,这样才能被QML使用。(我使用的是经典的那种)
C++
Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged)
Q_PROPERTY(qreal spacing MEMBER m_spacing NOTIFY spacingChanged)
Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged)
...
signals:
void colorChanged();
void spacingChanged();
void textChanged(const QString &newText);
private:
QColor m_color;
qreal m_spacing;
QString m_text;
一个属性的行为就像一个类的数据成员,但它有通过元对象系统访问的附加功能。
如果MEMBER关键字没有被指定,则一个READ访问函数是必须的。它被用来读取属性值。理想的情况下,一个const函数用于此目的,并且它必须返回的是属性类型或const引用。比如:QWidget::focus是一个只读属性,通过READ函数QWidget::hasFocus()访问。
一个WRITE访问函数是可选的,用于设置属性的值。它必须返回void并且只能接受一个参数,属性的类型是类型指针或引用,例如:QWidget::enabled具有WRITE函数QWidget::setEnabled()。只读属性不需要WRITE函数,例如:QWidget::focus没有WRITE函数。
如果READ访问函数没有被指定,则MEMBER变量关联是必须的。这使得给定的成员变量可读和可写,而不需要创建READ和WRITE访问函数。如果需要控制变量访问,仍然可以使用READ和WRITE函数而不仅仅是MEMBER(但别同时使用)。
一个RESET函数是可选的,用于将属性设置为上下文指定的默认值。例如:QWidget::cursor有READ和WRITE函数QWidget::cursor()和QWidget::setCursor(),同时也有一个RESET函数QWidget::unsetCursor(),因为没有可用的QWidget::setCursor()调用可以确定的将cursor属性重置为上下文默认的值。RESET函数必须返回void类型,并且不带任何参数。
一个NOTIFY信号是可选的。如果定义了NOTIFY,则需要在类中指定一个已存在的信号,该信号在属性值发生改变时发射。与MEMBER变量相关的NOTIFY信号必须有零个或一个参数,而且必须与属性的类型相同。参数保存的是属性的新值。NOTIFY信号应该仅当属性值真正的发生变化时发射,以避免被QML重新评估。例如:当需要一个没有显式setter的MEMBER属性时,Qt会自动发射信号。
一个REVISION数字是可选的。如果包含了该关键字,它定义了属性并且通知信号被特定版本的API使用(通常是QML);如果没有包含,它默认为0。
DESIGNABLE属性指定了该属性在GUI设计器(例如:Qt Designer)里的编辑器中是否可见。大多数的属性是DESIGNABLE (默认为true)。除了true或false,你还可以指定boolean成员函数。
SCRIPTABLE属性表明这个属性是否可以被一个脚本引擎操作(默认是true)。除了true或false,你还可以指定boolean成员函数。
STORED属性表明了该属性是否是独立存在的还是依赖于其它属性。它也表明在保存对象状态时,是否必须保存此属性的值。大多数属性是STORED(默认为true)。但是例如:QWidget::minmunWidth()的STROED为false,因为它的值从QWidget::minimumSize()(类型为QSize)中的width部分取得。
USER属性指定了属性是否被设计为用户可见和可编辑的。通常情况下,每一个类只有一个USER属性(默认为false)。例如: QAbstractButton::checked是(checkable)buttons的用户可修改属性。注意:QItemDelegate获取和设置widget的USER属性。
CONSTANT属性的出现表明属性是一个常量值。对于给定的object实例,常量属性的READ函数在每次被调用时必须返回相同的值。对于不同的object实例该常量值可能会不同。一个常量属性不能具有WRITE函数或NOYIFY信号。
FINAL属性的出现表明属性不能被派生类所重写。有些情况下,这可以用于效率优化,但不能被moc强制执行。必须注意不能覆盖一个FINAL属性。
动态属性
这部分我还没有实际使用到,或者是没有大量使用,没有啥感觉,我们还是搬运一下大佬的内容,以及是上方链接
QObject::setProperty()也可以用来在运行时期向一个类的实例添加新的属性。当使用一个名字和值调用它时,如果QObject中一个指定名称的属性已经存在,并且如果给定的值与属性的类型兼容,那么,值就被存储到属性中,然后返回true。如果值与属性类型不兼容,属性的值就不会发生改变,会返回false。但是如果QObject中一个指定名称的属性不存在(例如:未用Q_PROPERTY()声明),一个带有指定名称和值的新属性就被自动添加到QObject中,但是依然会返回false。这意味着返回值不能用于确定一个属性是否被设置值,除非事先知道这个属性已经存在于QObject中。
注意:态属性被添加到每一个实例中,即:它们被添加到QObject中,而不是QMetaObject。一个属性可以从一个实例中删除,通过传入属性名和非法的QVariant值给QObject::setProperty()。默认的QVariant构造器会构造一个非法的QVariant。
动态属性可用QObject::property()来查询,就像使用Q_PROPERTY()声明的属性一样。
属性和自定义类型
被属性使用的自定义类型需要使用Q_DECLARE_METATYPE()宏注册,以便它们的值能被保存在QVariant对象中。这使得它们适用于在类定义时使用Q_PROPERTY()宏声明的静态属性,以及运行时创建的动态属性。
总结一下
额 说实话,目前还是云里雾里的,目前我能力也只能到这个地步,后期如果对Qt 属性系统有了新的理解,咱们再开一篇。这篇先这样