赞
踩
用过Qt的都知道Qt的元对象系统,Qt的元对象系统为对象间通信、运行时类型信息和动态属性系统提供了信号和插槽机制。今天我们就来认识下Qt的动态属性系统。
引入官方文档的介绍:
Qt提供了一个复杂的属性系统,类似于一些编译器供应商提供的系统。然而,作为一个独立于编译器和平台的库,Qt不依赖于像__property或[property]这样的非标准编译器特性。Qt解决方案可以在Qt支持的每个平台上与任何标准C++编译器一起工作。它基于元对象系统,该系统也通过信号和插槽提供对象间的通信。
使用Qt动态属性,需要继承自QObject类,并使用宏 Q_PROPERTY()
我们熟知的QWidget就定义了很多的属性
具体结构为:
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] [REQUIRED])
可以看到字段很多,具体可自行查看官方文档。下面介绍Q_PROPERTY的常见用法。
项目开发中,如果使用的是Qt Creator,输入Q_PROPERTY时,自动补全功能就会联想出一些可选项,选择附带有type、READ、WRITE、NOTIFY字段的选项,这是一个最常规的用法,提供类型、读写和信号,能够满足大部分需求了。
输入完成后,使用快捷键Alt+回车,就会提示生成对应的变量和函数,确认后就会自动补全
还可以鼠标光标放在Q_PROPERTY,然后右键→Refactor也是一样的效果
按照上面的定义方式可以使用定义的接口setName和name进行修改和取值,还可以使用下面的方式进行操作
- bool setProperty(const char *name, const QVariant &value);
- QVariant property(const char *name) const;
name就是type对应的属性名称,使用setProperty的方式的一个好处就是只需要知道属性名称和类型,另外使用setName的方式速度会更快,两种方式各有利弊吧
- setProperty("name", "1111");
- qDebug() << __FUNCTION__ << "song" << "name:" << m_name << property("name").toString();
在父类中定义的属性,子类也是可以使用的
- QPushButton *button = new QPushButton;
- QObject *object = button;
-
- button->setDown(true);
- object->setProperty("down", true);
动态属性就是没有手动添加Q_PROPERTY,直接调用setProperty,如果该属性没有,则会自动添加,提供一个invalid的QVariant就可以移除
- setProperty("name22", "1111");
- qDebug() << __FUNCTION__ << "song" << "name22:" << property("name22").toString();
- setProperty("name22", QVariant());
- qDebug() << __FUNCTION__ << "song" << "name22:" << property("name22");
需要注意的是动态属性并不会添加到元对象系统中,所以元对象相关的功能就用不了,如无法在QML中使用属性
直接看代码就好了, 这也是C++与QML交互运用
- #include <QObject>
- #include <QColor>
- #include <qqml.h>
-
- class TestClass : public QObject
- {
- Q_OBJECT
- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- QML_ELEMENT
- public:
- explicit TestClass(QObject *parent = nullptr);
-
- const QColor &color() const;
- void setColor(const QColor &newColor);
-
- signals:
- void colorChanged();
-
- private:
- QColor m_color;
-
- };
- import QtQuick 2.15
- import QtQuick.Window 2.15
- import com.mycompany.qmlcomponents 1.0
-
- Window {
- width: 640
- height: 480
- visible: true
- title: qsTr("Hello World")
-
- TestClass {
- id: testClass
- color: Qt.red
- }
-
- Rectangle {
- width: 100
- height: 100
- color: testClass.color
- }
- }
还有更简单的定义方式,把READ和WRITE去掉,只保留NOTIFY,这样就可以把setter和getter的接口去掉,这样也是可以的,代码量更少,QML中使用NOTIFY是必须的,在C++中对属性进行操作则可以使用前面介绍的setProperty
- class TestClass : public QObject
- {
- Q_OBJECT
- Q_PROPERTY(QColor color MEMBER m_color NOTIFY colorChanged)
- QML_ELEMENT
- public:
- explicit TestClass(QObject *parent = nullptr);
-
- signals:
- void colorChanged();
-
- private:
- QColor m_color;
-
- };
Qt属性系统贯穿整个Qt框架,作为Qt框架的使用者必须要有所了解,并且会基本的运用,本篇文章就介绍一些常见的点。
最后的QML的完整demo地址:GitHub
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。