Qt的事件机制

事件过滤器:
  可以让一个对象侦听拦截另外一个对象的事件。
  实现原理:
  在所有Qt对象的基类:QObject中有一个
  类型为:QObjectList
  名字为:eventFilters
  的成员变量,当A给B安装了事件过滤器后
  B的eventList中就会保存A对象的指针,
  在B处理事件之前,会先检查eventList是
  否为空,如果不为空,就会调用事件过滤器函数eventFilter(),如果eventFilter()返回true,表示事件已经被处理完毕,Qt将直接返回进行下一事件处理,如果为false,事件将接着被送往剩下的事件过滤器或者是目标对象进行处理。

按照事件的起源将事件分为三类:

  Spontaneous事件-----自发事件

  由窗口系统产生,被放到系统队列中,通过事件循环逐个处理。

  Posted事件

  由Qt或是应用程序产生,被Qt组成队列,再通过事件循环处理。

  sent事件

  由Qt或是应用程序产生,但他们被直接发送到目标对象。

Qt事件循环的过程

  在调用QApplication::exec()时,程序进入了Qt的事件循环,

  事件循环的大致示意

 while (!exit_was_called)
{
while(!posted_event_queue_is_empty)
{
process_next_posted_event();
}
while(!spontaneous_event_queue_is_empty)
{
process_next_spontaneous_event();
}
while(!posted_event_queue_is_empty)
{
process_next_posted_event();
}
}

  可以看出,程序首先处理所有的posted事件,知道队列空,再处理Spontaneous事件,再处理因Spontaneous事件产生的posted事件。

  send事件不在事件循环内,因为他们不进入事件队列而是直接发送给目标对象

实例paint()事件:

  当一个widget第一次可见,或者是被遮挡后可见,窗口产生一个(Spontaneous)paint事件,要求程序重绘widget,事件循环最宗从事件队列中拣选这个事件并把他们分发到那个徐奥重画的widget对象。

  并不是所有paint事件都是窗口系统产生,当你调用update()去强行重画widget,这个widget会post一个paint事件给自己,这个paint事件被放入队列,最终被事件循环分发。

  而当你等不及事件循环时,本来应该调用paintEvent()强制立即重画,但是实际上不可行因为paintEvent()是受保护的函数,因此Qt提供了一个机制直接sending事件给对象,repaint()就使用了这个机制来进行立即重画。(这是update()更新和repaint()更新的区别)。

  posting相对于sending的一个优势就是给了Qt一个压缩事件的机会,假如在一个widget上连续调用update()十次,因update()而产生的这十个事件,会被自动地合并成一个单独的事件,

人工合成的事件

  Qt应用程序可以产生他们自己的事件,或是预定义类型,或是自定义类型。这可以通过创建QEvent类或它的子类的实例,并且调用QApplication::postEvent()或QApplication::sendEvent()来实现。

  这两个函数需要一个QObject* 与一个QEvent作为参数,如果使用postEvent(),要使用new操作符来创建事件对象,如

  QApplication::postEvent(mainWin,new QKeyEvent(QEvent::KeyPress,Key_X,'X',0));

如果使用sendEvent(),应该使用栈来创建事件

  QKeyEvent event(QEvent::KeyPress,Key_X,'X',0);

  QApplication::sendEvent(mainWin,&event);

定制事件类型

  Qt允许创建自己的事件类型,可以作为对象间的一种通讯机制。是因为这个可以是异步的,函数调用或槽调用总是同步的。另一个好处是可以被过滤

  post一个定制事件:

    const QEvent::Type MyEvent = (QEvent::Type)1234;

    ...

    QApplication::postEvent(obj,new QCustomEvent(MyEvent));

  事件必须是QCustomEvent类型(或子类)的。构造函数的参数是事件的类型,

  为了处理定制事件类型,要重新实现customEvent()函数:

  void MyLineEdit::customEvent(QCustomEvent *event)

  {

    if(event->type() == MyEvent){

      myEvent();

    }else{

      QLineEdit::customEvent(event);

    }

  }

  可以子类化QCustomEvent,加上别的成员,但是需要在customEvent()中转换QCustomEvent到特有的类型

事件的处理与过滤

  Qt的事件可以在五个不同的层次上被处理

  1.重新实现一个特定的事件handler

    QObject与QWidget提供了许多特定的事件handlers,分别对应于不同的事件类型。(如paintEvent()对应paint()事件)

  2.重新实现QObject::event()

    event()函数是所有对象事件的入口,QObject和QWidget中缺省的实现是简单地把事件推入特定的事件handlers。

   3.在QObject上安装事件过滤器

     事件过滤器是一个对象,它在事件到达指定目标之前接收这些事件。

   4.在aApp上安装一个事件过滤器

     它会监视程序中发送到所有对象的所有事件

   5.重新实现QApplication::notify()

     Qt的事件循环与sendEvent()调用这个函数来分发事件,

