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提供了兩種組件定位機制:絕對定位和佈局定位。佈局管理器就是爲了實現界面大小改變控件自適應。