• 035-第三代软件开发-Qt属性系统


    头图

    第三代软件开发-Qt属性系统


    关键字: QtQmlQ_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 属性系统的详细介绍:

    1. 属性(Properties):

      • 属性是 Qt 对象的特征或状态,可以是任何数据类型,例如整数、字符串等。
      • 属性可以通过 Q_PROPERTY 宏在类的头文件中进行定义。
    2. 访问器函数(Accessor Functions):

      • 对于每个属性,Qt 提供了自动生成的访问器函数,用于获取和设置属性的值。
      • 访问器函数遵循命名约定:propertyName() 用于获取属性值,setPropertyName(value) 用于设置属性值。
    3. 反射(Reflection):

      • Qt 属性系统基于反射机制,允许在运行时获取和操作对象的属性信息。
      • 可以使用 QObject::metaObject() 函数获取对象的元对象(QMetaObject),然后使用元对象的方法来访问属性。
    4. 元对象系统(Meta-Object System):

      • 元对象系统是 Qt 的核心部分,用于支持属性系统、信号与槽等功能。
      • QMetaObject 是一个描述对象的结构和行为的元对象,包括属性、方法、信号和槽等。
    5. 动态属性(Dynamic Properties):

      • Qt 的属性系统还支持动态属性,允许在运行时为对象添加新的属性。
      • 可以使用 QObject::setProperty(propertyName, value) 方法来设置动态属性,使用 QObject::property(propertyName) 方法来获取动态属性值。
    6. 信号与槽(Signals and Slots):

      • 属性系统与信号与槽机制密切相关。当属性的值发生变化时,可以使用信号和槽来通知其他部分进行相应的处理。
      • 可以通过属性的 notify 信号来触发属性值变化的通知。

    总结:Qt 的属性系统提供了一种方便而强大的方式来管理对象的属性。它支持静态属性和动态属性,并与元对象系统、反射和信号与槽机制紧密集成,使得开发者可以轻松地定义、访问和操作对象的属性。

    目的

    最近越写越迷茫了,就Qt 的属性系统而言,目前仅仅是会用,但是真的很想知道当初Qt 设计这个东西的初衷是什么,是为了C++与 Qml 交互的方便吗?带着这个问题找了百度,也找了Google,终究大家都是清一色如何使用,却没有一个人说说的他的由来,所以以下是GPT 给出的答案

    问:开发 Qt 属性系统的目的是什么

    答:Qt 属性系统的目的是为了提供一种方便和灵活地管理对象属性的方式。它允许开发人员在 Qt 应用程序中定义和操作对象的属性,包括读取、写入、通知、验证以及与其他属性之间建立关联等操作。

    以下是开发 Qt 属性系统的一些主要目的:

    1. 简化属性管理:Qt 属性系统使开发人员能够以一致的方式管理对象的属性。通过使用属性系统,可以将属性的读取、写入和通知功能集成到对象中,而不需要手动编写大量的代码。

    2. 支持元对象系统:属性系统与 Qt 的元对象系统紧密集成。这意味着属性可以在运行时通过名称进行访问,并且支持信号和槽机制。

    3. 可扩展性:Qt 属性系统是可扩展的,开发人员可以根据自己的需求定义自定义属性类型。这使得开发人员能够创建适合特定应用程序需求的灵活的属性。

    4. 与界面框架的集成: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

    image-20230801225943282

    声明属性的要求

    要声明一个属性,在继承QObject的类中使用Q_PROPERTY()宏。

    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])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    下面的示例,展示了如何使用MEMBER关键字将类成员变量导出为Qt属性。注意:NOTIFY信号必须被指定,这样才能被QML使用。(我使用的是经典的那种)

        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;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    一个属性的行为就像一个类的数据成员,但它有通过元对象系统访问的附加功能。

    如果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 属性系统有了新的理解,咱们再开一篇。这篇先这样


    博客签名2021
  • 相关阅读:
    vue+nodejs+express+jwt如何生成并处理token
    Python中使用IDLE调试程序
    Java 下数据业务逻辑开发技术 JOOQ 和 SPL
    【状态机模型】大盗阿福 买卖股票IV V
    leetcode - 1658. Minimum Operations to Reduce X to Zero
    了解微前端,深入前端架构的前世今生
    线路测量通用公式的推导及编程
    JDBC的工作原理
    JMeter笔记9 | JMeter参数化
    【每日三十六记 —— BGP知识点汇总大全】(第一弹)
  • 原文地址:https://blog.csdn.net/z609932088/article/details/134097205