Qt的事件模型一个强大的功能是一个QObject对象能够监视发送其他QObject对象的事件,在事件到达之前对其进行处理。

假设我们有一个CustomerInfoDialog控件,由一些QLineEdit控件组成。我们希望使用Space键得到下一个QLineEdit的输入焦点。一个最直接的方法是继承QLineEdit重写keyPressEvent()函数,当点击了Space键时,调用focusNextChild():

void MyLineEdit::keyPressEvent(QKeyEvent *event)
{if (event->key() == Qt::Key_Space) {focusNextChild();} else {QLineEdit::keyPressEvent(event);}
}

这个方法有一个最大的缺点:如果我们在窗体中使用了很多不同类型的控件(QComboBox,QSpinBox等等),我们也要继承这些控件,重写它们的keyPressEvent()。一个更好的解决方法是让CustomerInfoDialog监视其子控件的键盘事件,在监视代码处实现以上功能。这就是事件过滤的方法。实现一个事件过滤包括两个步骤:

  1. 在目标对象上调用installEventFilter(),注册监视对象。
  2. 在监视对象的eventFilter()函数中处理目标对象的事件。

注册监视对象的位置是在CustomerInfoDialog的构造函数中:

CustomerInfoDialog::CustomerInfoDialog(QWidget *parent): QDialog(parent)
{…firstNameEdit->installEventFilter(this);lastNameEdit->installEventFilter(this);cityEdit->installEventFilter(this);phoneNumberEdit->installEventFilter(this);
}

事件过滤器注册后,发送到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);
}

首先,我们看是目标控件是否为QLineEdit,如果事件为键盘事件,把QEvent转换为QKeyEvent,确定被敲击的键。如果为Space键,调用focusNextChild(),把焦点交给下一个控件,返回true通知Qt已经处理了这个事件,如果返回false,Qt将会把事件传递给目标控件,把一个空格字符插入到QLineEdit中。
如果目标控件不是QLineEdit,或者事件不是Space敲击事件,把控制权交给基类QDialog的eventFilter()。目标控件也可以是基类QDialog正在监视的控件。(在Qt4.1中,QDialog没有监视的控件,但是Qt的其他控件类,如QScrollArea,监视一些它们的子控件)
Qt的事件处理有5中级别:

  1. 重写控件的事件处理函数:如重写keyPressEvent(),mousePressEvent()和paintEvent(),这是最常用的事件处理方法,我们已经看到过很多这样的例子了。
  2. 重写QObject::event(),在事件到达事件处理函数时处理它。在需要改变Tab键的惯用法时这样做。也可以处理那些没有特定事件处理函数的比较少见的事件类型(例如,QEvent::HoverEnter)。我们重写event()时,必须要调用基类的event(),由基类处理我们不需要处理的那些情况。
  3. 给QObject对象安装事件过滤器:对象用installEventFilter()后,所有达到目标控件的事件都首先到达监视对象的eventFilter()函数。如果一个对象有多个事件过滤器,过滤器按顺序激活,先到达最近安装的监视对象,最后到达最先安装的监视对象。
  4. 给QApplication安装事件过滤器,如果qApp(唯一的QApplication对象)安装了事件过滤器,程序中所有对象的事件都要送到eventFilter()函数中。这个方法在调试的时候非常有用,在处理非活动状态控件的鼠标事件时这个方法也很常用。
  5. 继承QApplication,重写notify()。Qt调用QApplication::nofity()来发送事件。重写这个函数是在其他事件过滤器处理事件前得到所有事件的唯一方法。通常事件过滤器是最有用的,因为在同一时间,可以有任意数量的事件过滤器,但是notify()函数只有一个。

许多事件类型,包括鼠标,键盘事件,是能够传播的。如果事件在到达目标对象的途中或者由目标对象处理掉,事件处理的过程会重新开始,不同的是这时的目标对象是原目标对象的父控件。这样从父控件再到父控件,知道有控件处理这个事件或者到达了最顶级的那个控件。
图7.2显示了一个键盘事件在一个对话框中从子控件到父控件的传播过程。当用户敲击一个键盘,时间首先发送到有焦点的控件上(这个例子中是QCheckBox)。如果QCheckBox没有处理这个事件,Qt把事件发送到QGroupBox中,如果仍然没有处理,则最后发送到QDialog中。

