简单介绍Qt的属性子系统

深入理解Qt的属性系统

​ 笔者最近正在大规模的开发Qt的项目和工程,这里笔者需要指出的是,这个玩意在最常规的Qt开发中是相对比较少用的,笔者也只是在Qt的QPropertyAnimation需要动画感知笔者设置的一个属性的时候方才知道这个东西的。因此,这篇文章的属性更加象是整合和消化,请各位Qt大佬批评指正。

先说说Qt的属性系统可以做啥

​ 我不想一上来就扔出来一大堆概念和写法,这没意思,看着啥也看不懂就来整一处,只会把人吓跑。

更加高级的和封闭的属性读写机制(C++的反射和动态属性)

​ 在纯 C++ 环境下,通过 QObject::setProperty 和 QObject::property,开发者可以在不知道具体类定义的情况下,以字符串形式读写对象属性,从而实现对第三方或未知类型对象的动态操作,这在插件系统或运行时配置中尤为有用。如果需要在不同线程之间安全地调用方法,也可以借助 QMetaObject::invokeMethod 配合 Qt::QueuedConnection,将对属性的修改或方法调用排入目标线程的事件队列,从而避免手动管理互斥锁和死锁风险。这个就是把对对象属性的修改扔到巨大的事件循环队列中,事件循环队列是保证我们的数据读写不会发生争夺,必须按照顺序一个个执行的。

UI 自动化与 Qt Designer 集成

​ Qt Designer 以及 Qt Quick Designer 均依赖元对象系统和属性系统来生成可视化属性面板。无论是 QWidget 还是 QML 项目,当在设计器中选中控件时,右侧属性编辑器都会列出该控件所有可设计属性,包括可脚本化(SCRIPTABLE)和可存储(STORED)的属性,通过动态读取 QMetaObject 数据实现即时更新和回显,这为界面原型设计和主题定制提供了极大便利。这个事情在笔者之后体验如何自己制作自己的插件的时候会进行尝试。

QML 中的数据绑定与模型驱动(这个没做过,gpt这样说的)

在 QML 层面,属性系统是响应式界面的基石。将 C++ 对象通过 QQmlContext 或 qmlRegisterType 暴露给 QML 时,凡是使用 Q_PROPERTY 宏声明并带有 NOTIFY 信号的属性,都可以在 QML 中像普通属性一样使用绑定表达式。当模型层的属性在 C++ 侧被修改时,对应的 QML 界面会自动更新,无需手动编写额外的同步代码,这使得使用 Qt Quick 构建数据驱动型界面变得直观而高效。即便是在复杂的逻辑场景下,QML 引擎也会跟踪属性的依赖关系,在底层的 BindingEvaluator 中智能地避免多余的计算与重绘,从而兼顾性能和开发效率

动画、状态机与属性驱动

Qt 的动画框架广泛使用属性系统来驱动动画效果。QPropertyAnimation 类通过属性名称来获取和设置目标对象的属性值,并在不同时间点上插值更新,例如对 QWidget 的 geometry、opacity 或自定义属性进行平滑过渡;在状态机(QStateMachine)中,也可以使用属性动作(QPropertyAction)根据状态切换自动修改属性,从而将动画与状态逻辑解耦,简化状态驱动的界面行为实现。这个在笔者自己手搓网易云的动画效果的时候又遇到过,笔者会在那里详细的说明这个用途

非常心动,所以咋玩

​ 很正常的想法!这个属性非常的有趣,所以我们需要怎么做呢?答案是下面的:

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])

​ 注意,这些代码实际上啥也不会留下,他是给我们的MOC提供信息用的。告诉我们这个属性的性质,名称,如何读写等等方法。举个例子:

Q_PROPERTY(bool focus READ hasFocus)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)

​ 依次说明了如下的基本事实:

1. Q_PROPERTY(bool focus READ hasFocus)

声明了一个名为 focus 的布尔类型属性:

  • READ:通过 hasFocus() 方法读取属性值(无写入功能)。
  • 用途:通常表示控件是否获得键盘焦点(如输入框被选中时)。
  • 特点:这是一个只读属性,无法直接修改(没有 WRITEMEMBER 标记)。

2. Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)

声明了一个名为 enabled 的布尔类型属性:

  • READ:通过 isEnabled() 方法读取属性值。
  • WRITE:通过 setEnabled(bool) 方法修改属性值。
  • 用途:控制控件是否启用(禁用时通常变灰且不响应用户输入)。
  • 特点:支持读写,修改时会自动触发 Qt 的属性系统通知(如信号或样式更新)。

3. Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)

声明了一个名为 cursorQCursor 类型属性:

  • READ:通过 cursor() 方法获取当前光标样式。
  • WRITE:通过 setCursor(QCursor) 方法设置光标样式(如鼠标悬停时变为手型)。
  • RESET:通过 unsetCursor() 方法恢复默认光标(移除自定义设置)。
  • 用途:动态改变控件的光标外观。
  • 特点:支持读、写和重置操作,灵活性更高。
#include <QObject>
class Person : public QObject
{Q_OBJECTQ_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:explicit Person(QObject *parent = nullptr) : QObject(parent) {}QString name() const { return m_name; }void setName(const QString &name) {if (m_name != name) {m_name = name;emit nameChanged();}}
signals:void nameChanged();
private:QString m_name;
};// 在某处使用
Person p;
p.setProperty("name", "Alice");
QString current = p.property("name").toString();

​ 当然,这样我们就完成了一次对属性的读写。这个的好处其实跟正常的get set接口类似,但是多了Qt上的很多元对象支持,就是我刚刚提到的那些。

附录:属性文档

  • 如果未指定 MEMBER 变量,则需要一个 READ 访问器函数。该函数用于读取属性值。理想情况下,使用 const 函数来实现此目的,并且它必须返回属性的类型或该类型的 const 引用。例如,QWidget::focus 是一个只读属性,其 READ 函数为 QWidget::hasFocus()。如果指定了 BINDABLE 变量,则可以编写 READ default 来从 BINDABLE 变量生成 READ 访问器。
  • WRITE 访问器函数是可选的。它用于设置属性值。它必须返回 void,并且必须只接受一个参数,该参数可以是属性的类型、指向该类型的指针或引用。例如,QWidget::enabled 具有 WRITE 函数 QWidget::setEnabled()。只读属性不需要 WRITE 函数。例如,QWidget::focus 没有 WRITE 函数。如果您同时指定了 BINDABLE 和 WRITE 的默认值,则系统会从 BINDABLE 生成一个 WRITE 访问器。生成的 WRITE 访问器不会显式发出任何使用 NOTIFY 声明的信号。您应该将该信号注册为 BINDABLE 的变更处理程序,例如使用 Q_OBJECT_BINDABLE_PROPERTY。
  • 如果没有指定 READ 访问器函数,则需要 MEMBER 变量关联。这使得给定的成员变量无需创建 READ 和 WRITE 访问器函数即可读写。如果您需要控制变量访问,除了 MEMBER 变量关联之外,仍然可以使用 READ 或 WRITE 访问器函数(但不能同时使用)。
  • RESET 函数是可选的。它用于将属性设置回其上下文相关的默认值。例如,QWidget::cursor 具有典型的 READ 和 WRITE 函数,即 QWidget::cursor() 和 QWidget::setCursor(),此外它还具有 RESET 函数,即 QWidget::unsetCursor(),因为任何对 QWidget::setCursor() 的调用都不能重置为上下文特定的游标。RESET 函数必须返回 void 且不接受任何参数。
  • NOTIFY 信号是可选的。如果定义,则应指定该类中一个现有的信号,该信号在属性值发生变化时发出。MEMBER 变量的 NOTIFY 信号必须接受零个或一个参数,并且该参数必须与属性的类型相同。该参数将采用属性的新值。NOTIFY 信号应仅在属性确实发生更改时发出,以避免在 QML 中不必要地重新评估绑定。当通过 Qt API(QObject::setProperty、QMetaProperty 等)更改属性时,会自动发出信号,但直接更改 MEMBER 时则不会发出信号。
  • REVISION 编号或 REVISION() 宏是可选的。如果包含,则它定义了在特定 API 版本(通常用于暴露给 QML)中使用的属性及其通知信号。如果不包含,则默认为 0。
  • DESIGNABLE 属性指示该属性是否应在 GUI 设计工具(例如 Qt Widgets Designer)的属性编辑器中可见。大多数属性都是 DESIGNABLE(默认为 true)。有效值为 true 和 false。
  • SCRIPTABLE 属性指示此属性是否应由脚本引擎访问(默认为 true)。有效值为 true 和 false。
  • STORED 属性指示应将属性视为独立存在还是依赖于其他值。它还指示在存储对象状态时是否必须保存属性值。大多数属性都是 STORED 属性(默认为 true),但例如 QWidget::minimumWidth() 的 STORED 属性为 false,因为它的值取自 QWidget::minimumSize() 属性的宽度部分,而该属性的类型为 QSize。
  • USER 属性指示该属性是被指定为面向用户的属性还是用户可编辑的属性。通常,每个类只有一个 USER 属性(默认为 false)。例如,QAbstractButton::checked 是(可勾选的)按钮的用户可编辑属性。请注意,QItemDelegate 可以获取和设置小部件的 USER 属性。
  • BINDABLE bindableProperty 属性指示该属性支持绑定,并且可以通过元对象系统 (QMetaProperty) 设置和检查与该属性的绑定。bindableProperty 命名一个 QBindable 类型的类成员,其中 T 是属性类型。此属性是在 Qt 6.0 中引入的。
  • CONSTANT 属性的存在表示该属性值为常量。对于给定的对象实例,常量属性的 READ 方法每次调用时必须返回相同的值。对于不同的对象实例,此常量值可能不同。常量属性不能具有 WRITE 方法或 NOTIFY 信号。
  • FINAL 属性的存在表示该属性不会被派生类覆盖。在某些情况下,这可以用于性能优化,但 moc 并不强制执行。必须注意切勿覆盖 FINAL 属性。
  • REQUIRED 属性的存在表示该属性应由类的用户设置。moc 并不强制执行此操作,并且主要用于适用于暴露给 QML 的类。在 QML 中,除非设置了所有必需属性,否则无法实例化具有必需属性的类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NestJS 框架深度解析

