1. 回顾事件传递的过程
Qt 中的事件处理(二)
①源头:操作系统   操作系统检测到用户的动作时,就会产生一个系统消息,系统消息就会被发送到正在运行的Qt应用程序中,
应用程序收到系统消息后, 他会将系统消息翻译成对应的QEvent事件对象,并调用QObject::event()将该对象分发下去,
③事件对象被分发到当前用户正在操作的窗口部件上去 ,该窗口部件是一个Qwidget的子类对象,该对象收到这个事件之后, 就会调用QWidget::event()函数来处理 ,该函数内部再调用其他的子函数(如KeyPressEvent或mouseReleaseEvent)进行具体的事件处理。
④可能会再被出传递到其父组件对象
 Qt 中的事件处理(二)

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

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

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

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

 

2. QEvent及其子类对象涉及的关键成员函数:实际上只是在操作或判断一个标志位

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

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

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

 

事件传递流程①事件先传递给指定窗口部件,确切的说传递给获得焦点窗口的部件,②如果该部件忽略该事件,那么这个事件就会传递给其父组件
还需要注意当重新实现事件处理函数时,一般需要调用父组件的相应事件处理函数来实现其默认的行为
如:
void MyLineEdit::keyPressEvent(QKeyEvent *e)
{
qDebug()<<"MyLineEdit::keyPressEvent";
    QLineEdit::keyPressEvent(e);// 执行QLineEdit类的默认事件处理
 }

 实例事件处理的顺序

//main.cpp

Qt 中的事件处理(二)
#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::event
MyLineEdit::keyPressEvent
*/
View Code

//MyLineEdit.h

Qt 中的事件处理(二)
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>

class MyLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit MyLineEdit(QWidget* parent = 0);
    bool event(QEvent* e);
    void keyPressEvent(QKeyEvent* e);
};

#endif // MYLINEEDIT_H
View Code

//MyLineEdit.cpp

Qt 中的事件处理(二)
#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函数不会被触发
}
View Code

//Widget.h

Qt 中的事件处理(二)
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "MyLineEdit.h"

class Widget : public QWidget
{
    Q_OBJECT

private:
    MyLineEdit myLineEdit;

public:
    Widget(QWidget *parent = 0);

    bool event(QEvent* e);
    void keyPressEvent(QKeyEvent* e);

    ~Widget();
};

#endif // WIDGET_H
View Code

//Widget.cpp

Qt 中的事件处理(二)
#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()
{

}
View Code

相关文章: