热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Qt的事件

Qt

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的事件循环,

  事件循环的大致示意

 1 while (!exit_was_called) 
 2 { 
 3     while(!posted_event_queue_is_empty) 
 4     { 
 5         process_next_posted_event(); 
 6     } 
 7     while(!spontaneous_event_queue_is_empty) 
 8     { 
 9         process_next_spontaneous_event(); 
10     } 
11     while(!posted_event_queue_is_empty) 
12     { 
13         process_next_posted_event(); 
14     } 
15 }

  可以看出,程序首先处理所有的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


推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 抽空写了一个ICON图标的转换程序
    抽空写了一个ICON图标的转换程序,支持png\jpe\bmp格式到ico的转换。具体的程序就在下面,如果看的人多,过两天再把思路写一下。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 本文讨论了读书的目的以及学习算法的重要性,并介绍了两个算法:除法速算和约瑟夫环的数学算法。同时,通过具体的例子和推理,解释了为什么x=x+k序列中的第一个人的位置为k,以及序列2和序列3的关系。通过学习算法,可以提高思维能力和解决问题的能力。 ... [详细]
  • 今日份分享:Flutter自定义之旋转木马
    今日份分享:Flutter自定义之旋转木马-先上图,带你回到童年时光:效果分析子布局按照圆形顺序放置且平分角度子布局旋转、支持手势滑动旋转、快速滑动抬手继续旋转、自动旋转支持X轴旋 ... [详细]
author-avatar
孤鹰与战狼
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有