框架功能分析 NestJS 是一个基于 Node.js 的渐进式框架&#xff0c;专为构建高效、可扩展的服务器端应用程序而设计。其核心理念结合了 面向对象编程&#xff08;OOP&#xff09;、函数式编程&#xff08;FP&#xff09; 和 函数式响应式编程&#xff08;FRP&#xff09;&…

PostgreSQL技术大讲堂 - 第89讲:重讲数据库完全恢复

PostgreSQL技术大讲堂 - 第89讲&#xff0c;主题&#xff1a;重讲数据库完全恢复 时间&#xff1a;2025年05月10日19:30 欢迎持续关注CUUG PostgreSQL技术大讲堂。

ubuntu部署supabase

安装supabse https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroupsplatform&platformlinux brew install supabase/tap/supabase supabase init supabase start需要使用brewuser进行安装&#xff1a; brew安装参考链接&#xff1a; ht…

基于javaweb的SpringBoot酒店管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

python 上海新闻爬虫, 东方网 + 澎湃新闻

1. 起因&#xff0c; 目的: 继续做新闻爬虫。我之前写过。此文先记录2个新闻来源。后面打算进行过滤&#xff0c;比如只选出某一个类型新闻。 2. 先看效果 过滤出某种类型的新闻&#xff0c;然后生成 html 页面&#xff0c;而且&#xff0c;自动打开这个页面。 比如科技犯罪…

使用bitNet架构

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、配置二、报错总结 前言 大型语言模型&#xff08;LLM&#xff09;面临的挑战&#xff1a;高能耗、高内存需求、部署门槛高。 微软提出 BitNet 架构&#x…

笔试强训(十七)

文章目录 活动安排题解代码 哈夫曼编码题解代码 奇数位丢弃题解代码 活动安排 题目链接 题解 1. 区间贪心 排序 2. 如果有重叠部分&#xff0c;每次选择右端点较小的&#xff0c;可以尽可能多的选择区间个数&#xff0c;如果没有重叠部分&#xff0c;选择下一个区间的右端…

数据库数据清洗、预处理与质量监控、 数据质量的核心概念

数据库数据清洗、预处理与质量监控、 数据质量的核心概念 准确性 (Accuracy) 准确性指数据正确反映其所描述的实体或事件真实状况的程度。准确的数据应当与现实世界中的实际情况一致。 一致性 (Consistency) 一致性指数据在不同表、系统或时间点之间保持逻辑上一致的程度。…

Docker组件详解:核心技术与架构分析

Docker详解&#xff1a;核心技术与架构分析 Docker作为一种容器化技术&#xff0c;已经彻底改变了软件的开发、交付和部署方式。要充分理解和利用Docker的强大功能&#xff0c;我们需要深入了解其核心组件以及它们如何协同工作。本文将详细介绍Docker的主要组件、架构设计以及…

【言语】刷题3

