如果对MFC有点了解,可以近似的把Qt的信号(signal)和事件(event)对应于MFC的命令(command)和消息(message) ,事件是窗口系统或者qt对不同情况的响应,绝大多数被产生的事件都是对用户行为的响应,但是也有一些,比如定时器事件,它们是被系统独立产生的。QWidget::event()虚函数是各种事件的一个大管家,负责把大多数常用类型的事件传递给特定的事件处理器(事件处理函数,也都是虚拟函数,便于其继承子类对于该事件处理的编程),可以分析一下事件总管QWidget::event()虚函数的部分源码(完整源码在C:/Qt/4.2.2/src/gui/kernel/qwidget.cpp中qwidget::event()函数的定义):
QEvent类实现对事件的封装。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); //将鼠标移动类型的事件分派给mouseMoveEvent函数处理 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派生类中重写响应的事件处理函数(覆盖默认的虚函数,如event,keyPressEvent等函数)来完成在该派生类对象中对该事件的响应。 关于对事件过滤器的编程,一般分两步: 1、通过对目标对象(被监视对象)调用installEventFilter()函数来注册监视对象; 2、在监视对象的eventFilter函数中处理目标对象的事件。(可以认为监视对象拦截了目标对象的事件) 下面用代码来说明事件处理处理和事件过滤: //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虚函数来处理特定的事件 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虚函数来拦截特定的事件 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()函数处理 } 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监视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) //判断监视拦截条件是否满足,如是,则拦截该事件 { ui.lineEdit->insert(tr("filter completed!")); return true; } return QMainWindow::eventFilter(target, event); } www::~www() { } 然后我们再来分析一下QObject::installEventFilter函数的源码,看其是如何实现过滤功能的: 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的文章. |
|