除了信號槽,Qt也使用了另一種手段來響應(yīng)對象,即事件。比如鼠標(biāo)左鍵按下事件,鍵盤某一個按鍵按下事件。 Qt的主循環(huán)QCoreapplication::exec()就是一個事件循環(huán),這個循環(huán)捕獲本地計算機產(chǎn)生的各種事件然后將這些事件存放到事件隊列中,按照FIFO的順序?qū)⒚恳粋€事件傳遞給相應(yīng)的對象(QObject)。 事件隊列中的事件被傳遞給QObject::event()函數(shù),這個函數(shù)是一個集中分配營,它判斷參數(shù)是哪種類型的事件,然后將該事件傳遞給相應(yīng)的事件處理函數(shù)進行處理。而event本身并不對事件進行處理 。
事件的傳播順序: 1. 在QCoreApplication::exec()主循環(huán)中,Qt捕獲計算機產(chǎn)生的各種事件,如果在此之前還有其他事件沒有分配,就暫時將該事件放到事件隊列中,隨后再按照FIFO順序一個個傳播。 2. 事件經(jīng)過一系列傳播后到達該類的事件過濾器eventFilter(),這個函數(shù)對該事件進行過濾,如果返回true則傳播終止。返回false則告訴Qt不過濾這個事件,繼續(xù)傳播。 3. 如果沒有過濾掉,則隨后會傳播到該類的event()函數(shù)(或其父類),在這個函數(shù)中會根據(jù)事件的所屬類型進行分配,調(diào)用相應(yīng)的事件處理函數(shù)。如果不需要再向它的父類傳播這個事件,則返回true告訴Qt應(yīng)該處理完這個事件了。否則,調(diào)用父類的event函數(shù)來保證由父類來處理這個事件,防止其他類型的事件被忽略掉。 4. 特定的事件處理函數(shù)進行處理。
接下來我們逐個討論這幾個函數(shù):
eventFilter
bool QObject::eventFilter(QObject *watched, QEvent *event)事件過濾函數(shù),會在event函數(shù)之前被調(diào)用。返回true則告訴Qt事件被過濾掉,反之繼續(xù)傳播給event函數(shù)。通常的實現(xiàn)形式為:
/*判斷對象指針watched是否是需要過濾掉事件的那個對象*//*通常和this比較或者和該類的某個成員變量比較*/if(watched == this) //或 if(watched == m_watched){ /*判斷事件類型是否是需要過濾的事件*/ if(event->type() == /*某個事件類型*/ ) { return true; }}return false;event
bool QObject::event(QEvent *e)如果成功分配掉事件則返回true;否則,調(diào)用父類的event函數(shù)防止其他類型事件被忽略掉。通常的實現(xiàn)形式為:
if(e->type() == /*event 1*/){ doThings1(); return true;}else if(e->type() == /*event 2*/){ doThings2(); return true;}//...關(guān)心的幾個類型的事件分配return QWidget::event(e); //調(diào)用父類的函數(shù)然后就是特定的事件處理函數(shù),舉個例子,如果我們需要對鼠標(biāo)點擊事件進行自定義的處理,那么我們就需要在自定義類中重新實現(xiàn)mousePRessEvent()函數(shù)。又因為這個函數(shù)是父類的虛函數(shù),我們無需重新實現(xiàn)event()函數(shù),所以可以像這樣:
//.h#include <QWidget>#include <QLabel>class MyClass : public QWidget{ Q_OBJECTpublic: MyClass(QWidget *parent = 0);protected: void mousePressEvent(QMouseEvent *event);private: QLabel *label;};//.cppMyClass::MyClass(QWidget *parent) :QWidget(parent){ label = new QLabel(); setCentralWidget(label);}void MyClass::mousePressEvent(QMouseEvent *event){ label->setText(QString("[%1, %2]") .arg(event->x(), event->y()));}新聞熱點
疑難解答