Qt学习(18)——系统属性
Qt元对象系统最主要的功能是实现信号和槽机制,当然也有其他功能,就是支持属性系统。有些高级语言通过编译器的_property或者[property]等关键字实现属性系统,用于提供对成员变量的访问权限,Qt则通过自己的元对象系统支持属性访问,Qt是基于标准C++的,不需要底层编译器支持属性,Qt本身提供了通用的跨平台的属性系统。关于属性系统可以在Qt助手索引里面输入“The Property System”,找到相应的主题文档。Qt类库大量使用属性,通常开发基于Qt的类库时,也会用到属性系统。下面我们介绍简化版的属性系统,只是列举了属性系统的几个基本的条目。
1、属性系统简介
为了保持类的封装特性,通常成员变量需要保持私有状态,而为了与其他对象协作,就需要提供相应的 get/set函数。如果成员变量的数值发生了变化,通常也需要提供通知(NOTIFY)信息告知相关对象,Qt 里的通知一般都是使用信号触发。set函数可以作为槽函数,方便接收相关对象的信号以实现自动调整,比如上一节标签控件的 setText 槽函数。set函数会导致成员变量数值变化,为了通知相关对象,set 函数里通常会 emit 该成员变量发生变化的信号。
属性系统也是通过元对象系统实现的,它也是需要直接或间接从 QObject 类继承,并在类的声明里需要 Q_OBJECT宏。下面介绍简化版的属性声明,第一类是不指明与属性相关的私有成员变量,这时必须至少提供该属性的读函数:
Q_PROPERTY(type name
READ getFunction
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal] )
Q_PROPERTY()宏就是属性的声明:
- type 是指属性的类型,可以是 C++ 标准类型、类名、结构体、枚举等,name 就是属性的名字。
- READ 标出该属性的读函数 getFunction,Qt 属性的读函数通常省略 get 三个字母。
- WRITE 标出该属性的写函数 setFunction,中括号表示可选,写函数不是必须的。
- RESET 标出该属性的重置函数 resetFunction,重置函数将属性设为某个默认值,中括号表示可选,重置函数不是必须的。
- NOTIFY 标出该属性变化时发出的通知信号 notifySignal,中括号表示可选,这个信号不是必须的。
这仅仅列举了属性声明里简单的几行,复杂需要查阅 Qt 帮助文档。对于属性,注意 name仅仅是一个用于标识属性的名字,它不是实际存在的成员变量,属性系统不会自动生成成员变量,它就是虚无的名字代号(不同属性的名字不能相同)。对于属性用到的数值会存在一个真正的私有成员变量里面,私有成员变量、读函数、写函数、信号等需要另外编写这些声明,对于函数还需要编写实体代码。
上面是不明确指出私有成员变量的情形,也可以明确指出使用了哪个成员变量,这时候属性声明为:
Q_PROPERTY(type name
MEMBER memberName
[READ getFunction]
[WRITE setFunction]
[RESET resetFunction]
[NOTIFY notifySignal] )
这里的 MEMBER 标出属性使用的成员变量 memberName,其他的行与上面的声明类似。
在明确标出属性使用的成员变量的情况下,属性的读写函数可以省略不写,Qt 的 moc 工具会自动为成员变量生成读写代码;而重置函数、信号等需要自己声明,并编写必须的代码;如果声明了属性值变化的通知信号,那么 moc 工具生成的写属性代码会自动触发该通知信号。
如果希望自己的编写的类库支持 QML,那么 NOTIFY 通知信号是必须的,一般建议把成员变量、读函数、写函数、通知信号都明确标出来,这样方便程序员阅读和使用。