1. 事件过滤器
void QObject::installEventFilter(QObject *filterObj)
bool eventFilter(QObject *obj, QEvent *event);
filterObj表示事件筛选器对象,它接收发送到此QObject对象(安装事件过滤器的部件对象)的所有事件。筛选器可以停止事件(返回true),也可以将事件转发给此QObject对象(返回false)。事件过滤器filterObj通过它的eventFilter()函数接收事件。
//举例说明:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
lineEdit = new MyLineEdit(this); //在部件A建立部件B,部件A即B的父部件
lineEdit->move(100, 100);
lineEdit->installEventFilter(this); // 在Widget上为lineEdit安装事件过滤器
}
/*
* 此时filterObj为this:表示窗口部件Widget。Widget接收发送到lineEdit对象的全部事件。
* 可以这样理解:一个部件安装了事件筛选器对象是其父部件的事件过滤器,则其父部件可以接收其全部事件。
*/
2. 接收事件
在Qt中,事件过滤器的eventFilter函数返回值表示该事件是否被事件过滤器拦截,即是否停止事件的传递。返回值是一个布尔类型的值:
1)当返回true时,表示事件已被过滤器拦截,不会传递给被监听的对象进行处理;
2)当返回false时,事件会继续传递给被监听的对象进行处理。
3)返回给基类进行处理,例:return QObject::eventFilter(obj, event);(可以理解为:没有条件的递归,即死循环递归调用自己)。
按F1打开帮助文档
注意:
1)eventFilter函数一般会被重写,返回true/false是程序员自己在程序里手动添加的;
2)return QObject::eventFilter(obj, event)具体值,其实也是每次调用自己,根据是否有手动添加的true/false来决定的。默认不过滤,返回false.
3. 事件的传递(通过4实例中的键盘按下事件举例)
4. 实例
//mylineedit.cpp
#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>
MyLineEdit::MyLineEdit(QWidget *parent) :
QLineEdit(parent)
{
}
void MyLineEdit::keyPressEvent(QKeyEvent *event) // 键盘按下事件
{
qDebug() << tr("MyLineEdit键盘按下事件");
QLineEdit::keyPressEvent(event); // 执行QLineEdit类的默认事件处理
//事件是先传递给指定窗口部件的,这里确切的说应该是先传递给获得焦点的窗口部件的。但是如果该部件忽略掉该事件,那么这个事件就会传递给这个部件的父部件。
event->ignore(); // 忽略该事件
}
bool MyLineEdit::event(QEvent *event) // 事件
{
if(event->type() == QEvent::KeyPress)
qDebug() << tr("MyLineEdit的event()函数");
return QLineEdit::event(event); // 执行QLineEdit类event()函数的默认操作
}
//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
lineEdit = new MyLineEdit(this); //在部件A建立部件B,部件A即B的父部件
lineEdit->move(100, 100);
lineEdit->installEventFilter(this); // 在Widget上为lineEdit安装事件过滤器
}
Widget::~Widget()
{
delete ui;
}
void Widget::keyPressEvent(QKeyEvent *event)
{
Q_UNUSED(event);
qDebug() << tr("Widget键盘按下事件");
}
bool Widget::eventFilter(QObject *obj, QEvent *event) // 事件过滤器
{
if(obj == lineEdit){ // 如果是lineEdit部件上的事件
if(event->type() == QEvent::KeyPress){
qDebug() << tr("Widget的事件过滤器");
}
}
return QWidget::eventFilter(obj, event);
}
测试结果:
总结:
1)只有installEventFilter,没有eventFilter,事件依旧不会被提前捕获接收。必须成对存在。
2)没有event 事件传递依旧成立。