Qt中事件处理的方式,最常用的就是使用事件处理器(event handler)和事件过滤器(event filter)这两种方法。接下来,我们就来看看事件处理器和事件过滤器是怎么使用的。

事件处理器

Qt中针对每一种常见的事件类型都提供了相应的事件处理器,我们如果想捕获某种类型的事件并进行自定义处理,那么只需要实现重写这些事件处理器就行。常见的事件类型和对应的事件处理器如下图所示:

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

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

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

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

到这里这个功能就实现了,大家看看上面的头文件就知道这里还实现了其它类型事件的处理,其实都是一样的思路,找到欲处理的事件类型,找到对应的事件处理器,重写事件处理器中处理事件的方法即可。这个看起来比较简单!

事件过滤器

Qt事件模型中一项非常强大的功能就是一个QObject实例可以监视另一个QObject实例中的事件,实现方法是在目标对象中安装事件过滤器。

假设我们有一个Dialog控件,由一些QLineEdit控件组成。我们希望使用Space键得到下一个QLineEdit的输入焦点。

一个最直接的方法是继承QLineEdit重写keyPressEvent()函数,当点击了Space键时,调用focusNextChild():

 C++ Code 
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()函数中处理目标对象的事件。

 Dialog.h 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
#include <QDialog>

class QLineEdit;
class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = );
    ~Dialog();

protected:
    virtual bool eventFilter(QObject *target, QEvent *event);

private:
    QLineEdit*      firstNameEdit ;
    QLineEdit*      lastNameEdit;
    QLineEdit*      cityEdit;
    QLineEdit*      phoneNumberEdit;
};

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

 C++ Code 
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->installEventFilter(this);
    lastNameEdit->installEventFilter(this);
    cityEdit->installEventFilter(this);
    phoneNumberEdit->installEventFilter(this);
}

事件过滤器注册后,发送到firstNameEdit,lastNameEdit,cityEdit,phoneNumberEdit控件的事件首先到达CustomerInfoDialog::eventFilter()函数,然后在到达最终的目的地。

下面是eventFilter()函数的代码:

 C++ Code 
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中事件处理器和事件过滤器实现实例的更多相关文章

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

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

  2. Qt中事件分发源代码剖析

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

  3. Qt中事件分发源码剖析

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

  4. 关于vue.js中事件处理器的练习

    html: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8 ...

  5. Qt 中事件与处理

    一.事件与处理程序在运算过程中发生的一些事情:鼠标单击.键盘的按下...这些的事件的监控与处理在Qt中不是以信号的方式处理的.当这些事件发生时会调用QObject类中的功能函数(虚函数),所有的控件类 ...

  6. QT父子窗口事件传递与事件过滤器(讲了一些原理,比较清楚)

    处理监控系统的时候遇到问题,在MainWidget中创建多个子Widget的时候,原意是想鼠标点击先让MainWidget截获处理后再分派给子Widget去处理,但调试后发现如果子Widget重新实现 ...

  7. Qt 中的事件处理(二)

    1. 回顾事件传递的过程 ①源头:操作系统   操作系统检测到用户的动作时,就会产生一个系统消息,系统消息就会被发送到正在运行的Qt应用程序中, ②应用程序收到系统消息后, 他会将系统消息翻译成对应的 ...

  8. Qt 中的事件处理(一)

    1.图形界面应用程序的消息处理模型 特点: 基于操作系统才能运行 GUI应用程序提供的功能必须由用户触发 用户操作界面时操作系统是第一个感知的 系统内核的消息通过事件处理转变成QT的信号 2. Qt中 ...

  9. 第39课 Qt中的事件处理(下)

    1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...

随机推荐

  1. 等差数列 [USACO Training Section 1.4]

    题目描述 一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…)的数列. 在这个问题中a是一个非负的整数,b是正整数.写一个程序来找出在双平方数集合(双平方数集 ...

  2. redis:order set有序集合类型的操作(有序集合)

    1. order set有序集合类型的操作(有序集合) 有序集合是在无序集合的基础上加了一个排序的依据,这个排序依据叫score,因此声明一个集合为有序集合的时候要加上score(作为排序的依据) 1 ...

  3. day6常用模块,数据库操作

    一.循环调用函数    map() 二.列表推导式和生成器 三.filter过滤器 四.os模块 五.datetime模块 六.random模块 七.写日志,导入nnlog模块 八,发邮件 九,操作数 ...

  4. 团队——League of Programers简介

    团队名称  League of Programers 团队成员简介 武璧泽:编程能力较强,善于程序思路设计: 邹兰兰:擅长代码的分析.编写与调试: 倪彤炜:擅长解决代码的修正与编写,善于调节团队关系: ...

  5. Docker命令使用详解(转)

    如果各位看官熟悉 Git 和 GitHub ,可与 Docker 做个类比,可更加容易理解 Docker 和 Docker Hub 及两者关系. 1. docker version 显示 Docker ...

  6. JAVA自学笔记18

    JAVA自学笔记18 1.Map接口: 1)功能: 2) Map<String,String>m=new HashMap<String,String>(); //添加元素,元素 ...

  7. JAVA自学笔记17

    JAVA自学笔记17 1.Map接口 1)概述 将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值.可以存储键值对的元素 2)与Collection接口的不同: ①Map是双列的 ...

  8. JSP(8)—EL案例和JSTL案例

    1.EL案例 el.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  9. 基于spring boot 2.x的websocket示例

    spring boot 2/spring 5自带了websocket,下面是最基本的示例(包括java服务端.java客户端以及js客户端) 一.pom依赖 <dependencies> ...

  10. .NET分布式缓存Memcached从入门到实战

    一.课程介绍 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法.但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是 ...