front&#xff1a;刷题2 题干 超限效应介绍冰桶挑战要避免超限效应 B明星的作用只是病痛挑战的一个因素&#xff0c;把握程度才是重点&#xff0c;不是强化弱化明星作用&#xff0c;排除 A虽没有超限效应&#xff0c;但是唯一的点出“冰桶效应”的选项&#xff0c;“作秀之嫌…

【fastadmin开发实战】在前端页面中使用bootstraptable以及表格中实现文件上传

先看效果&#xff1a; 1、前端页面中引入了表格 2、表格中实现文件上传 3、增加截止时间页面 难点在哪呢&#xff1f; 1、这是前端页面&#xff0c;并不支持直接使用btn-dialog的类属性实现弹窗&#xff1b; 2、前端页面一般绑定了layout模板&#xff0c;如何实现某个页面不…

豆包:基于多模态交互的智能心理咨询机器人系统设计与效果评估——情感计算框架下的对话机制创新

豆包:基于多模态交互的智能心理咨询机器人系统设计与效果评估——情感计算框架下的对话机制创新 摘要 随着人工智能在心理健康领域的应用深化,本文提出一种融合情感计算与动态对话管理的智能心理咨询机器人系统架构。通过构建“用户状态-情感响应-策略生成”三层模型,结合…

【漫话机器学习系列】257.填补缺失值(Imputing Missing Values)

数据科学必备技能&#xff1a;填补缺失值&#xff08;Imputing Missing Values&#xff09; 在数据分析和机器学习项目中&#xff0c;缺失值&#xff08;Missing Values&#xff09; 是非常常见的问题。缺失的数据如果处理不当&#xff0c;会严重影响模型的训练效果&#xff0…

基于千眼狼高速摄像机与三色掩模的体三维粒子图像测速PIV技术

研究背景 航空航天、能源动力领域&#xff0c;测量三维瞬态流场的速度场信息对于理解流体力学行为、优化系统设计非常关键。 传统三维粒子图像测速技术如Tomo层析PIV&#xff0c;因依赖多相机阵列&#xff0c;存在系统体积、操作复杂&#xff0c;在封闭空间测量存在困难&#…

MongoDB 的主要优势和劣势是什么?适用于哪些场景?

MongoDB 的主要优势 (Advantages) 灵活的文档模型 (Flexible Document Model): 无需预定义模式 (Schemaless/Flexible Schema): 这是 MongoDB 最核心的优势之一。它存储 JSON 格式的文档&#xff0c;每个文档可以有不同的字段和结构。这使得在开发过程中修改数据结构非常容易&a…

css iconfont图标样式修改,js 点击后更改样式

背景&#xff1a; 在vue项目中&#xff0c;通过点击/鼠标覆盖&#xff0c;更改选中元素的样式&#xff0c;可以通过js逻辑&#xff0c;也可以根据css样式修改。包括以下内容&#xff1a;iconfont图标的引入以及使用&#xff0c;iconfont图标样式修改【导入文件是纯白&#xff0…

CosyVoice介绍

CosyVoice介绍 CosyVoice是阿里开源的一个多语言语音生成大模型&#xff0c;可应用于TTS(Text To Speech) 工具的开发。它支持内置预制语音生成、语音克隆、自然语言控制语音生成等功能。CosyVoice的另一个亮点在于它对生成语音情感和韵律的精细控制&#xff0c;这是通过富文本…

分布式任务调度XXL-Job

​ XXL-Job 是一款轻量级、分布式的任务调度平台&#xff0c;其核心设计解决了传统任务调度&#xff08;如Quartz&#xff09;在分布式场景下的‌任务分片‌、‌高可用‌、‌可视化管控‌等痛点。以下从原理、核心架构、应用场景、代码示例及关联中间件展开详解 一、主流任务…

GOOSE 协议中MAC配置

在 GOOSE&#xff08;Generic Object Oriented Substation Event&#xff09;协议中&#xff0c;主站&#xff08;Publisher&#xff09;发送的 MAC 地址不需要与从站&#xff08;Listener&#xff09;的 MAC 地址一致&#xff0c;其通信机制与 MAC 地址的匹配逻辑取决于 GOOSE…

交流充电桩IEC 61851-1和IEC 61851-21-2标准测试项目

交流充电桩IEC 61851-1和IEC 61851-21-2标准测试项目 立讯检测的光储充实验室专注于光伏、储能、充电设施等新能源领域的检测与认证服务&#xff0c;以下是详细介绍&#xff1a; ‌1. 实验室概况‌ ‌覆盖领域‌&#xff1a;光伏逆变器、储能电池系统、充电桩、便携式储能电…