Qt属性系统Q_PROPERTY的通俗解释
创始人
2025-05-29 13:33:06
0

我们在查看QT工程的源代码的时候,有时候会发现类似于这样的代码:

    Q_OBJECTQ_PROPERTY(QColor bordercolor READ bordercolor WRITE setBordercolor)

因为我之前一直没用用过,就好奇这个到底有什么用,于是在网上搜索相关资料,发现很多文章都说得不清不楚,你抄我我抄你,一点意思没有,还跟反射扯上关系但是一直说不清道不明。

我就想问一句话,Q_PROPERTY这玩意儿有什么用,有什么优势?

但是诸多文章都没有说明为什么,直到我看到《Qt笔记(六十一)之Qt属性系统Q_PROPERTY》,终于讲到了重点,通过遍历属性名可以直接访问内部对象,即使最开始不知道内部对象的名称!

这样做有很大的一个好处就是,大大增强了模块之间的交互能力,又同时可以保证低耦合,避免模块直接接口的重复开发,比如在c++中你新增了一个接口或者属性,我必须新增一个对应的接口与属性才能调用,其实大可不必,利用了上面的这个属性,就可以不必改变接口,而实现对象的修改甚至重建!

结合反射机制,我们可以更好的理解这么做的优势,下面先看一下反射的定义。

反射是指程序在运行时动态获取对象属性与方法的一种机制,即编译器需要将类型信息(属性类型与偏移地址以及成员函数的地址等信息)编译到程序文件中,当程序运行时将这些信息加载到内存中去,做到运行时只根据对象的地址或引用就可以获取到对象的类型信息,从而利用这些信息达到修改或重建对象的目标。

我们可以简单理解为QT巧妙地实现了反射机制,因为c++本身是不支持反射的,但是QT这么做似乎就实现了反射,为什么说是似乎呢,因为我理解的反射机制,应该还包含对于函数的调用,甚至是更复杂的调用,而目前的例子,似乎只是调用了属性,也就是可以实现读取与修改部分变量的值,而没有能够实现调用内部对象函数的方法。

在这篇文章中《QT反射机制的原理和应用及优缺点》,也提到了如何通过反射机制调用函数,但是我发现该方法也不太完美,也没有实现类似于修改属性那种便利的操作。

总的来说,简单理解Q_PROPERTY,就是一种封装方式,使得调用者可以遍历其属性,修改其属性,而不需要提前知道这些属性的全部类型!

下面举一个例子,直接上代码:

#include "QtWidgetsTest.h"#include 
#include #include "../../CommonG/Log.h"QtWidgetsTest::QtWidgetsTest(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);int count = this->metaObject()->propertyCount();for (int i = 0; i < count; i++){CLOG::Out("%s", this->metaObject()->property(i).name());}CLOG::Out("width = %d", this->property("width").toInt());CLOG::Out("height = %d", this->property("height").toInt());CLOG::ViewLogFile();
}

在上面这个对象中,我并不知道对象有多少属性,但是可以通过这段代码遍历所有属性,输出结果如下:

[03-17 15:31:20 414]objectName
[03-17 15:31:20 414]modal
[03-17 15:31:20 414]windowModality
[03-17 15:31:20 414]enabled
[03-17 15:31:20 415]geometry
[03-17 15:31:20 415]frameGeometry
[03-17 15:31:20 415]normalGeometry
[03-17 15:31:20 415]x
[03-17 15:31:20 415]y
[03-17 15:31:20 415]pos
[03-17 15:31:20 415]frameSize
[03-17 15:31:20 415]size
[03-17 15:31:20 415]width
[03-17 15:31:20 415]height
[03-17 15:31:20 415]rect
[03-17 15:31:20 415]childrenRect
[03-17 15:31:20 415]childrenRegion
[03-17 15:31:20 415]sizePolicy
[03-17 15:31:20 415]minimumSize
[03-17 15:31:20 415]maximumSize
[03-17 15:31:20 416]minimumWidth
[03-17 15:31:20 416]minimumHeight
[03-17 15:31:20 416]maximumWidth
[03-17 15:31:20 416]maximumHeight
[03-17 15:31:20 416]sizeIncrement
[03-17 15:31:20 416]baseSize
[03-17 15:31:20 416]palette
[03-17 15:31:20 416]font
[03-17 15:31:20 416]cursor
[03-17 15:31:20 416]mouseTracking
[03-17 15:31:20 416]tabletTracking
[03-17 15:31:20 416]isActiveWindow
[03-17 15:31:20 416]focusPolicy
[03-17 15:31:20 416]focus
[03-17 15:31:20 416]contextMenuPolicy
[03-17 15:31:20 416]updatesEnabled
[03-17 15:31:20 417]visible
[03-17 15:31:20 417]minimized
[03-17 15:31:20 417]maximized
[03-17 15:31:20 417]fullScreen
[03-17 15:31:20 417]sizeHint
[03-17 15:31:20 417]minimumSizeHint
[03-17 15:31:20 417]acceptDrops
[03-17 15:31:20 417]windowTitle
[03-17 15:31:20 417]windowIcon
[03-17 15:31:20 417]windowIconText
[03-17 15:31:20 417]windowOpacity
[03-17 15:31:20 417]windowModified
[03-17 15:31:20 417]toolTip
[03-17 15:31:20 417]toolTipDuration
[03-17 15:31:20 417]statusTip
[03-17 15:31:20 417]whatsThis
[03-17 15:31:20 417]accessibleName
[03-17 15:31:20 417]accessibleDescription
[03-17 15:31:20 418]layoutDirection
[03-17 15:31:20 418]autoFillBackground
[03-17 15:31:20 418]styleSheet
[03-17 15:31:20 418]locale
[03-17 15:31:20 418]windowFilePath
[03-17 15:31:20 418]inputMethodHints
[03-17 15:31:20 418]iconSize
[03-17 15:31:20 418]toolButtonStyle
[03-17 15:31:20 418]animated
[03-17 15:31:20 418]documentMode
[03-17 15:31:20 418]tabShape
[03-17 15:31:20 418]dockNestingEnabled
[03-17 15:31:20 418]dockOptions
[03-17 15:31:20 418]unifiedTitleAndToolBarOnMac
[03-17 15:31:20 418]width = 600
[03-17 15:31:20 418]height = 400

上面是获取属性的值,那么如何设置呢?

this->setProperty("size", QSize(200, 200));

如上面的代码所示,如果我获取到了size类型,则可以设置其大小,如果我没获取到,那肯定不能设置了,加一个判断就可以了。其他属性的设置,方法是类似的。

但是我仍然有一些疑问,不知道大佬们是否可以帮忙解答一下。

1.是否有办法获取内部方法(函数)呢?如果有,是否有办法获取参数类型呢?

2.是否有办法获取属性参数的类型呢?比如上面的QSize,当然,我们可以通过约定的方式,比如把参数类型放在名称当中,但是这显然不是我想要的答案,我希望有更明确的方法来获取参数类型,而不是通过曲线救国。

这玩意儿如果用得上肯定还是很方便的,如果用不上也不用大费周折吧!

欢迎交流与讨论。

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...