特定对象的事件处理

  一些事件类型可以被传递。这意味着加入目标对象不处理一个事件,Qt会试着寻找另外的事件接收者。用新的目标来调用QApplication::notify()。举例来讲,key事件是传递的,假如拥有焦点的Widget不处理特定键,Qt会分发相同的事件给父widget,然后是父亲的父亲,直到最顶层widget。

什么时候该接收事件,什么时候该忽略

  通过accept()函数和ignore()函数。可被传递的事件有一个accept()函数和一个ignore()函数,可以用他们来告诉Qt,你"接收"或是"忽略"这个事件。假如事件handler调用accept(),这个事件将不会再被传递。假如事件handler调用ignore(),Qt会试着查找另外的事件接收者。

来源:http://www.cnblogs.com/li-hao/archive/2011/11/13/2247662.html

Qt的事件的更多相关文章

  1. Qt的事件模型(5种使用办法,通常重新实现event handler即可。只有定义控件才需要管理信号的发射)

    Qt的事件模型 1.事件的概念 应用程序对象将系统消息接收为 Qt 事件.应用程序可以按照不同的粒度对事件加以监控.过滤并做出响应. 在 Qt 中,事件是指从 QEvent继承 的对象.Qt将事件发送 ...

  2. 剖析Qt的事件机制原理

    版权声明 请尊重原创作品.转载请保持文章完整性,并以超链接形式注明原始作者“tingsking18”和主站点地址,方便其他朋友提问和指正. QT源码解析(一) QT创建窗口程序.消息循环和WinMai ...

  3. Qt 自定义事件详细实例(继承QEvent,然后QCoreApplication::postEvent()、sendEvent())

    创建用户事件 创建一个自定义类型的事件,首先需要有一个事件号,其值通常大于QEvent::User.为了传递事件信息,因此必须编写自定义的事件类,该事件类从QEvent继承. 编写用户事件:编写用户事 ...

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

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

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

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

  6. 界面编程之QT的事件20180727

    /*******************************************************************************************/ 一.事件 1 ...

  7. QT paintevent 事件, update()槽函数

    一界面重载函数 使用方法: 1在头文件里定义函数 protected: void paintEvent(QPaintEvent *event); 2 在CPP内直接重载 void ---------- ...

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

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

  9. Qt 自定义事件(三种方法:继承QEvent,然后Send Post就都可以了,也可以覆盖customEvent函数,也可覆盖event()函数)

    Qt 自定义事件很简单,同其它类库的使用很相似,都是要继承一个类进行扩展.在 Qt 中,你需要继承的类是 QEvent. 继承QEvent类,你需要提供一个QEvent::Type类型的参数,作为自定 ...

随机推荐

  1. 第一册:lesson sixty nine.

    原文: The car race. There is a car race near our town every year. In 1995 ,there was a very big race. ...

  2. 第一册:lesson3-4.

    原文: A:My coat and my umbrella please?Here is my ticket. B:Thank you sir.Number five.Here is your umb ...

  3. JQuery官方学习资料(译):$ vs $()

    直到现在,我们一直是通过一个jQuery对象来调用函数的,例如: $( "h1" ).remove();      大多数jQuery函数是通过jQuery对象调用的,这是$.fn ...

  4. C#中设置窗口在最前显示而其他窗口不能使用

    对程序中的一个Form1处理,让其在打开的情况下,其他窗体都无法使用,全部焦点都在他身上. 1.这种方法最简单,直接调用窗体的模态对话框函数显示窗体 Form1.ShowDialog(): 2.设置窗 ...

  5. .NET 单元测试的利剑——模拟框架Moq(简述篇)

    .NET 单元测试的利剑--模拟框架Moq 前言 这篇文章是翻译文,因为通过自己参与的项目,越发觉得单元测试的重要性,特别是当跟业务数据打交道的时候的,Moq就如雪中送炭,所以想学习这个框架,就从这篇 ...

  6. JS经典题目解析

    此次列举出一些觉得有意思的JS题目(来源于出了名的44题),相信有非常多关于这些题目的博客,写这篇博客的目的在于巩固一些知识点,希望能和读者共同进步. 1. map函数执行过程 ["1&qu ...

  7. Node.js性能分析神器Easy-Monitor

    摘要: 使用Easy-Monitor,可以准确定位Node.js应用的性能瓶颈,帮助我们优化代码性能. 当应用出现性能问题时,最大的问题在于:如何准确定位造成性能瓶颈的代码呢?对于Node.js开发者 ...

  8. 原生JS实现随着鼠标滚动到元素位置触发对应css3动画,简单易用滚动监测

    预览链接:http://www.vanwee.cn/%E6%BB%9A%E5%8A%A8%E7%9B%91%E5%90%AC/ <style> body{overflow-x: hidde ...

  9. ajaxJson(常用)

    function ajaxJson(method, url, data, callback) { var options = { type: method, url: url, dataType: ' ...

  10. springboot 格式化返回日期

    两种方式: 1,可以在 pojo 类每个属性添加 @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8&qu ...