一、Qt中事件处理的顺序
1、事件传递的过程
(1)、事件被组件对象处理后可能传递到其父组件对象
2、QEvent中的关键成员函数
#include "Widget.h" #include <QEvent> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) { } Widget::~Widget() { } bool Widget::event(QEvent* e) { if(e->type()==QEvent::KeyPress) { qDebug() << "Widget::event"; } return QWidget::event(e); } void Widget::keyPressEvent(QKeyEvent* e) { qDebug() << "Widget::keyPressEvent";//1.会先打印Widget::event再打印Widget::keyPressEvent //即先被事件总的事件函数处理,再在里面调用相应的事件处理函数 QWidget::keyPressEvent(e); }
实验二:
#ifndef MYEDIT_H #define MYEDIT_H #include <QLineEdit> class MyEdit : public QLineEdit { Q_OBJECT public: bool event(QEvent* e); void keyPressEvent(QKeyEvent* e); explicit MyEdit(QWidget *parent = 0); signals: public slots: }; #endif // MYEDIT_H
#include "MyEdit.h" #include <QDebug> #include <QEvent> #include <QKeyEvent> MyEdit::MyEdit(QWidget *parent) : QLineEdit(parent) { } bool MyEdit::event(QEvent* e) { if(e->type()==QEvent::KeyPress) { qDebug() << "MyEdit::event"; } return QLineEdit::event(e); } void MyEdit::keyPressEvent(QKeyEvent* e) { qDebug() << "MyEdit::keyPressEvent"; QLineEdit::keyPressEvent(e); //e->ignore();没有这句时只打印MyEdit::event和MyEdit::keyPressEvent,有这句时 //打印 MyEdit::event和MyEdit::keyPressEvent、Widget::event和 Widget::keyPressEvent 说明可能传给父对象处理 }
#ifndef WIDGET_H #define WIDGET_H #include <QtGui/QWidget> #include "MyEdit.h" class Widget : public QWidget { Q_OBJECT MyEdit myEdit; public: bool event(QEvent* e); void keyPressEvent(QKeyEvent* e); Widget(QWidget *parent = 0); ~Widget(); }; #endif // WIDGET_H
#include "Widget.h" #include <QEvent> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent), myEdit(this) { } Widget::~Widget() { } bool Widget::event(QEvent* e) { if(e->type()==QEvent::KeyPress) { qDebug() << "Widget::event"; } return QWidget::event(e); } void Widget::keyPressEvent(QKeyEvent* e) { qDebug() << "Widget::keyPressEvent"; QWidget::keyPressEvent(e); }
#include <QtGui/QApplication> #include "Widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
二、Qt事件的过滤器
1、Qt中的事件过滤器
(1)、事件过滤器可以对其它组件接收到的事件进行监控
(2)、任意的QObject对象都可以作为事件过滤器使用
(3)、事件过滤器对象需要重写evenFilter()函数
2、组件通过installEventFilter()函数安装事件过滤器
(1)、事件过滤器在组件之前接收到事件
(2)、事件过滤器能够决定是否将事件转发到组件对象
3、事件过滤器的典型实现
//1.判断是不是感兴趣的对象和事件 //2.若是,就决定是没收还是还是继续转发给感兴趣的对象 //3.若不是,就按默认的方式处理事件 //4.最后一定安装过滤器 bool Widget::eventFilter(QObject* obj, QEvent* e) { bool ret = true; if(obj == &myEdit && (e->type() == QEvent::KeyPress)) { qDebug() << "Widget::eventFilter"; QKeyEvent* evt = dynamic_cast<QKeyEvent*>(e); switch(evt->key()) { case Qt::Key_0://若按下0-9,则事件被传到文本框处理,输出,若不是,什么也不显示 case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4: case Qt::Key_5: case Qt::Key_6: case Qt::Key_7: case Qt::Key_8: case Qt::Key_9: ret = false;//如果是0-9,ret仍然是true,此时就会传递到感兴趣的对象 break; default: break; } } else { ret = QWidget::eventFilter(obj, e);//如果不是感兴趣的事件或者对象,就按照默认方式处理 } return ret;//返回true说明事件已被处理,返回false说明事件还未处理 }
安装过滤器:
其它代码和上个例子一样
三、小结
(1)、Qt应用程序有严格的事件处理顺序
(2)、Qt事件在处理后可能传递给父组件对象
(3)、组件通过installEventFilter()函数安装事件过滤器
(4)、事件过滤器可以对其它组件接收到的事件进行监控
(5)、事件过滤器能够决定是否将事件转发到组件对象