QT学习十九天 QT核心机制
QT学习十九天 QT核心机制
- 核心机制简介
- 对象模型
- 元对象系统
- 属性系统
- 对象树与拥有权
核心机制简介
除了信号和槽,QT中还有对象模型、元对象系统、属性系统、对象树于拥有权等,他们是构成QT的基础。
对象模型
标准 C++ 对象模型可以在运行时非常有效的支持对象范式(object paradigm),但是它的静态特性在一些问题上不够灵活。图形用户界面编程不仅需要运行时的高效性,还需要高度的灵活性。为此,Qt 在标准 C++ 对象模型的基础上添加了一些特性,形成了自己的对象模型。
- 一个强大的无缝对象通信机制----信号和槽
- 可查询、可设计的对象属性系统
- 强大的事件和事件过滤器
- 基于上下文的国际化字符串翻译机制
- 完善的定时器驱动,可以在一个事件驱动GUI中处理多个任务
- 分层结构的、可查询的对象树,它使用一种很自然的方式来组织对象拥有权
- 守卫指针即 QPointer,它在引用对象被销毁时自动将其设置为 0
- 动态的对象转换机制
- 支持创建自定义类型
Qt 的这些特性大多是在遵循标准 C++ 规范内实现的,使用这些特性都必须要继承自 QObject 类。其中,对象通信机制和动态属性系统还需要元对象系统的支持。
元对象系统
Qt 中的元对象系统是对 C++ 的扩展,使其更适合真正的组件图形用户界面编程,提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。元对象系统是基于以下3个条件的。
- 该类必须继承自 QObject 类
- 必须在类定义的私有部分添加 Q_OBJECT 宏
- 元对象编译器 Meta-Object Compiler(MOC)为 QObject 的子类实现元对象特性提供必要条件的代码。
其中 MOC 工具读取一个 C++ 源文件,如果它发现一个或者多个类定义中包含有 Q_OBJECT 宏,便会另外创建一个 C++ 源文件,其中包含了为每一个类生成的元对象代码。这些产生的源文件或者被包含进类的源文件中,或者和类的实现同时进行编译和链接。
元对象系统主要是为了实现信号和槽机制才被引入的,不过除了信号和槽机制,元对象系统还提供了其他一些特性。
- QObject::metaObject() 返回一个类的元对象 QMetaObject
- QMetaObject::className() 可以在运行时以字符串形式返回类名,而不需要 C++ 编辑器原生的运行时类型信息的支持。
- QObject::inherits() 返回一个对象是否是 QObject 继承树上一个类的实例的信息
- QObject::tr() 进行字符串翻译实现国际化
- QObject::setProperty() 和 QObject::property() 通过名字来动态设置或者获取对象属性
- QMetaObject::newInstance() 构造类的一个新实例
- qobject_cast() 对 QObject 类进行动态类型转换,这个函数的功能类似于标准 C++ 中的 dynamic_cast()
属性系统
Qt 提供了强大的基于元对象系统的属性系统,可以在运行 Qt 的平台上支持标准 C++ 编译器。要在一个类中声明属性,该类必须继承自 QObject 类,还要在声明前使用 Q_PROPERTY() 宏
class Rectangle : public QObject {
Q_OBJECT
public:
Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged BINDABLE bindableWidth)
Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged BINDABLE bindableHeight)
Rectangle(QObject *parent = nullptr) : QObject(parent), m_width(0), m_height(0) {
m_height.setBinding([this]() { return m_width; });
}
int width() const { return m_width; }
void setWidth(int w) {
if (m_width == w) return;
m_width = w;
emit widthChanged();
}
int height() const { return m_height; }
void setHeight(int h) {
if (m_height == h) return;
m_height = h;
emit heightChanged();
}
signals:
void widthChanged();
void heightChanged();
private:
Q_OBJECT_BINDABLE_PROPERTY(Rectangle, int, m_width, &Rectangle::widthChanged);
Q_OBJECT_BINDABLE_PROPERTY(Rectangle, int, m_height, &Rectangle::heightChanged);
};
这个例子中,首先使用Q_PROPERTY宏声明了width和height两个可绑定属性,并分别为它们指定了读取器(READ)、写入器(WRITE)以及变更通知信号(NOTIFY)。接着,在构造函数内部调用了setBinding()方法,建立了从width到height的单向数据流。每当width发生改变时,height也会随之调整至相同的数值。最后,通过定义私有成员变量m_width和m_height及其对应的绑定属性,实现了对属性值的有效管理和跟踪。
对象树与拥有权
对象树用来管理所有的 QObject 类及其子类的对象。当创建一个 QObject 对象时,子对象会出现在父对象的 children() 列表中。如果父对象被销毁,子对象也会随之被销毁。这个机制很适合管理 GUI 对象。