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

1、Qt中的事件处理 

事件的传递过程 

                                     事件被组件对象处理后可能传递到其父组件对象 

QEvent中的关键成员函数 

         - void ignore(); 

                接收者忽略当前事件,事件可能传递给父组件

         - void accept(); 

                接收者期望处理当前事件 (不绝对)

         - bool isAccepted(); 

                判断当前事件是否被处理 

 

2、编程实验 

事件处理的顺序    39-1.pro 

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

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

class Widget : public QWidget
{
    Q_OBJECT
    
    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 <QDebug>
#include <QEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent), myLineEdit(this)
{

}
 
bool Widget::event(QEvent* e) //Qt事件被event函数处理
{
    if( e->type() == QEvent::KeyPress ) //当处理的事件是按键事件
    {
        qDebug() << "Widget::event";
    }

    return QWidget::event(e);//根据事件的类型调用keyPressEvent()事件处理函数处理
}

void Widget::keyPressEvent(QKeyEvent* e)//注意事件类型是QKeyEvent
{
    qDebug() << "Widget::keyPressEvent";

    QWidget::keyPressEvent(e);//调用父类的事件处理函数
}

Widget::~Widget()
{
    
}

MyLineEdit.h

#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);
signals:
    
public slots:
    
};

#endif // MYLINEEDIT_H

MyLineEdit.cpp

#include "MyLineEdit.h"
#include <QDebug>
#include <QEvent>
#include <QKeyEvent>

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();告诉Qt平台事件没有被处理,会调用父组件event函数处理
}

main.cpp

#include <QtGui/QApplication>
#include "Widget.h"

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

                           Qt事件被分配到MyLineEdit,调用自身event函数进行事件处理

                                      根据事件类型不同调用不同的事件处理函数

当取消 e->ignore();注释

                                               调用了父组件的event函数处理事件

3、Qt中的事件处理 

Qt中的事件过滤器 

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

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

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

 

被监控组件通过installEventFilter()安装事件过滤器 

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

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

事件过滤器的典型实现 

4、编程实验 

事件过滤器的使用   39-2.pro 

Widget.cpp(其它同上代码)

#include "Widget.h"
#include <QDebug>
#include <QEvent>
#include <QKeyEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent), myLineEdit(this)
{
    myLineEdit.installEventFilter(this);//被监控组件安装事件过滤器
}

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);
}

bool Widget::eventFilter(QObject* obj, QEvent* e)//事件过滤对象重写eventFilter函数
{
    bool ret = true;

    if( (obj == &myLineEdit) && (e->type() == QEvent::KeyPress) )//当被监控组件为myLineEdit且事件为按下按键
    {
        qDebug() << "Widget::eventFilter";

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

        switch(evt->key())//当键入数字时,事件被myLineEdit正常接收,其它都被没收
        {
        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, e);
    }

    return ret;
}

Widget::~Widget()
{
    
}

当按下除数字以外的键时

                                                  发现字母等都被过滤,MyLineEdit对象没有接收到时间

当按下数字键时

5、小结 

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

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

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

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

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

猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/81543824