1. 回顾事件传递的过程

①源头:操作系统   操作系统检测到用户的动作时,就会产生一个系统消息,系统消息就会被发送到正在运行的Qt应用程序中,
②应用程序收到系统消息后, 他会将系统消息翻译成对应的QEvent事件对象,并调用QObject::event()将该对象分发下去,
③事件对象被分发到当前用户正在操作的窗口部件上去 ,该窗口部件是一个Qwidget的子类对象,该对象收到这个事件之后, 就会调用QWidget::event()函数来处理 ,该函数内部再调用其他的子函数(如KeyPressEvent或mouseReleaseEvent)进行具体的事件处理。
④可能会再被出传递到其父组件对象
 

(1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序

(2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject::event()将其分发出去。

(3)事件对应被分发到当前正在操作的窗口部件上,该窗口部件会调用QWidget::event()函数来处理,然后,在这个函数内部又会调用其他的子函数(如KeyPressEvent或mouseReleaseEvent)来进行具体的处理。

(4)event函数处理完后,可能会将当前事件传递给父组件(parent)对象。但这个过程只是一种可能,也就是有一部分会被传递,有些并不需要被传递。

2. QEvent及其子类对象涉及的关键成员函数:实际上只是在操作或判断一个标志位

(1)void ignore():事件的接收者忽略当前事件,事件可能传递给父组件

(2)void accept();事件的接收者期望处理当前事件,表明我们自己写了事件处理函数,一般不需要被父组件再处理

(3)bool isAccepted();判断当前事件是否被处理

事件传递流程①事件先传递给指定窗口部件,确切的说传递给获得焦点窗口的部件,②如果该部件忽略该事件,那么这个事件就会传递给其父组件
还需要注意当重新实现事件处理函数时,一般需要调用父组件的相应事件处理函数来实现其默认的行为
如:
  1. void MyLineEdit::keyPressEvent(QKeyEvent *e)
  1. {
    qDebug()<<"MyLineEdit::keyPressEvent";
  1. QLineEdit::keyPressEvent(e);// 执行QLineEdit类的默认事件处理
  1. }

实例事件处理的顺序

//main.cpp

  1. #include "Widget.h"
  2. #include <QApplication>
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6. QApplication a(argc, argv);
  7. Widget w;
  8. w.show();
  9.  
  10. return a.exec();
  11. }
  12. /*当在编辑框中按下按键时输出结果:(注意MyLineEdit的父组件,即w中的
  13. 的event事件并未被触发
  14. MyLineEdit::event
  15. MyLineEdit::keyPressEvent
  16. */

//MyLineEdit.h

  1. #ifndef MYLINEEDIT_H
  2. #define MYLINEEDIT_H
  3.  
  4. #include <QLineEdit>
  5.  
  6. class MyLineEdit : public QLineEdit
  7. {
  8. Q_OBJECT
  9. public:
  10. explicit MyLineEdit(QWidget* parent = );
  11. bool event(QEvent* e);
  12. void keyPressEvent(QKeyEvent* e);
  13. };
  14.  
  15. #endif // MYLINEEDIT_H

//MyLineEdit.cpp

  1. #include "MyLineEdit.h"
  2. #include <QKeyEvent>
  3. #include <QDebug>
  4.  
  5. MyLineEdit::MyLineEdit(QWidget* parent):QLineEdit(parent)
  6. {
  7.  
  8. }
  9.  
  10. bool MyLineEdit::event(QEvent* e)
  11. {
  12. if( e->type() == QEvent::KeyPress)
  13. {
  14. qDebug() << "MyLineEdit::event";
  15. }
  16. return QLineEdit::event(e);
  17. }
  18.  
  19. void MyLineEdit::keyPressEvent(QKeyEvent* e)
  20. {
  21. qDebug() << "MyLineEdit::keyPressEvent";
  22. QLineEdit::keyPressEvent(e);
  23.  
  24. // e->ignore(); //表示事件会继续传递给父组件,本例中为Widget对象
  25. //如果注释或e-accept()表示不再传递,则父组件的
  26. //event函数不会被触发
  27. }

//Widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5. #include "MyLineEdit.h"
  6.  
  7. class Widget : public QWidget
  8. {
  9. Q_OBJECT
  10.  
  11. private:
  12. MyLineEdit myLineEdit;
  13.  
  14. public:
  15. Widget(QWidget *parent = );
  16.  
  17. bool event(QEvent* e);
  18. void keyPressEvent(QKeyEvent* e);
  19.  
  20. ~Widget();
  21. };
  22.  
  23. #endif // WIDGET_H

//Widget.cpp

  1. #include "Widget.h"
  2. #include <QEvent>
  3. #include <QDebug>
  4.  
  5. Widget::Widget(QWidget *parent)
  6. : QWidget(parent),myLineEdit(this)
  7. {
  8. }
  9.  
  10. //操作系统将消息转化为事件,并分发到了这个Widget,会首先调用
  11. //这个Wiget的event函数,该函数可以收到多种的系统事件,同时其内部会根据event
  12. //事件的类型调用相应的事件处理函数,如keyPressEvent()。比如,当发生按键事件时
  13. //会先调用event(),再调用后面的keyPressEvent()
  14. bool Widget::event(QEvent* e)
  15. {
  16. if(e->type() == QEvent::KeyPress)
  17. {
  18. qDebug() << "Widget::event";
  19. }
  20.  
  21. return QWidget::event(e);
  22. }
  23.  
  24. void Widget::keyPressEvent(QKeyEvent *e)
  25. {
  26. qDebug() << "Widget::keyPressEvent";
  27. QWidget::keyPressEvent(e);
  28. }
  29.  
  30. Widget::~Widget()
  31. {
  32.  
  33. }

3. Qt中的事件过滤器

(1)事件过滤器

  ①事件过滤器可以对其他组件接收到的事件进行监控

  ②任意的QObject对象都可以作为事件过滤器使用

  ③事件过滤器对象需要重写eventFilter()函数

(2)安装事件过滤器:installEventFilter()函数

  ①事件过滤器在组件之前接收到事件

  ②事件过滤器能够决定是否将事件转到到组件对象

(3)Qt中的事件过滤器与dll中的勾子的不同

  ①Qt中事件的过滤,是由事件的目标对象自己,发起过滤请求的。即委托过滤器,在自己接收事件前,先叫过滤器过滤一下。这意味着目标对象是知道这个过滤器的存在的。如下面例子中的myLineEdit.installEventFilter(this),就是myLineEdit委托Widget对事件进行过滤。

  ②而dll中的勾子不管目标对象愿不愿意,消息都会被拦下,而且目标对象本身也并不知道勾子的存在

(4)事件过滤器的典型实现

  1. //场景:将所有发往obj的事件先经过指定的过滤函数处理一下,然后再发往obj
  2. //返回true表示事件己经处理,无需再传递给obj对象了
  3. //返回false则正常传递到obj对象
  4. bool Widget::eventFilter(QObject* obj, QEvent* e)
  5. {
  6. if(/*根据obj判断是否是所需的目标对象*/)
  7. {
  8. if(/*根据e->type()判断是否是感兴趣的事件*/)
  9. {
  10. /*事件处理逻辑*/
  11. }
  12. }
  13.  
  14. /*调用父类中的同名函数*/
  15. return QWidget::eventFilter(obj, e);
  16. }

main.cpp

  1. #include <QApplication>
  2. #include "widget.h"
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6. QApplication a(argc, argv);
  7. Widget w;
  8. w.show();
  9.  
  10. return a.exec();
  11. }

  widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. #include <QWidget>
  5. #include "mylineedit.h"
  6.  
  7. class Widget : public QWidget
  8. {
  9. Q_OBJECT
  10. MyLineEdit* lineEdit;
  11. protected:
  12. void keyPressEvent(QKeyEvent *);
  13. public:
  14. Widget(QWidget *parent = 0);
  15. ~Widget();
  16. bool eventFilter(QObject* obj, QEvent *event);
  17. };
  18.  
  19. #endif // WIDGET_H

  widget.cpp

  1. #include "widget.h"
  2. #include <QDebug>
  3. Widget::Widget(QWidget *parent)
  4. : QWidget(parent)
  5. {
  6. lineEdit=new MyLineEdit(this);
  7. //安装事件过滤器,即让所有发往myLineEdit的事件先由经由eventFilter过滤,这里委派Widget的EventFilter来过滤
  8. lineEdit->installEventFilter(this);//在Widget上为lineedit安装事件过滤器了
  9. }
  10.  
  11. Widget::~Widget()
  12. {
  13.  
  14. }
  15.  
  16. bool Widget::eventFilter(QObject *obj, QEvent *event)//事件过滤器
  17. {
  18. //该过滤器只过滤发往myLineEdit对象的KeyPress事件
  19. if(obj==lineEdit)//判断事件的对象是不是linEdit
  20. {
  21. if(event->type()==QEvent::KeyPress)//判断事件类型
  22. {
  23. qDebug()<<"Widget::eventFilter";
  24. }
  25. }
  26. return QWidget::eventFilter(obj, event);//最后返回QWidget类默认的事件过滤器的执行结果
  27. }
  28.  
  29. void Widget::keyPressEvent(QKeyEvent *)
  30. {
  31.   qDebug()<<"Widget::keyPressEvent";
  32. }

