Qt创建了QEvent事件对象之后,会调用QObject的event()函数做事件的分发。有时候,你可能需要在调用event()函数之前做一些另外的操作,比如,对话框上某些组件可能并不需要响应回车按下的事件,此时,你就需要重新定义组件的event()函数。如果组件很多,就需要重写很多次event()函数,这显然没有效率。为此,你可以使用一个事件过滤器,来判断是否需要调用event()函数。

QOjbect有一个eventFilter()函数,用于建立事件过滤器。这个函数的签名如下:

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event )

如果watched对象安装了事件过滤器,这个函数会被调用并进行事件过滤,然后才轮到组件进行事件处理。在重写这个函数时,如果你需要过滤掉某个事件,例如停止对这个事件的响应,需要返回true。

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
 {
         if (obj == textEdit) {
                 if (event->type() == QEvent::KeyPress) {
                         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
                         qDebug() << "Ate key press" << keyEvent->key();
                         return true;
                 } else {
                         return false;
                 }
         } else {
                 // pass the event on to the parent class
                 return QMainWindow::eventFilter(obj, event);
         }
 }

上面的例子中为MainWindow建立了一个事件过滤器。为了过滤某个组件上的事件,首先需要判断这个对象是哪个组件,然后判断这个事件的类型。例如,我不想让textEdit组件处理键盘事件,于是就首先找到这个组件,如果这个事件是键盘事件,则直接返回true,也就是过滤掉了这个事件,其他事件还是要继续处理,所以返回false。对于其他组件,我们并不保证是不是还有过滤器,于是最保险的办法是调用父类的函数。

在创建了过滤器之后,下面要做的是安装这个过滤器。安装过滤器需要调用installEventFilter()函数。这个函数的签名如下:

void QObject::installEventFilter ( QObject * filterObj )

这个函数是QObject的一个函数,因此可以安装到任何QObject的子类,并不仅仅是UI组件。这个函数接收一个QObject对象,调用了这个函数安装事件过滤器的组件会调用filterObj定义的eventFilter()函数。例如,textField.installEventFilter(obj),则如果有事件发送到textField组件是,会先调用obj->eventFilter()函数,然后才会调用textField.event()。

当然,你也可以把事件过滤器安装到QApplication上面,这样就可以过滤所有的事件,已获得更大的控制权。不过,这样做的后果就是会降低事件分发的效率。

如果一个组件安装了多个过滤器,则最后一个安装的会最先调用,类似于堆栈的行为。

注意,如果你在事件过滤器中delete了某个接收组件,务必将返回值设为true。否则,Qt还是会将事件分发给这个接收组件,从而导致程序崩溃。

事件过滤器和被安装的组件必须在同一线程,否则,过滤器不起作用。另外,如果在install之后,这两个组件到了不同的线程,那么,只有等到二者重新回到同一线程的时候过滤器才会有效。

事件的调用最终都会调用QCoreApplication的notify()函数,因此,最大的控制权实际上是重写QCoreApplication的notify()函数。由此可以看出,Qt的事件处理实际上是分层五个层次:重定义事件处理函数,重定义event()函数,为单个组件安装事件过滤器,为QApplication安装事件过滤器,重定义QCoreApplication的notify()函数。这几个层次的控制权是逐层增大的。

转自:http://devbean.blog.51cto.com/448512/231861

延伸:http://blog.csdn.net/michealtx/article/details/6865891 Qt事件处理的五个层次

Qt 事件过滤器的更多相关文章

  1. QT事件过滤器(QT事件处理的5个层次:自己覆盖或过滤,父窗口过滤,Application过滤与通知)

    Qt事件模型一个真正强大的特色是一个QObject 的实例能够管理另一个QObject 实例的事件. 让我们试着设想已经有了一个CustomerInfoDialog的小部件.CustomerInfoD ...

  2. Qt事件过滤器和事件的发送

    事件过滤器 /* *事件过滤器不是类,仅仅是QObject类的两个函数:installEventFilter() 和 eventFilter() . *下面讲个例子: * 监视过滤 textEdit的 ...

  3. qt事件过滤器的使用(可以用于控制屏幕背光等)

    在嵌入式qt项目中,有时并不需求屏幕一直亮着,需要一段时间不操作时,将屏幕背光关掉,以达到节能的目的: 在qt项目中,可以通过重写事件过滤器来实现屏幕操作的检测,加上定时器的时间控制,可以实现指定时间 ...

  4. Qt事件过滤器Event Filter

    事件过滤器针对一类或者多种不同类型的对象,定义了重写操作. 简单的说: 1.先对UI对象注册Event Filter 例如:    ui->drawBtn->installEventFil ...

  5. QT 事件过滤器 eventFilter

    在监测的代码里执行需要的行为. 这可以用event Filter来达到. 设置一个event filter有两个步骤: 1. 在目标对象上调用installEventFilter(),将监测对象注册到 ...

  6. Qt如何在QTabWidget上绘图

    Qt绘图事件必须在paintEvent事件下绘图,这样导致我们在向Qt设计师界面上拖拽的控件绘图时,造成了很大的麻烦. 我们不能在拖拽的控件上写paintEvent函数,但是可以自定义一个类,继承某一 ...

  7. QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL

    QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL 课程1   C语言程序设计高级实用速成课程 基础+进阶+自学 课程2   C语言程序设计Windows GDI图形绘 ...

  8. Qt入门(8)——事件和事件过滤器

    在Qt里,一个事件是继承自QEvent的对象.事件通过调用QObject::event(),被发送到继承自 QObject 的对象.事件发送就是一个事件已经产生,由 QEvent正好去表达,且QObj ...

  9. Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)

    Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的.下面举例说明: 1)首先看看下面一段示例代码: in ...

随机推荐

  1. PopupWindow的简单使用(结合RecyclerView)

    Android弹窗: 在Android中弹出式菜单(以下称弹窗)是使用十分广泛一种菜单呈现的方式,弹窗为用户交互提供了便利.关于弹窗的实现大致有以下两种方式AlertDialog和PopupWindo ...

  2. 具体解释java中的volatilekeyword

    一.为什么要有volatilekeyword 预计非常多java刚開始学习的人都被volatile这个keyword迷惑过.尽管网上有非常多讨论volatile的文章,但它们有的过于讲述底层原理,而没 ...

  3. RGB(FFFFFF)转255:255:255

    NSString *color = model.display_color; long colorLong = strtoul([color cStringUsingEncoding:NSUTF8St ...

  4. POJ 3254 简单状压DP

    没什么可说的,入门级状压DP.直接撸掉 #include <iostream> #include <cstring> #include <cstdlib> #inc ...

  5. jquery 可拖拽的窗体控件实现代码

    引入JQUERY框架.把这个控件代码放到一个js文件里面直接引入就可以了控件代码 $.fn.myDrag = function() { var self = $(this); self.css(&qu ...

  6. [na]wireshark添加显示ip.id列

    wireshark添加ip.id字段 为了在多个设备上追踪同一个数据包. 如果是同一个会话,则可以计算延迟, 如sta和应用服务器慢,这种问题,可以根据这个加上ip.id追踪数据到哪里慢了.

  7. linux命令(29):用户组管理

    用户管理: 新建用户或组:新建用户:adduser user //新建user用户(推荐)passwd user //给user用户设置密码 新建组:groupadd test //新建test工作组 ...

  8. Eclipse+tomcat+axis2进行web service部署

    用Eclipse+axis2+tomcat进行web service部署 2016-12-07 目录  1 安装JDK  1.1 下载JDK  1.2 安装和配置JDK  1.3 验证2 安装Ecli ...

  9. sql server 递归汇总 按指定层级汇总

    每个地区递归层级可能不一致,数据表(table)存放最小层级地区 area --地区层级表 id name f_id leve 1 中国 0 1 2 湖北 1 2 3 武汉 2 3 ... --测试数 ...

  10. sqlserver 对多条数据分组

    在开发中,经常会遇到要吧一行行数据按照某一行进行分组 USE [OA] GO /****** Object: StoredProcedure [dbo].[usp_report_GatherDataM ...