初识QT(二十)——Qt元对象和属性系统详解

2023-11-06

Qt 是一个用标准 C++ 编写的跨平台开发类库,它对标准 C++ 进行了扩展,引入了元对象系统、信号与槽、属性等特性,使应用程序的开发变得更高效。

本节将介绍 Qt 的这些核心特点,对于理解和编写高效的 Qt C++ 程序是大有帮助的。

Qt 的元对象系统

Qt 的元对象系统(Meta-Object System)提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。

元对象系统由以下三个基础组成:

  1. QObject 类是所有使用元对象系统的类的基类。
  2. 在一个类的 private 部分声明 Q_OBJECT宏,使得类可以使用元对象的特性,如动态属性、信号与槽。
  3. MOC(元对象编译器)为每个 QObject 的子类提供必要的代码来实现元对象系统的特性。


构建项目时,MOC 工具读取 C++ 源文件,当它发现类的定义里有 Q_OBJECT 宏时,它就会为这个类生成另外一个包含有元对象支持代码的 C++ 源文件,这个生成的源文件连同类的实现文件一起被编译和连接。

除了信号与槽机制外,元对象还提供如下一些功能:

  • QObject::metaObject() 函数返回类关联的元对象,元对象类 QMetaObject 包含了访问元对象的一些接口函数,例如 QMetaObject::className() 函数可在运行时返回类的名称字符串。

    QObject *obj = new QPushButton;
    obj->metaObject()->className (); //返回"QPushButton"

  • QMetaObject::newInstance() 函数创建类的一个新的实例。
  • QObject::inherits(const char *className) 函数判断一个对象实例是否是名称为 className 的类或 QObject 的子类的实例。例如:

    QTimer *timer = new QTimer; // QTimer 是 QObject 的子类
    timer->inherits ("QTimer"); // 返回 true
    timer->inherits ("QObject");  // 返回 true
    timer->inherits ("QAbstractButton");//返回 false,不是 QAbstractButton 的子类

  • QObject::tr() 和 QObject::trUtf8() 函数可翻译字符串,用于多语言界面设计,后续章会专门介绍多语言界面设计。
  • QObject::setProperty() 和 QObject::property() 函数用于通过属性名称动态设置和获取属性值。


对于 QObject 及其子类,还可以使用 qobject_cast() 函数进行动态投射(dynamic cast)。例如,假设 QMyWidget 是 QWidget 的子类并且在类定义中声明了 Q_OBJECT 宏。创建实例使用下面的语句:

QObject *obj = new QMyWidget;

变量 obj 定义为 QObject 指针,但它实际指向 QMyWidget 类,所以可以正确投射为 QWidget,即:

QWidget *widget = qobject_cast<QWidget *>(obj);

从 QObject 到 QWidget 的投射是成功的,因为 obj 实际是 QMyWidget 类,是 QWidget 的子类。也可以将其成功投射为 QMyWidget,即:

QMyWidget *myWidget = qobject_cast<QMyWidget *>(obj);

投射为 QMyWidget 是成功的,因为 qobject_cast() 并不区分 Qt 内建的类型和用户自定义类型。但是,若要将 obj 投射为 QLabel 则是失败的,即:

QLabel * label - qobject_cast<QLabel *>(obj);

这样投射是失败的,返回指针 label 为 NULL,因为 QMyWidget 不是 QLabel 的子类。

使用动态投射,使得程序可以在运行时对不同的对象做不同的处理。

属性系统

属性定义

Qt 提供一个 Q_PROPERTY() 宏可以定义属性,它也是基于元对象系统实现的。Qt 的属性系统与 C++ 编译器无关,可以用任何标准的 C++ 编译器编译定义了属性的 Qt C++ 程序。

在 QObject 的子类中,用宏 Q_PROPERTY() 定义属性,其使用格式如下:

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

Q_PROPERTY 宏定义一个返回值类型为 type,名称为 name 的属性,用 READ、WRITE 关键字定义属性的读取、写入函数,还有其他的一些关键字定义属性的一些操作特性。属性的类型可以是 QVariant 支持的任何类型,也可以用户自定义类型。

Q_PROPERTY 宏定义属性的一些主要关键字的意义如下:

  • READ 指定一个读取属性值的函数,没有 MEMBER 关键字时必须设置 READ。
  • WRITE 指定一个设定属性值的函数,只读属性没有 WRITE 设置。
  • MEMBER 指定一个成员变量与属性关联,成为可读可写的属性,无需再设置 READ 和 WRITE。
  • RESET 是可选的,用于指定一个设置属性缺省值的函数。
  • NOTIFY 是可选的,用于设置一个信号,当属性值变化时发射此信号。
  • DESIGNABLE 表示属性是否在 Qt Designer 里可见,缺省为 true。
  • CONSTANT 表示属性值是一个常数,对于一个对象实例,READ 指定的函数返回值是常数,但是每个实例的返回值可以不一样。具有 CONSTANT 关键字的属性不能有 WRITE 和 NOTIFY 关键字。
  • FINAL 表示所定义的属性不能被子类重载。


