首页 > 代码库 > 第39课 Qt中的事件处理(下)

第39课 Qt中的事件处理(下)

1. 事件的传递过程

技术分享 

(1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序

(2)Qt应用程序收到系统消息后,将其转化为一个对应的事件对象,并将其分发出去。

(3)事件对应被分发到当前正在操作的窗口部件上,该窗口部件会调用event函数来处理,然后,在这个函数内部又会调用其他的子函数如KeyPress或mouseReleaseEvent)来进行具体的处理。

(4)event函数处理完后,可能会将当前事件传递给父组件(parent)对象。但这个过程只是一种可能,也就是有一部分会被传递,有些并不需要被传递。

2. QEvent中的关键成员函数:标志上只是在操作或判断一个标志位

(1)void ignore():事件的接收者忽略当前事件,事件可能传递给父组件

(2)void accept();事件的接收者期望处理当前事件,表明我们自己写了事件处理函数,一般不需要被父组件再处理了。

(3)bool isAccepted();判断当前事件是否被处理

【编程实验】事件处理的顺序

//main.cpp

#include "Widget.h"#include <QApplication>int main(int argc, char *argv[]){    QApplication a(argc, argv);    Widget w;    w.show();    return a.exec();}/*当在编辑框中按下按键时输出结果:(注意MyLineEdit的父组件,即w中的的event事件并未被触发MyLineEdit::eventMyLineEdit::keyPressEvent*/

//MyLineEdit.h

#ifndef MYLINEEDIT_H#define MYLINEEDIT_H#include <QLineEdit>class MyLineEdit : public QLineEdit{    Q_OBJECTpublic:    explicit MyLineEdit(QWidget* parent = 0);    bool event(QEvent* e);    void keyPressEvent(QKeyEvent* e);};#endif // MYLINEEDIT_H

//MyLineEdit.cpp

#include "MyLineEdit.h"#include <QKeyEvent>#include <QDebug>MyLineEdit::MyLineEdit(QWidget* parent):QLineEdit(parent){}bool MyLineEdit::event(QEvent* e){    if( e->type() == QEvent::KeyPress)    {        qDebug() << "MyLineEdit::event";    }    return QLineEdit::event(e);}void MyLineEdit::keyPressEvent(QKeyEvent* e){    qDebug() << "MyLineEdit::keyPressEvent";    QLineEdit::keyPressEvent(e);   // e->ignore(); //表示事件会继续传递给父组件,本例中为Widget对象                 //如果注释或e-accept()表示不再传递,则父组件的                 //event函数不会被触发}

//Widget.h

#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include "MyLineEdit.h"class Widget : public QWidget{    Q_OBJECTprivate:    MyLineEdit myLineEdit;public:    Widget(QWidget *parent = 0);    bool event(QEvent* e);    void keyPressEvent(QKeyEvent* e);    ~Widget();};#endif // WIDGET_H

//Widget.cpp

#include "Widget.h"#include <QEvent>#include <QDebug>Widget::Widget(QWidget *parent)    : QWidget(parent),myLineEdit(this){}//操作系统将消息转化为事件,并分发到了这个Widget,会首先调用//这个Wiget的event函数,该函数可以收到多种的系统事件,同时其内部会根据event//事件的类型调用相应的事件处理函数,如keyPressEvent()。比如,当发生按键事件时//会先调用event(),再调用后面的keyPressEvent()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);}Widget::~Widget(){}

3. Qt中的事件过滤器

(1)事件过滤器

  ①事件过滤器可以对其他组件接收到的事件进行监控

  ②任意的QObject对象都可以作为事件过滤器使用

  ③事件过滤器对象需要重写eventFilter()函数

(2)安装事件过滤器:installEventFilter()函数

  ①事件过滤器在组件之前接收到事件

  ②事件过滤器能够决定是否将事件转到到组件对象

 技术分享

(3)事件过滤器的典型实现

//场景:事件由A对象经Widget过滤后发给obj对象//返回true表示事件己经处理,无需再传递给obj对象了//返回false则正常传递到obj对象bool Widget::eventFilter(QObject* obj, QEvent* e){    if(/*根据obj判断是否是所需的目标对象*/)    {        if(/*根据e->type()判断是否是感兴趣的事件*/)        {            /*事件处理逻辑*/        }    }        /*调用父类中的同名函数*/    return QWidget::eventFilter(obj, e);}

【编程实验】事件过滤器的使用

 

4. 小结

(1)Qt应用程序有严格的事件处理顺序

(2)Qt事件在处理后可能传递给父组件对象

(3)可以通过installEventFilter()函数安装事件过滤器

(4)事件过滤器可以对其他组件接收到的事件进行监控

(5)事件过滤器能够决定是否将事件转发到组件对象

第39课 Qt中的事件处理(下)