Qt的Event Filter(转)

event filter是什么?
EventFilter即所谓事件过滤器, 在Qt中是一个比较重要的概念, 它的功能是把所有事件在到达watchee(被监控者)之前全部传递给另一个watcher(监控者), 由watcher先行处理并决定是否继续传递该事件, 如果继续传递, 则事件将回传给watchee来处理。 可能很多人已经知道怎么用event filter处理事件了, 不过你也别嫌本文太简单, 毕竟总是不断的有新人提出类似的问题, 就当是复习一下吧。

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

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

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

如何使用event filter处理事件?
在前面的一篇blog中, 作者bug介绍了Qt中事件传递的顺序(如果没看过的先来扫扫盲), 其中就提到了两个级别的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;//返回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… 大家不要被函数的名字给误导了, 这些函数并不是全局级别的, 充其量只能拿到应用程序内部的事件, 想做系统级别的事件过滤还是差着档次…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来回答您的问题。Qt中的事件过滤器(Event Filter)是一个对象,它可以拦截并处理所有的事件,例如鼠标事件、键盘事件等等。事件过滤器可以用于拦截事件并进行自定义处理,从而实现一些特殊的功能。 在Qt中,事件过滤器是通过重载QObject类的eventFilter方法来实现的。当一个事件发生时,该事件会被发送到QObject对象的event方法中处理。如果该对象设置了事件过滤器,则事件会被先发送到事件过滤器的eventFilter方法中处理。在事件过滤器中,可以对事件进行拦截、修改或者直接处理,并返回一个布尔值来指示是否继续将事件传递给目标QObject对象。 以下是一个简单的示例代码,演示了如何在Qt中使用事件过滤器: ```c++ // 创建一个事件过滤器对象 class MyEventFilter : public QObject { public: explicit MyEventFilter(QObject *parent = nullptr); protected: bool eventFilter(QObject *obj, QEvent *event) override; }; MyEventFilter::MyEventFilter(QObject *parent) : QObject(parent) { } bool MyEventFilter::eventFilter(QObject *obj, QEvent *event) { // 在这里处理事件 if (event->type() == QEvent::MouseButtonPress) { qDebug() << "Mouse button pressed!"; // 返回true表示事件被处理完毕,不会继续传递给目标QObject对象 return true; } // 返回false表示事件继续传递给目标QObject对象 return QObject::eventFilter(obj, event); } // 将事件过滤器对象安装到目标QObject对象上 QObject *targetObject = ...; MyEventFilter *eventFilter = new MyEventFilter(); targetObject->installEventFilter(eventFilter); ``` 在上述代码中,我们创建了一个MyEventFilter类来作为事件过滤器对象。在eventFilter方法中,我们判断了当前事件的类型,如果是鼠标按下事件,则输出一条调试信息,并返回true,表示事件已经被处理完毕。如果不是鼠标按下事件,则返回false,表示事件继续传递给目标QObject对象。 最后,我们将事件过滤器对象安装到目标QObject对象上,这样事件就会先被发送到事件过滤器中进行处理,然后再传递给目标QObject对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值