QWidget 类定义属性的一些例子如下:

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

属性的使用

不管是否用 READ 和 WRITE 定义了接口函数,只要知道属性名称,就可以通过 QObject::property() 读取属性值,并通过 QObject::setProperty() 设置属性值。例如:

QPushButton *button = new QPushButton;
QObject *object = button;
object->setProperty("flat", true);
bool isFlat= object->property ("flat");

动态属性

QObject::setProperty() 函数可以在运行时为类定义一个新的属性,称之为动态属性。动态属性是针对类的实例定义的。

动态属性可以使用 QObject::property() 查询,就如在类定义里用 Q_PROPERTY 宏定义的属性一样。

例如,在数据表编辑界面上,一些字段是必填字段,就可以在初始化界面时为这些字段的关联显示组件定义一个新的 required 属性,并设置值为“true”,如:

editName->setProperty("required", "true");
comboSex->setProperty("required", "true");
checkAgree->setProperty("required", "true");

然后,可以应用下面的样式定义将这种必填字段的背景颜色设置为亮绿色。

*[required="true"]{background-color:lime}

类的附加信息

属性系统还有一个宏 Q_CLASSINFO(),可以为类的元对象定义“名称——值”信息,如:

class QMyClass:public QObject {
    Q_OBJECT
    Q_CLASSINFO("author", "Wang")
    Q_CLASSINFO ("company", "UPC")
    Q_CLASSINFO("version ", "3.0.1")
  public:
    ...
};

用 Q_CLASSINFO() 宏定义附加类信息后,可以通过元对象的一些函数获取类的附加信息,如 classlnfo(int) 获取某个附加信息,函数原型定义如下:

QMetaClassInfo QMetaObject::classInfo(int index) const

返回值是 QMetaClassInfo 类型,有 name() 和 value() 两个函数,可获得类附加信息的名称和值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

初识QT(二十)——Qt元对象和属性系统详解 的相关文章

  • Java语言连接数据库时间读取错误的问题

    连接时候的数据库相关配置
  • pcie inbound和outbound关系

    Inbound PCI域訪问存储器域 Outbound 存储器域訪问PCI域 RC訪问EP RC存储器域 gt outbound gt RC PCI域 gt EP PCI域 gt inbound gt EP存储器域 EP訪问RC EP存储器
  • Jenkins插件下载失败两种处理办法

    持续集成 自动化部署 弹性伸缩教程 http edu csdn net course detail 6452 大家在使用jenkins安装插件的时候经常遇到一下问题 就是插件由于网络或者墙的原因无法直接下载 出现下面截图的问题 处理办法有两
  • flume采集log4j日志到kafka

    简单测试项目 1 新建Java项目结构如下 测试类FlumeTest代码如下 package com demo flume import org apache log4j Logger public class FlumeTest priv
  • 芯片电源引脚为什么要加一个100nF电容

    在设计电路的时候 常常会在芯片的每个电源引脚就近的放一个100nF的贴片电容 这电容有什么作用呢 今天就来和大家分享一下这个电容的作用以及为什么是100nF 首先这个芯片电源引脚的100nF的电容一般我们称为旁路电容 也有叫去耦电容的 因为
  • Oracle 行转列 动态出转换的列

    10月的第二天 前天写了个Oracle中行转列的pivot的基本使用方法 然后 因为pivot的用法中 正常情况下 我们需要转出多少个列 都得在我们的sql中完完整整地写出 而不能直接在里面写个查询来动态转换 然后 趁着祖国母亲的生日 这几
  • 漫谈设计模式之建造者模式(Builder)

    建造者模式 Builder 又叫生成器模式 属于对象创建型模式 建造者模式的目的是要将一个复杂对象的构建与它的表示分离 使得同样的构建过程可以创建不同的表示 产品 说得通俗点就是一个产品 表示 的构建 生产 过程是一样的 但是同样的生产过程
  • hdu 1465不容易系列之一

    http acm hdu edu cn showproblem php pid 1465 这是一道排错问题 用排错公式 排错公式推导 当n个编号元素放在n个编号位置 元素编号与位置编号各不对应的方法数用D n 表示 那么D n 1 就表示n
  • FISCO BCOS 2.0原理解析: 群组架构的设计

    为了方便企业 开发者更深入理解FISCO BCOS 2 0诸多新特性 更快速地运用FISCO BCOS搭建联盟链应用 我们启动了FISCO BCOS 2 0系列剖析的计划 在后续的推送中 我们将陆续推出 FISCO BCOS 2 0原理解析
  • LeetCode 260. 只出现一次的数字 III

    题目链接 https leetcode cn problems single number iii 思路如下 从头到尾依次异或数组中的每一个数字 那么最终得到的结果就是两个只出现一次的数字的异或结果 因为其他数字都出现了两次 在异或中全部抵
  • javascript求任意一组数的平均值

    代码 function getAvg 任意一组数求平均值 var sum 0 len arguments length i arguments是js函数中内置的类数组 它能像数组一样使用下标进行访问元素 for i 0 i
  • vue怎么改logo_vue项目添加网页logo

    网上关于为vue项目添加网页logo的文章很多 步骤很简单 但是博主还是踩了坑 特此记录一下 先上效果 1 首先 要为网页添加logo我们需要一张ico格式的图标 可以用网上的在线转换工具 将 jpg png 格式的图片转为 ico 格式
  • 防抖与节流函数

    文章目录 前言 节流函数代码 防抖函数代码 前言 防抖与节流是日常开发中常用的两个函数 目的都在于控制事件触发频率降低性能损耗和代码错误 节流 点击事件即开始计时 计时时间内无论触发多少次事件 都只执行触发计时的那个事件 防抖 点击事件即开
  • Python: SQLAlchemy 增、删、改、查

    目录 一 完整代码 1 1 代码 1 2 运行结果 二 增删改查 2 1 增加一行记录 2 2 修改一行记录 2 3 查询一行记录 2 4 删除一行记录 一 完整代码 1 1 代码 import uuid import datetime i
  • 一个关于缓存的问题

    网上查了一下 关于生命周期的话题 如果是类的成员变量 则其声明周期贯穿整个其对象的生命周期 如果是方法内的变量 局部变量 则仅仅在该方法内有效 出了方法体则无效 失去意义 static是修饰静态代码块或者成员变量或者方法的 其方法或者代码块
  • 介绍一个十分牛逼的GitHub看代码神器,零基础必学会的操作。

    给大家介绍一个非常实用的工具 有了它 我们可以在几秒之内用 VS Code 打开 GitHub 上的任意一个 Repo 无需 Clone 速度飞快 用法也十分简单而且好记 下面给大家介绍下 介绍 比如这里是 Scrapy 的仓库 https
  • 【線段樹】Mayor's posters

    Description The citizens of Bytetown AB could not stand that the candidates in the mayoral election campaign have been p
  • 如何使用pandas进行excel文件读取(二)

    如何使用pandas进行excel指定行列读取 文章目录 前言 一 pandas是什么 二 loc和iloc方法 1 引入库 2 读入数据 3 读取指定数据 总结 前言 前面说到了如何用pandas对excel文件进行读取 但是那种读取只适