mylinedit.h

  1. #ifndef MYLINEEDIT_H
  2. #define MYLINEEDIT_H
  3.  
  4. #include <QLineEdit>
  5. #include <QEvent>
  6. class MyLineEdit : public QLineEdit
  7. {
  8. Q_OBJECT
  9. protected:
  10. void keyPressEvent(QKeyEvent *e);
  11.  
  12. public:
  13. explicit MyLineEdit(QWidget *parent = 0);
  14.  
  15. bool event(QEvent* event);
  16. signals:
  17.  
  18. public slots:
  19.  
  20. };
  21.  
  22. #endif // MYLINEEDIT_H

  

mylineedit.cpp

  1. #include "mylineedit.h"
  2. #include <QDebug>
  3. #include <QkeyEvent>
  4. #include <QLineEdit>
  5. MyLineEdit::MyLineEdit(QWidget *parent) :
  6. QLineEdit(parent)
  7. {
  8.  
  9. }
  10.  
  11. bool MyLineEdit::event(QEvent *event)
  12. {
  13. if(event->type()==QEvent::KeyPress)
  14. qDebug()<<"MyLineEdit::event";
  15.  
  16. return QLineEdit::event(event);//执行QLineEdit类的event()函数的默认操作 因为event()函数是有一个bool型返回值所以在函数的最后要使用return语句,这里一般是返回父类的event()函数的操作结果
  17. }
  18.  
  19. void MyLineEdit::keyPressEvent(QKeyEvent *e)
  20. {
  21. qDebug()<<"MyLineEdit::keyPressEvent";
  22.  
  23. // QLineEdit::keyPressEvent(e);
  24. e->ignore();
  25. }

  当点击键盘按键时,执行结果为:

  1. Widget::eventFilter
  2. MyLineEdit::event
  3. MyLineEdit::keyPressEvent
  4. Widget::keyPressEvent

可以看到事件的传递顺序是:事件过滤器----->该部件的event()函数------>该部件的事件处理函数------>有可能是父组件的event函数(如果子部件ignore())

3. 小结

(1)Qt应用程序有严格的事件处理顺序

(2)Qt事件在处理后可能传递给父组件对象

(3)可以通过installEventFilter()函数安装事件过滤器

(4)事件过滤器可以对其他组件接收到的事件进行监控

(5)事件过滤器能够决定是否将事件转发到组件对象

Qt 中的事件处理(二)的更多相关文章

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

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

  2. 第38课 Qt中的事件处理(上)

    1. GUI程序原理回顾 (1)图形界面应用程序的消息处理模型 (2)思考:操作系统发送的消息如何转变为Qt信号 2. Qt中的事件处理 (1)Qt平台将系统产生的消息转换为Qt事件 ①Qt事件是一个 ...

  3. Qt事件系统之一:Qt中的事件处理与传递

    一.简介 在Qt中,事件作为一个对象,继承自 QEvent 类,常见的有键盘事件 QKeyEvent.鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等,与 QEvent 类的 ...

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

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

  5. OS开发中的事件处理(二)-事件传递,响应者链条

    事件处理的事件传递 简介: 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件 队列中,UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理, ...

  6. QT_8_Qt中的事件处理_定时器事件_定时器类_事件分发器_事件过滤器_绘图事件_高级绘图事件_绘图设备_QFile 文件读写_QFileInfo文件信息

    Qt中的事件处理 1.1. 捕获QLabel中是鼠标事件 1.2. enterevent 鼠标进入 1.3. leaveevent 鼠标离开 1.4. 鼠标按下MyLabel::mousePressE ...

  7. Qt中事件处理的方法(三种处理方法,四种覆盖event函数,notify函数,event过滤,事件处理器。然后继续传递给父窗口。可观察QWidget::event的源码,它是虚拟保护函数,可改写)

    一.Qt中事件处理的方式   1.事件处理模式一 首先是事件源产生事件,最后是事件处理器对这些事件进行处理.然而也许大家会问, Qt中有这么多类的事件,我们怎么样比较简便的处理每个事件呢?设想,如果是 ...

  8. QT开发(十二)——QT事件处理机制

    一.QT事件简介 QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发.QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. 常见的QT事件类型如下: 键盘事件: 按键按下和松开 ...

  9. Qt中事件处理的顺序

    本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息.原文链接.原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途. 谢谢合作.原文链接:Qt中事件处理的顺序 文章内容主要来自 ...

