Qt的事件传递过程和事件过滤器的示例

每个程序main ()函数的最后都会调用QApplication类的exec()函数,它会使应用程序进入事件循环,这样就可以使应用程序在运行时接收发生的各种事件。一旦有事件发生,Qt便会构建一个相应的QEvent子类的对象来表示它,然后将它传递给相应的QObject对象或者其子类对象。
举例一:
新建Qt Widget应用,项目名为myevent,基类选择QWidget,类名保持Widget不变。
第一步:
添加一个MyLineEdit类,头文件为mylineedit.h,源文件为mylineedit.cpp
mylineedit.h代码为:

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>

class MyLineEdit : public QLineEdit
{
    Q_OBJECT

public:
    explicit MyLineEdit(QWidget * parent = nullptr);

protected:
    void keyPressEvent(QKeyEvent *event) override;
};

#endif // MYLINEEDIT_H

mylineedit.cpp代码为:

#include "mylineedit.h"

#include <QKeyEvent>
#include <QDebug>

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

void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
    qDebug() << "MyLineEdi键盘按下事件";
    QLineEdit::keyPressEvent(event);
//    event->ignore();
}

widget.h代码为:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class MyLineEdit;

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget() override;

protected:
    void keyPressEvent(QKeyEvent *event) override;

private:
    MyLineEdit *m_lineEdit;
};
#endif // WIDGET_H

widget.cpp代码为:

#include "widget.h"
#include "mylineedit.h"

#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    m_lineEdit = new MyLineEdit(this);
    m_lineEdit->move(100, 100);
}

Widget::~Widget()
{
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    Q_UNUSED(event)
    qDebug() << "Widget键盘按下事件";
}

运行结果为:
在这里插入图片描述

MyLineEdi键盘按下事件

改造一下:

void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
    qDebug() << "MyLineEdi键盘按下事件";
    QLineEdit::keyPressEvent(event);
    event->ignore();
}

在MyLineEdit中添加了event->ignore();
再运行:
在这里插入图片描述
在这里插入图片描述
这时候看到MyLineEdit的父窗口也响应了这个按键事件。

事件的传递
举例二
widget.h代码:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class MyLineEdit;

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget() override;

protected:
    bool event(QEvent *event) override;
    bool eventFilter(QObject *obj, QEvent *event) override;
    void keyPressEvent(QKeyEvent *event) override;

private:
    MyLineEdit *m_lineEdit;
};
#endif // WIDGET_H

widget.cpp代码:

#include "widget.h"
#include "mylineedit.h"

#include <QEvent>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    m_lineEdit = new MyLineEdit(this);
    m_lineEdit->move(100, 100);
    m_lineEdit->installEventFilter(this);
}

Widget::~Widget()
{
}

bool Widget::event(QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        qDebug() << "Widget的event()函数";
    }
    return QWidget::event(event);
}

bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == m_lineEdit)
    {
        if (event->type() == QEvent::KeyPress)
        {
            qDebug() << "Widget的事件过滤器";
//            return true;
        }
    }
    return QWidget::eventFilter(obj, event);
}

void Widget::keyPressEvent(QKeyEvent *event)
{
    Q_UNUSED(event)
    qDebug() << "Widget键盘按下事件";
}

mylineedit.h代码:

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>

class MyLineEdit : public QLineEdit
{
    Q_OBJECT

public:
    explicit MyLineEdit(QWidget * parent = nullptr);

protected:
    bool event(QEvent *event) override;
    void keyPressEvent(QKeyEvent *event) override;
};

#endif // MYLINEEDIT_H

mylineedit.cpp代码:

#include "mylineedit.h"

#include <QKeyEvent>
#include <QDebug>

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

}

bool MyLineEdit::event(QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        qDebug() << "MyLineEdit的event()函数";
    }
    return QLineEdit::event(event);
}

void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
    qDebug() << "MyLineEdi键盘按下事件";
    QLineEdit::keyPressEvent(event);
    event->ignore();
}

键盘上输入一个数字,或者字母
在这里插入图片描述
在这里插入图片描述
用图来表示事件的传播顺序:
在这里插入图片描述
对于事件过滤器的使用方法:
先在父窗口中注册需要安装接收某消息的控件安装事件过滤器:

m_lineEdit->installEventFilter(this);

然后重写父窗口的

bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == m_lineEdit)
    {
        if (event->type() == QEvent::KeyPress)
        {
            qDebug() << "Widget的事件过滤器";
//            return true;
        }
    }
    return QWidget::eventFilter(obj, event);
}

return true表示事件已经得到了处理,不必继续传播。(大家可以将return true;的注释去掉看看,会看到只会输出 “Widget的事件过滤器” 后消息就不再被传播了。)
return false表示事件需要继续传递。

return QWidget::eventFilter(obj, event);

这样写,是调用父类的eventFilter,也就是继续传播事件。

当过滤器的 eventFilter() 实现被调用的时候, 它就可以选择是处理该事件,还是转发该事件, 或禁止该事件继续被其它对象处理. 若所有的事件过滤器都允许一个事件可被继续处理( 每个过滤器处理后都返回 false ), 该事件最终将被发送到目标对象. 如果其中一个中止了这个流程(通过返回 true)。

文中的示例放在了百度云盘上:(大家有什么好的建议,我可以放到其他地方去。csdn下载太贵,要方便大家免费下载示例)
链接:https://pan.baidu.com/s/1GY7vrmpHkud7AnBi4uX2zw
提取码:om1l

参考:
Qt学习之路27–事件传递过程和事件过滤器
Qt学习之路26–事件处理、事件重写、关闭文本编辑器操作
详解 QT Event 以及 Event Filter 事件处理

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值