随机推荐

  • 根据计算两点之间的距离

    function getDistance lat1 lng1 lat2 lng2 earthRadius 6367000 lat1 lat1 pi 180 lng1 lng1 pi 180 lat2 lat2 pi 180 lng2 lng
  • 函数重写&运算符重载&类方法和静态方法&对象其他概念

    重要思想 python中万物皆对象 1 函数重写 有了的前提下改写 重写 override v 以权力 否决 推翻 在继承的前提下 如果在子类中重新实现了父类中的函数 才能进行函数重写 自定义函数的重写 1 什么时候需要重写函数 如果一个类
  • 静态Web服务器-返回指定页面数据

    学习目标 能够写出组装指定页面数据的响应报文 1 静态Web服务器的问题 目前的Web服务器 不管用户访问什么页面 返回的都是固定页面的数据 接下来需要根据用户的请求返回指定页面的数据 返回指定页面数据的实现步骤 获取用户请求资源的路径 根
  • Nginx 使用 proxy_cookie_path 解决反向代理 cookie 丢失导致无法登录等问题

    语法 参考nginx官方文档 语法 proxy cookie path off proxy cookie path path replacement 默认 proxy cookie path off 位置 http server locat
  • 学习前端必要的PS基础

    学习前端必要的PS基础 为什么我们要学习PS 学习PS需要知道的基本操作 为什么我们要学习PS 因为我们需要知道设计稿里面的颜色 字体大小 背景颜色 一些元素的宽高距离等等信息 学习PS需要知道的基本操作 点击菜单栏 窗口 信息 字符 图层
  • 新书上市

    本书从各种角度来思考同一个数学问题 一共 16 个问题 并给出不同的解答 这 16 个问题包括 三等分蛋糕 设计时钟的表盘 求出地球的直径 列举违背规律的东西 画出心形图像 列举答案为 1 的问题 三等分角 用大定理证明一些无聊的问题 求出
  • html标签类前端笔记

    HTML5 布局类标签 HTML是具有语义化的语言 针对网页的布局 有一类标签代表各种意义的 布局盒子 所有的布局类标签都主要用来构建页面的内容区域 是双标签类型 是双标签类型 默认显示为块状元素 通用的布局标签 div 语义 无明确的含义
  • ElasticSearch-基本操作

    目录 索引操作 创建索引 查看索引 删除索引 文档操作 创建文档 查看文档 修改文档 修改字段 删除文档 条件删除文档 映射操作 映射数据说明 创建映射 查看映射 索引映射关联 索引操作 对比关系型数据库 创建索引就等同于创建数据库 创建索
  • 在线音乐播放器测试用例

    登录功能测试用例 当用户输入正确的用户名和密码时 方可登录成功 否则 会给出相应得提示 上传音乐测试用例 用户选择上传的音乐后缀是 mp3时 才能上传成功 查询音乐测试用例 查询音乐支持指定名称查询和模糊匹配查询 安全测试 安全测试作为系统
  • Servlet+JSP实现web应用程序

    上一篇博客介绍了Servlet的基础知识 此篇博客通过实际例子来演示如果搭配Servlet和JSP编写web应用程序 如果对Servlet和JSP基础知识不清楚 可查看这里了解基础知识 另外 web Demo应用中还使用了Bootstrap
  • 【RocksDB】Ubuntu18.04下编译rocksdb

    最近的新项目是NewSQL 底层存储引擎是rocksdb 于是在Ubuntu下编译了一下 下面是编译过程 首先安装依赖的包以及组件 安装gcc g 及make sudo apt get install build essential 安装g
  • hive中分组取前N个值的实现

    背景 假设有一个学生各门课的成绩的表单 应用hive取出每科成绩前100名的学生成绩 这个就是典型在分组取Top N的需求 解决思路 对于取出每科成绩前100名的学生成绩 针对学生成绩表 根据学科 成绩做order by排序 然后对排序后的
  • 使用IDEA完成项目的一键部署运行(远程服务器(linux或者windows))

    使用阿里云的Cloud Toolkit工具 Cloud Toolkit配置 1 安装Cloud Toolkit插件 第 1 步 打开 Intellij 的 Settings Windows下 或 Preferences Mac下 窗口 第
  • windows2003服务器复制文件弹出正在复制的进度条,PowerShell拷贝文件并显示进度

    Function 从拷贝文件 并显示进度 Author wangccsy 126 com Date 2013 02 21 yestoday Get Date Get Date AddDays 1 Format yyyy MM dd remo
  • 期货开户交易保持独立客观

    一旦相信了交易就是概率游戏 那么对错 赢亏等概念就不再重要 有了合适的期望 就不会把市场定义解读为痛苦的或威胁的 也会有效地中和交易的情绪风险 保持策略的持续一致性客观地确认优势 这是长期经验总结的结果 但优势不是完全正确 仅仅代表概率较高
  • 鸿蒙笔记2

    常用基础组件 1 组件介绍 组件 Component 是界面搭建与显示的最小单位 HarmonyOS ArkUI声明式开发范式为开发者提供了丰富多样的UI组件 我们可以使用这些组件轻松的编写出更加丰富 漂亮的界面 组件根据功能可以分为以下五
  • MongoDB数据库常用SQL命令

    1 db collection updateMany 修改集合中的多个文档 db getCollection user find pId 3332a512df604a74a72f267cf246 updateMany pId c8018dd
  • ES6 数组的扩展方法

    1 数组的方法 from of from 将伪数组转换成真正的数组 function add console log arguments es5中 将参数转换成数组 let arr slice call arguments console
  • 时间序列--残差分析

    残差 y yhat 一般我们就停止在这里了 但是如果残差表现的有某种形式 代表我们的模型需要进一步改进 如果残差表现的杂乱无章 代表确实没什么别的信息好提取了 现在用最naive的model 上一个时间的值 yhat看看残差表现吧 关于残差
  • 初识QT(二十)——Qt元对象和属性系统详解

    Qt 是一个用标准 C 编写的跨平台开发类库 它对标准 C 进行了扩展 引入了元对象系统 信号与槽 属性等特性 使应用程序的开发变得更高效 本节将介绍 Qt 的这些核心特点 对于理解和编写高效的 Qt C 程序是大有帮助的 Qt 的元对象系