您的位置:首页 > 编程语言 > Qt开发

Qt:Event Filter事件过滤器

2015-08-04 11:13 507 查看
vent filter是什么?

EventFilter即所谓事件过滤器,在Qt中是一个比较重要的概念,它的功能是把所有事件在到达watchee(被监控者)之前全部传递给另一个watcher(监控者),由watcher先行处理并决定是否继续传递该事件,如果继续传递, 则事件将回传给watchee来处理。

event filter的常见应用场合

用来处理热键 -- 比如一个界面上可以由用户热键来触发的多个按钮。 由于只有得到焦点的控件才能获得键盘的事件, 如果不用event filter就需要给每个button都加上键盘事件的处理, 还要在button里去访问兄弟button的指针,逻辑非常混乱。如果由主窗体做各个按钮的eventFilter, 则只需要在主窗体里去处理键盘事件就好,而且主窗体可以很容易的访问到各个button的指针,很方便。

在监测的代码里执行需要的行为.,这可以用event Filter来达到,设置一个event filter有两个步骤:

1. 在目标对象上调用installEventFilter(),将监测对象注册到目标对象上。

2. 在监测对象的eventFilter()方法里处理目标对象的事件。

在ctor里注册监测对象是一个好地方:

CustomerInfoDialog::CustomerInfoDialog(QWidget *parent) :QDialog(parent)

{

...

firstNameEdit->installEventFilter(this);

lastNameEdit->installEventFilter(this);

cityEdit->installEventFilter(this);

phoneNumberEdit->installEventFilter(this);

}

一旦event Filter注册了, 发送到firstNameEdit,lastNameEdit,cityEdit和phoneNumberEdit的事件在被发送到原来的目的地之前, 会先发到CustomerInfoDialog的eventFilter()函数.

这是接收这些事件的eventFilter()函数:

bool CustomerInfoDialog::eventFilter(QObject *target, QEvent *event)

{

if (target == firstnameEdit || target == lastNameEdit

|| target == cityEdit || target == phoneNumberEdit)

{

if(event->type() == QEvent::KeyPress)

{

QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);

if (keyEvent->key() == Qt::Key_Space)

{

focusNextChild();

return true;

}

}

}

return QDialog::eventFilter(target, event);

}

用来代替派生和重写虚函数 -- Qt里的键盘鼠标事件基本上都是以虚函数的方式来处理,要想重写虚函数则必须派生一个子类,这样的话如果只是一个简单的事件处理也去派生子类代价未免大了些,这时候就值得用用eventFilter。比如我的MDI界面想在每个子窗体关闭的时候做一些统一的操作,一般的做法是处理子窗体的closeEvent。但显然给每个子窗体都去派生个子类太不现实,最好的方法是把mainwindow作为子窗体的eventFilter去处理CloseEvent事件。

这里只举了两个例子, 相信聪明的同学们能在自己的程序中找到适合eventFilter发挥的位置。

如何使用event filter处理事件?

两个级别的event filter, 一个是为QApplication类安装一个eventFilter, 另一个是针对某个控件来安装eventFilter。 本质上这两个级别的event filter调用的都是QObject类提供的API:“installEventFilter”。

event filter的使用有点曲折, 有两个步骤要做。一是要调用watchee的installEventFilter以watcher指针为参数

watchee->installEventFilter(watcher);

二是在watcher的类中实现bool eventFilter(QObject*, QEvent*) 这个虚函数,在此函数中处理事件。
class KeyPressEater : public QObject

{

Q_OBJECT

...

protected:

bool eventFilter(QObject *obj, QEvent *event);

};

bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)

{

if (event->type() == QEvent::KeyPress)

	{

QKeyEvent *keyEvent = static_cast(event);

qDebug("Ate key press %d", keyEvent->key());

return true;

}

else

{
// standard event processing

return QObject::eventFilter(obj, event);

}

}


上面的例子代码是直接从Qt文档里抄的

其中几点需要注意的地方:

- watchee和watcher必须都是从QObject派生的子类实例

- watcher的类必须是一个自定义的子类(因为需要重新实现虚函数, 用现成的类是不行的。)

- watcher类的eventFilter函数返回true时表示该事件处理完毕,不再继续传递;返回false表示该事件仍然传递

- eventFilter的实现的最后必须调用watcher基类的eventFilter函数以传递事件。如果不调的话watcher的所有事件都将丢失。

- 注意eventFilter的声明必须和文档里的一模一样, 写的时候注意返回值、大小写和参数类型

其他

在Qt中还有一些应用程序级别的eventFilter函数, 是和平台相关的,如x11EventFilter可以截获程序得到的所有X事件。相应的Windows平台下用winEventFilter… 大家不要被函数的名字给误导了, 这些函数并不是全局级别的,充其量只能拿到应用程序内部的事件,想做系统级别的事件过滤还是差着档次…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: