QT中事件处理器和事件过滤器实现实例
Qt中事件处理的方式,最常用的就是使用事件处理器(event handler)和事件过滤器(event filter)这两种方法。接下来,我们就来看看事件处理器和事件过滤器是怎么使用的。
事件处理器
Qt中针对每一种常见的事件类型都提供了相应的事件处理器,我们如果想捕获某种类型的事件并进行自定义处理,那么只需要实现重写这些事件处理器就行。常见的事件类型和对应的事件处理器如下图所示:

用户自定义事件定义如下:

在日常使用中,我们最常使用的鼠标事件:

新建一个基于QWidget的应用程序,在QWidget的头文件中找到鼠标操作事件处理器虚函数如下:

我们将其在我们的QWidget子类中重写实现:


到这里这个功能就实现了,大家看看上面的头文件就知道这里还实现了其它类型事件的处理,其实都是一样的思路,找到欲处理的事件类型,找到对应的事件处理器,重写事件处理器中处理事件的方法即可。这个看起来比较简单!
事件过滤器
Qt事件模型中一项非常强大的功能就是一个QObject实例可以监视另一个QObject实例中的事件,实现方法是在目标对象中安装事件过滤器。
假设我们有一个Dialog控件,由一些QLineEdit控件组成。我们希望使用Space键得到下一个QLineEdit的输入焦点。
一个最直接的方法是继承QLineEdit重写keyPressEvent()函数,当点击了Space键时,调用focusNextChild():
|
1
2 3 4 5 6 7 8 9 10 11 |
void MyLineEdit::keyPressEvent(QKeyEvent *event)
{ if (event->key() == Qt::Key_Space) { focusNextChild(); } else { QLineEdit::keyPressEvent(event); } } |
这个方法有一个最大的缺点:如果我们在窗体中使用了很多不同类型的控件(QComboBox,QSpinBox等等),我们也要继承这些控件,重写它们的keyPressEvent()。
一个更好的解决方法是让Dialog监视其子控件的键盘事件,在监视代码处实现以上功能。
这就是事件过滤的方法。实现一个事件过滤包括两个步骤:
1、在目标对象上调用installEventFilter(),注册监视对象。
2、在监视对象的eventFilter()函数中处理目标对象的事件。
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <QDialog>
class QLineEdit; public: protected: private: |
注册监视对象的位置是在CustomerInfoDialog的构造函数中:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Dialog::Dialog(QWidget *parent)
: QDialog(parent) { QFormLayout* formLayout = new QFormLayout; firstNameEdit = new QLineEdit(); lastNameEdit = new QLineEdit(); cityEdit = new QLineEdit(); phoneNumberEdit = new QLineEdit(); formLayout->addRow(tr("&FirstName:"), firstNameEdit); formLayout->addRow(tr("&LastName:"), lastNameEdit); formLayout->addRow(tr("&City:"), cityEdit); formLayout->addRow(tr("&PhoneNumber:"), phoneNumberEdit); setLayout(formLayout); // 给QLineEdit安装事件过滤器 |
事件过滤器注册后,发送到firstNameEdit,lastNameEdit,cityEdit,phoneNumberEdit控件的事件首先到达CustomerInfoDialog::eventFilter()函数,然后在到达最终的目的地。
下面是eventFilter()函数的代码:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
bool Dialog::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中。

QT中事件处理器和事件过滤器实现实例的更多相关文章
- Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)
Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的.下面举例说明: 1)首先看看下面一段示例代码: in ...
- Qt中事件分发源代码剖析
Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的. 下面举例说明: 1)首先看看下面一段示例代码: i ...
- Qt中事件分发源码剖析
Qt中事件分发源码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,而且进行分发,这些都是在exec中进行的. 以下举例说明: 1)首先看看以下一段演示样例代码: ...
- 关于vue.js中事件处理器的练习
html: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8 ...
- Qt 中事件与处理
一.事件与处理程序在运算过程中发生的一些事情:鼠标单击.键盘的按下...这些的事件的监控与处理在Qt中不是以信号的方式处理的.当这些事件发生时会调用QObject类中的功能函数(虚函数),所有的控件类 ...
- QT父子窗口事件传递与事件过滤器(讲了一些原理,比较清楚)
处理监控系统的时候遇到问题,在MainWidget中创建多个子Widget的时候,原意是想鼠标点击先让MainWidget截获处理后再分派给子Widget去处理,但调试后发现如果子Widget重新实现 ...
- Qt 中的事件处理(二)
1. 回顾事件传递的过程 ①源头:操作系统 操作系统检测到用户的动作时,就会产生一个系统消息,系统消息就会被发送到正在运行的Qt应用程序中, ②应用程序收到系统消息后, 他会将系统消息翻译成对应的 ...
- Qt 中的事件处理(一)
1.图形界面应用程序的消息处理模型 特点: 基于操作系统才能运行 GUI应用程序提供的功能必须由用户触发 用户操作界面时操作系统是第一个感知的 系统内核的消息通过事件处理转变成QT的信号 2. Qt中 ...
- 第39课 Qt中的事件处理(下)
1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...
随机推荐
- linux公社
linux公社网址:http://www.linuxidc.com/ 资料下载地址:http://linux.linuxidc.com/
- yii2 用 bootstrap 给元素添加背景色
使用 bootstrap 给元素添加背景色 1.bootstrap 官网:http://getbootstrap.com/ 2.bootstrap 中文官网:http://v3.bootcss.com ...
- 移动游戏ui设计(一)
游戏世界 游戏界面就是根据游戏特性,把必要的信息展现在游戏主界面,操控界面和弹出界面上,通过合理的设计引导用户进行人机交互操作: 1, 游戏界面设计原则:交互设计尽量不要繁琐,用最简单的方式引导用户即 ...
- 移动端input中的placeholder属性垂直
今天做项目时发现,在手机端用placeholder时,Android手机可以垂直显示:ISO则不能使placeholder垂直;解决办法: .gcddfadf-con-pay-1 input::-we ...
- Java面试题集锦
1. String.StringBuffer和StringBuilder的区别. (1) String:存储数值不可改变的字符串 (2) StringBuffer:可变字符序列.线程安全.效率低 ...
- docker 清理容器的命令
执行以下命令会彻底清除所有容器. docker rm -f $(docker ps -qa) rm -rf /var/lib/etcd /var/lib/cni /var/run/calico rm ...
- http理解
http是一种基与客户端和服务端的架构模式,通过一种可靠的连接(URL)来交换消息,是一个诶状态的请求/响应协议. http协议传输过程 client发送request到server,server接收 ...
- poj3320 Jessica's Reading Problem(尺取思路+STL)
https://vjudge.net/problem/POJ-3320 尺取法,要想好组织方式. 又被卡了cin.. #include<iostream> #include<cstd ...
- 卷积的三种模式:full, same, valid
通常用外部api进行卷积的时候,会面临mode选择. 本文清晰展示三种模式的不同之处,其实这三种不同模式是对卷积核移动范围的不同限制. 设 image的大小是7x7,filter的大小是3x3 1,f ...
- shell字符串的用法
shell字符串的用法 注意:shell4.2和shell4.1会有差别,较低版本的shell可能不支持某些功能 获取字符串长度:${#string} 获取子串: 注:(左边的第一个字符是用 0 表示 ...