QT中事件处理(下--Qt中事件处理的具体方法)

在上一篇博客中,我们深入分析了QT中事件处理的相关机制,在这篇博客中我们将来深入分析一下QT中事件处理的具体方法。

首先,我们来回顾一下,事件的传递过程是怎么样的?

             

                                                               QT中事件的传递的具体过程

分析一下上述流程图可以总结为下面的流程过程:

1.用户操作相关的GUI应用程序,首先由操作系统感受到用户的操作,然后操作系统会把用户的操作翻译成一条系统消息

2.这个系统消息就会发送到当前用户正在使用的QT应用程序上去(或者这样表达,当前具有焦点的应用程序上去),QT应用程序收到了系统消息就会做一个翻译的动作,将系统消息翻译成为一个QT事件对象。并且将这个QT事件对象分发下去。

3.那么分发到哪里去呢?就分发到用户正在操作的QT窗口部件上去,那么这个窗口部件毫无疑问是一个QWidget子类的窗口部件对象。

4.那么这个QWidget子类对象收到事件对象后会做什么事情呢?它就会调用QEvent()事情处理函数,那么这个事件处理函数又会调用其他的子函数进行事件处理。那么处理完成之后会怎么做呢?看到图片上的3:QEvent()蓝色的箭头吗?当窗口部件QWidget(Child)处理完成事件之后,就可能将事件传送到它的父组件QWidget(Parent)上去。只是可能传递到它的父组件上去,这个传递不是一定的,不是绝对的!就是有一些事件对象在处理完事件之后,会被传递到它的父组件对象进行继续处理,但是有一些事情对象在处理完事件之后,不会传递它的父组件对象进行继续处理。

(这个就是蓝色箭头的意义,事件被组件对象处理之后,只是有可能被传递到它的父组件进行再一次的进行处理。操作系统会检测用户的各种动作,而用户的动作肯定是各不相同的,因此操作系统发送的系统消息肯定也是成百上千的,又因为每一种系统消息会被转化为QT的事件,所以对应的QT事件也是成百上千的,这就说明了这些不同的事件被处理的方式可能是不同的,没有办法用统一的方法来处理不同的事件。所以对于不同的事件必须有不同的处理方法,因此有一些事件被处理之后会被传递它的父组件进行再一次的处理,而有的事件就不会传递到它的父组件进行处理了。)

下面来用程序证明上述的原理:

#ifndef WIDGET_H
#define WIDGET_H

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

class Widget : public QWidget
{
    Q_OBJECT
private:
    MyLineEdit m_lineEdit;
public:
    Widget(QWidget *parent = 0);
    bool event(QEvent* evt);
    void keyPressEvent(QKeyEvent* evt);
    bool eventFilter(QObject* obj, QEvent* evt);
    ~Widget();
};

#endif // WIDGET_H
#include "Widget.h"
#include <QEvent>
#include <QKeyEvent>
#include <QDebug>

Widget::Widget(QWidget *parent): QWidget(parent),m_lineEdit(this)
{
       m_lineEdit.installEventFilter(this);
}

bool Widget::event(QEvent* evt)
{
    if(evt->type()==QEvent::KeyPress)
    {
        qDebug()<<"Widget::event:"<<evt->type();
    }

    return QWidget::event(evt);
}

void Widget::keyPressEvent(QKeyEvent* evt)
{
    qDebug()<<"Widget::keyPressEvent:"<<evt->type();

    QWidget::keyPressEvent(evt);
}

bool Widget::eventFilter(QObject* obj, QEvent* evt)
{
    bool ret=true;

    if((obj==&m_lineEdit) && (evt->type()==QEvent::KeyPress))
    {
        qDebug()<<"Widget::eventFilter";

        QKeyEvent* e=dynamic_cast<QKeyEvent*>(evt);

        switch(e->key())
        {
            case Qt::Key_0:
            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;
                break;
            default:
                break;
        }
    }
    else
    {
        ret=QWidget::eventFilter(obj,evt);
    }

    return ret;
}

Widget::~Widget()
{
    
}
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>

class MyLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit MyLineEdit(QWidget *parent = 0);

    bool event(QEvent* evt);
    void keyPressEvent(QKeyEvent* evt);
    
};

#endif // MYLINEEDIT_H
#include "MyLineEdit.h"
#include <QEvent>
#include <QKeyEvent>
#include <QDebug>

MyLineEdit::MyLineEdit(QWidget *parent) :QLineEdit(parent)
{

}

bool MyLineEdit::event(QEvent* evt)
{
    if(evt->type()==QEvent::KeyPress)
    {
        qDebug()<<"MyLineEdit::event:"<<evt->type();
    }

    return QLineEdit::event(evt);
}

void MyLineEdit::keyPressEvent(QKeyEvent* evt)
{
    qDebug()<<"MyLineEdit::keyPressEvent:"<<evt->type();

    QLineEdit::keyPressEvent(evt);

    evt->ignore();
}
#include <QtGui/QApplication>
#include "Widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}

 

分析上述程序的运行结果可知:

1.首先我们知道调用的是bool event(QEvent* evt)事件处理函数,这个event()事件处理函数是整个事件的入口函数,然后在这个事件入口函数中,继续调用内部的字事件处理函数,void keyPressEvent(QKeyEvent* evt)。

2.因为在void MyLineEdit::keyPressEvent(QKeyEvent* evt) 这个函数中调用了 evt->ignore() 函数,所以子类对象组件没有将事件处理完,将事件发送到它的父组件Widget中去了。

来再来看重点这一段程序运行的结果分析:

我们知道事件过滤器可以对其他组件接受的事件进行监控,事件过滤器在组件之前接收到事件,当我们重写eventFilter()函数的时候,就可以让事件过滤器能够决定是否将事件转发到组件对象。像上述例子中,只有在文本框中输入0-9数字的时候,才没有过滤掉事件,输入其他按键的时候都会过滤掉事件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

repinkply

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值