QT事件过滤器eventFilter函数相关推荐

  1. Qt中事件过滤器eventFilter中所有枚举事件总结

    Qt中事件过滤器一般是用在继承QObject的类中,但是更多的是用在继承QWidget的界面类中.在界面类中,一般用的最多的是鼠标和键盘事件,包括鼠标摁下.移入.移除.拖拽等.一般在鼠标做出相应动作时 ...

  2. installEventFilter、eventFilter函数理解

    installEventFilter函数如下: void QObject::installEventFilter(QObject *filterObj) Qt助手的解释如下: 在对象上安装一个事件过滤 ...

  3. Qt 事件过滤器(秒懂)

    1.事件过滤器 void QObject::installEventFilter(QObject *filterObj) bool eventFilter(QObject *obj, QEvent * ...

  4. QT:常用函数详解--常用操作记录(个人笔记)

    QT:常用函数详解(个人笔记) PS:一下内容个人笔记,要求自己看懂,随笔,阅读体验会很差很差! Qt setContentsMargins()函数 函数原型:void QLayout::setCon ...

  5. QT多线程run函数不能使用信号与槽

    一.问题描述 今天遇到一个问题,我在一个子线程中定义一个信号与槽函数,然后直接连接,最后会报错Socket notifiers cannot be enabled or disabled from a ...

  6. Qt窗口操作函数(最大化,全屏,隐藏最大化,最小化)

    转自:https://blog.csdn.net/pamxy/article/details/9012221 转自:http://blog.csdn.net/zhangshan415/article/ ...

  7. Qt QLineEdit 信号函数总结

    Qt QLineEdit 信号函数总结 QLineEdit一共有6个信号函数,并不多,很好理解. void cursorPositionChanged( intold, intnew ) 当鼠标移动时 ...

  8. QT里的函数void Q_INIT_RESOURCE ( name )

        QT里的函数voidQ_INIT_RESOURCE ( name ) Initializesthe resources specified by the .qrc file with the ...

  9. QT5百度地图开发学习——qt调用JavaScript函数并传参

    文章目录 前言 一.通信桥梁bridge 二.QT与JS相互通信(调用函数) 1.QT调用js函数 前言 在上文<QT5百度地图开发学习--控件提升展示地图>中,我们通过控件提升的方式在同 ...

最新文章

  1. 学计算机如何防辐射,长期对电脑怎么防辐射
  2. 在项目中使用react
  3. Flutter开发Flutter与原生OC、Java的交互通信-2(48)
  4. SmartCode 使用常见问题
  5. Thymeleaf 标准表达式语法
  6. inurllay old.php id,搜索技巧
  7. 【博客】csdn搬家到wordpress
  8. [react-router] React-Router 4的switch有什么用?
  9. 完成课件中的动手动脑的或需要验证的相关内容。
  10. 【TSP】基于matlab蚁群算法求解旅行商问题【含Matlab源码 1130期】
  11. ▲▲▲▲▲▲▲▲▲▲▲yum源的配置(本地和ftp)▲▲▲▲▲▲▲▲▲▲▲▲▲v...
  12. python列表常用方法_python 列表常用方法
  13. java人脸识别开源算法,就是这么简单
  14. 网页悬浮按钮php,Javascript实现带关闭按钮的网页漂浮广告代码_javascript技巧
  15. java 月份缩写_英文月份简写
  16. Linux SPI驱动框架(2)——控制器驱动层
  17. k64 datasheet学习笔记26--Oscillator (OSC)
  18. B端和C端产品的理解
  19. 如何判断一个员工是潜力无限,还是“烂泥扶不上墙”?
  20. 川崎机器人总线通信_川崎机器人:PLC有那些功能?能实现机器人哪些通讯?

热门文章

  1. 搭配对比学习,万能的 prompt 还能做可控文本生成
  2. 召回 粗排 精排,如何各司其职?
  3. 「小公式」平均数与级数
  4. 大规模领域词汇库项目DomainWordsDict:涵盖68个领域、共计916万的词汇库资源开放
  5. docker下创建crontab定时任务失败
  6. Broadcast简单使用
  7. ajax之深入解析(2)
  8. 转:mysql group by 用法解析(详细)
  9. 在XML里的XSD和DTD以及standalone的使用
  10. iis5.1/6.0/7.0+ 配置url重写 无扩展名伪静态