Qt的精髓2
我觉得可以从基础模块开始看,首先核心就是QtCore:
1. 命名
如果说Qt最让人影响深刻的,就是命名了,清晰简洁,统一规范,老实说做到这个真的太不容易了。
2. 生命期管理
Qt是C++写的,C++程序对象和资源的生命期管理可是个麻烦事
Qt主要是用推荐对象树,我还是很喜欢这个方法的,尤其Gui程序中十分好用。同时用了COW,弱对象指针等。
3. 元对象系统
元对象系统的核心是MOC,元对象编译器,它对C++本身实现了扩展
- MOC
Qt的元对象系统实现了对类型和方法的反射,对注册过的对象实现了信号槽,INVOKABLE 方法,动态属性系统等。这也是能够用XML或QML来写Gui界面的基础。
基本方法是对Q_OBJECT 宏标记的类,编译时用MOC扫描生成代码文件 ,里面实现反射的方法的表。 编译Qt程序看看moc_xxx.cpp文件就可以看到它生成的代码。
这一块其实我们自己也可以实现。比如自己插入一个Map<name, method>保存对象的成员函数表,Map<name, property>保存属性, 然后再通过一些宏,来实现将属性和方法保存到Map里。
- signal slot
Qt发明用来做对象间通信的方法,在C#里叫Event Delegate。
Qt实现signal slot也是基于其元对象系统,MOC生成代码文件,signal实现成函数。
signal slot可以看做观察者模式的一种具体实现,相对于普通的观察者模式,抽象要高级一点,更加低耦合,不用保存对方指针,Qt还帮我们管理好了多连接,同时实现了自动断开连接,这样也避免里野指针问题。
Qt自己的signal slot相比于boost或其它的实现,跟自己的框架结合更紧密,可以有QueueConnection来实现跨线程(同线程也可以异步,默认Auto Connection会自动判断线程)的异步连接。
注意的是signal slot实现的是对象间通信,如果两个对象在逻辑上关系非常远,可以使用其他的消息订阅机制。
signal slot的实现本身也不复杂,借助C++11。
- Q_INVOKABLE 成员方法
这个跟slot在元对象上存储的信息略有不同,在遍历一个对象的反射方法时,可以区分方法时slot方法还是Q_INVOKABLE方法。
使用MetaMethod可以对一个对象方法的作异步调用(同/夸线程),同时Qt会处理好对象已经析构的问题。
另外MetaMethod也可以实现反射调用,https://github.com/hiitiger/sim
4. 驱动程序的核心,事件循环QEventloop
事件循环/消息循环,是程序运行核心,有一个循环,不断获取系统事件或自定义事件,然后进行分发处理。
QEventLoop loop;
loop.exec();
Qt封装不同平台自己的native事件处理,同时自己拥有一套QEvent事件心态,在loop.exec()处理线程中的各种事件。这一点各类Gui库/框架大同小异。
5. QThread
Qt的QThread应该和QEventloop结合起来看。
QThread是对不同系统线程的封装,默认有一个自身的eventloop再跑(见QThread::exec())。
Qt里QObject类型的对象都是属于某一个QThread的,前面说过signal slot连接跨线程默认是异步连接,这里Qt会判断signal所在的对象和slot所在的对象属于哪一个线程。
QObject在创建时所在的线程便是它所属于的线程,但是它可以被移动到其它线程(moveToThread)。
对于主线程,这是Qt在初始化时会生成一个线程对象作为主线程的代理对象。
注意,有些童鞋对Qt的线程使用有个典型错误,https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong;
6. Qt的几个主要Gui框架
- QWidget
- Graphics View
- Qt Quick (Qt Qml)
原文转载:https://www.zhihu.com/question/27040542/answer/220401994