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()函数安装事件过滤器
事件过滤器可以对其他组件接收到的事件进行监控
事件过滤器能够决定是否将事件转发到组件对象