随机推荐

  1. 2019-04-02-day024-内置方法

    昨日回顾 反射 用"字符串"类型的属性名/方法名来找到 属性的值或者方法的内存地址 所有可以反射的内容实际上都是变量 有内存地址 内存地址存的是"具体的值",直 ...

  2. js实现瀑布流以及加载效果

    一.瀑布流是个啥? 瀑布流,是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部. 最早采用瀑布流布局的网站是Pinteres ...

  3. zookeeper在Dubbo中扮演了一个什么角色

    作者:guxiangfly链接:https://www.zhihu.com/question/25070185/answer/188238271来源:知乎著作权归作者所有.商业转载请联系作者获得授权, ...

  4. [转]IP地址介绍

    [转]http://www.cnblogs.com/xiazdong/p/3675778.html IP地址分类介绍 这里讨论IPv4,IP地址分成了A类.B类.C类.C类.E类,如下图所示: 解释: ...

  5. matlab一行太长

    太长了,一行写不下,所以用...接下一行 例子: x=[ mvnrnd( mu_real(:,1) , cov_real(:,:,1) , round(N*a_real(1)) )' ,... mvn ...

  6. Refused to execute inline event handler because it violates the following Content Security Policy directive: "xxx". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...')

    /********************************************************************************* * Refused to exec ...

  7. Python之路,第二十篇:Python入门与基础20

    python3  面向对象4 supper 函数 supper(type, obj) 返回绑定超类的实例(要求obj必须为type类型的实例) supper()   返回绑定的超类的实例,等同于(cl ...

  8. ldd 查看程序依赖库

    ldd 查看程序依赖库 https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/ldd.html

  9. python sort、sorted高级排序技巧

    文章转载自:脚本之家 Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列. 1)排序基础 简单的升序排序是非常容易的 ...

  10. Dij_heap__前向星。

    //前向星 struct node { int nxt; int val; int lst; node () {} node (int next, int value) : nxt(next), va ...