Qt不只是界面库,Qt提供了功能丰富的C++类库,比如网络编程,数据库查询,xml解析,md5加密等…
1.事件驱动
1.1事件循环
Qt是事件驱动的,程序每个动作都是由某个事件所触发。QApplication::exec()会调用QEventLoop进入事件循环,此时程序会进入等待状态,等待处理各种事件
从系统得到的消息,比如鼠标,键盘等。Qt事件循环的时候读取这些事件,转换为QEvent后依次派发到对应窗口进行处理。
由Qt或应用程序产生,不放入队列直接通过QApplication::notify进行派发和处理,是同步的。
1.2事件过滤
从低到高逐渐可以分为如下步骤:
- 虚函数
keyPressEvent,mouseMoveEvent,dragEnterEvent,paintEvent
具体事件的处理。 - 虚函数
[virtual] bool QObject::event(QEvent *e)
接收到QEvent后派发个对应的事件过滤器。 - 通过调用
obj->installEventFilter(this)
,并重写虚函数bool eventFilter(QObject * watched, QEvent * event)
监视这个类和所有它的子类的所有事件。eventFilter未处理的消息会调用对应object的event函数 - QApplication::eventfilter
- QApplication::notify(QObject*receiver,QEvent *event)
2.信号和槽
2.1 相关说明
Qt的信号和槽机制是用来在对象间通信的方法,一个信号可以连接到多个槽和信号;多个信号可以连接到同一个槽;
如果一个信号连接到多个槽,当信号被发射后所有的槽函数按照连接建立的顺序都会被激活。
Qt信号槽需要Q_OBJECT宏支持的,程序在编译之前moc预处理器会对有Q_OBJECT宏的类进行预处理,生成moc_xxxx.cpp来扩展当前类。内部由meta object来维护我们需要的信息和接口。
2.2 信号槽关联
- 旧版本最原始的信号槽连接函数方式:
connect(m_slider,SIGNAL(valueChanged(int)),this,SLOT(onValueChanged(int)));
,其中SIGNAL和SLOT要求信号和槽的参数一致,且不可写形参名。否则不会响应槽函数。这是因为moc工具会将SIGNAL和SLOT宏转换的信息编译转化在生成的moc_xxx.cpp文件中对应起来。 - Qt5之后的connect版本引入了C++11新特性,使用最多的是下面两个,通过信号绑定funcation:
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QMetaObject::Connectionconnect(constQObject* senderPointerToMemberFunction signal, Functor functor)
- 对于自定义的类型在connect之前需要使用
qRegisterMetaType<>();
注册一下。
2.3 链接类型
- AutoConnection 默认参数,如果接收者所在的线程和信号发射的线程是同一个线程使用DirectConnect,否则使用QueuedConnection;
- DirectConnection信号发射后槽函数会被立刻调用,槽函数的执行在信号发射的线程;
- QueuedConnection将信号转换为事件,事件被派发到接收者所在的线程队列中,事件循环会在之后的某个时间取出事件调用槽函数,此槽函数的执行在接收者的线程;
- BlockingQueuedConnection与QueuedConnection类似,区别在于发送者的线程会被阻塞,直至接收者所在线程的事件循环处理发送者发送(入栈)的事件,当连接信号的槽被触发后,阻塞被解除。要注意的是使用这个参数要求接收者所在的线程不是信号发射的线程,否则应用程序会死锁
发送对象(sender)在哪个线程并不重要,AutoConnection是根据信号是在哪个线程发射的来决定用哪一种连接类型。
3.元对象
- 元对象就是描述另一个对象结构的对象,继承自QObject的类,需要定义QOBJECT宏。
- 展开QObject宏,如下:
#defineQ_OBJECT \
public:\
Q_OBJECT_CHECK \
static const QMetaObject staticMetaObject;\
virtual const QMetaObject *metaObject()const; \
virtual void *qt_metacast(const char *); \
QT_TR_FUNCTIONS \
virtual int qt_metacall(QMetaObject::Call,int, void **); \
private:\
Q_DECL_HIDDEN_STATIC_METACALL static voidqt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
struct QPrivateSignal {};
- QMetaObject是元对象的一个Qt实现,它提供了QObject对象所拥有的属性和方法等信息。一个拥有元对象的类就可以支持反射。虽然C++中不存在反射,但是Qt的元对象编译器(MetaObject compiler,moc)可以为QObject类生成支持这种机制的代码。
4.隐式共享,D指针技术(d-pointer)
Qt为了使其动态库最大程度上实现二进制兼容,引入了d指针的概念。
5.布局管理
GUI界面就是有一堆组件(控件)的组合,对于组件放在什么位置Qt提供了两种组件定位机制:绝对定位和布局定位。布局管理器就是为了实现界面大小改变控件自适应。