如果對MFC有點了解,可以近似的把Qt的信號(signal)和事件(event)對應(yīng)于MFC的命令(command)和消息(message) ,事件是窗口系統(tǒng)或者qt對不同情況的響應(yīng),絕大多數(shù)被產(chǎn)生的事件都是對用戶行為的響應(yīng),但是也有一些,比如定時器事件,它們是被系統(tǒng)獨立產(chǎn)生的。QWidget::event()虛函數(shù)是各種事件的一個大管家,負責(zé)把大多數(shù)常用類型的事件傳遞給特定的事件處理器(事件處理函數(shù),也都是虛擬函數(shù),便于其繼承子類對于該事件處理的編程),可以分析一下事件總管QWidget::event()虛函數(shù)的部分源碼(完整源碼在C:/Qt/4.2.2/src/gui/kernel/qwidget.cpp中qwidget::event()函數(shù)的定義):
QEvent類實現(xiàn)對事件的封裝。The QEvent class is the base class of all event classes. Event objects contain event parameters. bool QWidget::event(QEvent *event) { Q_D(QWidget); // ignore mouse events when disabled if (!isEnabled()) { switch(event->type()) { case QEvent::TabletPress: case QEvent::TabletRelease: case QEvent::TabletMove: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: case QEvent::ContextMenu: #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: #endif return false; default: break; } } switch (event->type()) { //判斷事件類型 case QEvent::MouseMove: mouseMoveEvent((QMouseEvent*)event); //將鼠標(biāo)移動類型的事件分派給mouseMoveEvent函數(shù)處理 break; case QEvent::MouseButtonPress: // Don't reset input context here. Whether reset or not is // a responsibility of input method. reset() will be // called by mouseHandler() of input method if necessary // via mousePressEvent() of text widgets. #if 0 resetInputContext(); #endif mousePressEvent((QMouseEvent*)event); break; case QEvent::MouseButtonRelease: mouseReleaseEvent((QMouseEvent*)event); break; case QEvent::MouseButtonDblClick: mouseDoubleClickEvent((QMouseEvent*)event); break; #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: wheelEvent((QWheelEvent*)event); break; #endif …… …… 然后在需要處理該事件的QWidget派生類中重寫響應(yīng)的事件處理函數(shù)(覆蓋默認的虛函數(shù),如event,keyPressEvent等函數(shù))來完成在該派生類對象中對該事件的響應(yīng)。 關(guān)于對事件過濾器的編程,一般分兩步: 1、通過對目標(biāo)對象(被監(jiān)視對象)調(diào)用installEventFilter()函數(shù)來注冊監(jiān)視對象; 2、在監(jiān)視對象的eventFilter函數(shù)中處理目標(biāo)對象的事件。(可以認為監(jiān)視對象攔截了目標(biāo)對象的事件) 下面用代碼來說明事件處理處理和事件過濾: //newlineedit.h #ifndef NEWLINEEDIT_H #define NEWLINEEDIT_H #include <QLineEdit> #include "ui_newlineedit.h" class newLineEdit : public QLineEdit { Q_OBJECT public: newLineEdit(QWidget *parent = 0); ~newLineEdit(); bool event(QEvent *event); //重寫event虛函數(shù)來處理特定的事件 private: Ui::newLineEditClass ui; }; #endif // NEWLINEEDIT_H //www.h #ifndef WWW_H #define WWW_H #include <QtGui/QMainWindow> #include "ui_www.h" class www : public QMainWindow { Q_OBJECT public: www(QWidget *parent = 0, Qt::WFlags flags = 0); ~www(); bool eventFilter(QObject *target, QEvent *event); //重寫eventFilter虛函數(shù)來攔截特定的事件 private: Ui::wwwClass ui; }; #endif // WWW_H //newlineedit.cpp #include "newlineedit.h" #include <QKeyEvent> newLineEdit::newLineEdit(QWidget *parent) : QLineEdit(parent) { ui.setupUi(this); } bool newLineEdit::event(QEvent *event) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = (QKeyEvent *)event; if (keyEvent->key() == Qt::Key_Tab) //判斷特定的事件,作出自定義的處理 { insert("/t"); return true; } } return QWidget::event(event); //將不需要特定處理的事件交給默認的基類event()函數(shù)處理 } newLineEdit::~newLineEdit() { } //www.cpp #include "www.h" #include <QKeyEvent> www::www(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { ui.setupUi(this); ui.lineEdit->installEventFilter(this); //注冊this監(jiān)視ui.lineEdit對象,this攔截ui.lineEdit的某些事件 bool www::eventFilter(QObject *target, QEvent *event) { if (target == ui.lineEdit && event->type() == QEvent::KeyPress && ((QKeyEvent *)event)->key() == Qt::Key_Tab) //判斷監(jiān)視攔截條件是否滿足,如是,則攔截該事件 { ui.lineEdit->insert(tr("filter completed!")); return true; } return QMainWindow::eventFilter(target, event); } www::~www() { } 然后我們再來分析一下QObject::installEventFilter函數(shù)的源碼,看其是如何實現(xiàn)過濾功能的: void QObject::installEventFilter(QObject *obj) { Q_D(QObject); if (!obj) return; QWriteLocker locker(QObjectPrivate::readWriteLock()); // clean up unused items in the list d->eventFilters.removeAll((QObject*)0); d->eventFilters.removeAll(obj); d->eventFilters.prepend(obj); } 可以參考下一篇分析QObject的文章. |
|