Qt属性系统Q_PROPERTY的通俗解释

62 篇文章 8 订阅

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

    Q_OBJECT
    Q_PROPERTY(QColor bordercolor READ bordercolor WRITE setBordercolor)

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

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

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

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

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

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

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

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

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

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

#include "QtWidgetsTest.h"

#include <QDebug>
#include <QMetaProperty>

#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,当然,我们可以通过约定的方式,比如把参数类型放在名称当中,但是这显然不是我想要的答案,我希望有更明确的方法来获取参数类型,而不是通过曲线救国。

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

欢迎交流与讨论。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值