本次内容主要为Qt中的一些核心机制,它们是构成Qt的基础,包括对象模型、信号和槽、属性系统、对象树与拥有权、元对象系统等。
1.对象模型
在已有的标准C++对象模型(可以在运行时非常有效地支持对象范式)的基础上添加一些特性,形成了自己的对象模型。这些特性有:
·信号和槽(Qt的核心特征,用于两个对象之间的通信)
·对象属性系统(基于元对象系统)
要在一个类中声明属性,该类必须继承自QObject类,而且还要在声明前使用Q_PROPERTY()宏:
Q_PROPERTY(type name
(READ getFunction[WRITE setFunction]|MEMBER memberName[(READ getFunction|WRITE setFunction)])
[RESER resertFunction]
[NOTIFY notifSignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL]
)
·事件和事件过滤器
·国际化字符串翻译机制
·定时器驱动
·分层结构的、可查询的对象树
组织和管理所有的QObject类及其子类的对象。当创建一个QObject时,如果使用了其他的对象作为其父对象(parent),那么这个QObject就会被添加到父对象的children()列表中;当父对象被销毁时,这个QObject也会被销毁。这个机制非常适合于管理管理GUI对象。
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QPushButton>
class MyButton : public QPushButton
{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = 0);
~MyButton();
};
#endif // MYBUTTON_H
这里主要是添加了析构函数的声明。然后到mybutton.cpp文件中,修改如下:
#include "mybutton.h"
#include <QDebug>
MyButton::MyButton(QWidget *parent) :
QPushButton(parent)
{
}
MyButton::~MyButton()
{
qDebug() << "delete button";
}
这里添加了析构函数的定义,这样当MyButton的对象被销毁时,就会输出相应的信息。这里定义析构函数只是为了更清楚地看到部件的销毁过程,其实一般在构建新类时不需要实现析构函数。下面到widget.cpp文件中进行更改,添加头文件:
#include<mybutton.h>
#include<QDebug>
在构造函数中添加代码:
MyButton *button = new MyButton(this); // 创建按钮部件,指定widget为父部件
button->setText(tr("button"));
更改析构函数:
Widget::~Widget()
{
delete ui;
qDebug() << "delete widget";
}
Widget类的析构函数中默认已经有了销毁ui的语句,这里又添加了输出语句。当Widget窗口被销毁时,将输出信息。下面运行程序,然后关闭窗口,在Qt Creator的应用程序输出栏中的输出信息为:
delete widget
delete button
可以看到,当关闭窗口后,因为该窗口是顶层窗口,关闭后没有可以显示的窗口,所以应用程序要销毁该窗口部件(如果不是顶层窗口,那么关闭时只是隐藏,不会被销毁),而当窗口部件销毁时会自动销毁其子部件。这也就是在Qt中经常只看到new操作而看不到delete操作的原因。再来看一下main.cpp文件,其中Widget对象是建立在栈上的:
Widget w;
w.show();
这样对于对象w,在关闭程序时会被自动销毁。而对于Widget中的部件,如果是在堆上创建(使用new操作符),那么只要指定Widget为其父窗口(创建时指定parent参数为this)就可以了,也不需要进行delete操作。整个应用程序关闭时,会去销毁w对象,而此时又会自动销毁它的所有子部件,这些都是Qt的对象树所完成的。
所以,对于规范的Qt程序,我们要在main()函数中将主窗口部件创建在栈上,比如“Widget w;”,而不要在堆上进行创建(使用new操作符)。对于其他窗口部件,可以使用new操作符在堆上进行创建,不过一定要指定其父部件,这样就不需要再使用delete操作符来销毁该对象了。
·守卫指针即QPointer
·动态的对象转换机制
·支持创建自定义类型
元对象系统
提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。基于以下3个条件:
1.该类必须继承自QObject类
2.必须在类的私有声明区声明Q_OBJECT宏
3.元对象编译器Meta-Object Compiler(moc)为QObject的子类实现元对象特性提供必要的代码。