The Event System
The Event System
在Qt中,事件是继承了虚拟类QEvent的对象,它代表了程序所发生的事情或者程序需要知道的一个外部活动的结果。事件可以被任意 QObject子类的实例接收和处理,是与widgets密切相关。本文描述了在一个典型的程序中事件是如何被传送和处理的。
How Events are Delivered
当发生一个事件,Qt通过构造一个适当的 QEvent子类的实例来创建事件对象来代表它,并通过调用vevent()函数把它传送到特定的 QObject 实例。
该函数本身不处理事件:根据传送的事件类型,它为特定的时间类型调用一个事件处理程序,并根据事件是被接受或忽略发送一个响应。
一些事件,如QMouseEvent 和 QKeyEvent来自windows系统。如QTimerEvent, 来自其他来源,一些来自程序本身。
Event Types
大多数的事件类型有特别的类,尤其是 QResizeEvent, QPaintEvent, QMouseEvent, QKeyEvent,andQCloseEvent. ,它们都继承了QEvent 和添加了特殊的函数。如 QResizeEvent 添加了 size()和 oldSize()函数使得widgets 可以获得其改变的规模。
一些类支持多于一种实际的事件类型。 QMouseEvent 支持鼠标按下,双击,移动和其他相关操作。
每个事件都有一个定义在QEvent::Type的相关的类型,它可以用作运行时的类型信息以快速确定事件对象是构造自哪个子类。
由于程序需要多种复杂的方式的响应,Qt的事件传送机制也是灵活的。QCoreApplication::notify()文档对称进行了确切的描述。
Event Handlers
通常事件被传送的方法是调用一个虚函数。例如, QPaintEvent 通过调用 QWidget::paintEvent().而被传送。该虚函数复杂作出适当的响应,通常是重绘widget。如果在你实现的虚函数里不能完成所需要的功能,可以调用基类的实现。
例如,下面的代码处理了自定义的checkbox 鼠标左键按下事件,把其他按键按下的事件传送给基类QCheckBox :
void MyCheckBox::mousePressEvent(QMouseEvent*event)
{
if (event->button() ==Qt::LeftButton) {
// handle left mouse button here
} else {
// pass on other buttons to base class
QCheckBox::mousePressEvent(event);
}
}
如果你想取代基类的函数,你必须自己实现每件事。然而,如果你只想扩展基类的功能,你可以实现自己想实现的部分,在任何你不想处理情况,可以调用基类来获得默认的处理。
偶尔,可能没有特定事件的函数,或者特定事件的函数功能不充分。最常见的例子包含Tab 按下。通常, QWidget拦截事件来移动键盘焦点,但是有的widget需要自己处理Tab 按下事件。
这些对象可以重新实现 QObject::event(),,一般的事件处理程序,可以在通常的事件处理之前或之后对它们的事件进行处理,或者完全取代整个函数的。一个既拦截Tab 也有自定义事件的widget 可能包含以下的event() 函数:
bool MyWidget::event(QEvent*event)
{
if (event->type() ==QEvent::KeyPress) {
QKeyEvent*ke =static_cast<QKeyEvent*>(event);
if (ke->key() ==Qt::Key_Tab) {
// special tab handling here
returntrue;
}
} elseif (event->type() == MyCustomEventType) {
MyCustomEvent *myEvent =static_cast<MyCustomEvent *>(event);
// custom event handling here
returntrue;
}
returnQWidget::event(event);
}
我们注意到对于没有处理的所有情况都调用了QWidget::event() ,而且返回值表明了事件是否被处理。返回值true阻止了事件被传递给其他对象。
Event Filters
有时一个对象需要检查并可能拦截被传送给其他对象的事件。例如,对话框一般需要为一下widget过滤键盘按键事件。例如,修改返回键处理。
QObject::installEventFilter()设置了eventfilter,,在目标对象的QObject::eventFilter() 函数里接收事件。事件过滤器在目标对象之前处理事件,根据需要允许对事件进行检查和丢弃。可以用 QObject::removeEventFilter()函数移除一个已经存在的事件过滤器。
当一个过滤器对象的eventFilter() 实现被调用,它可以接受或不接受事件,允许或拒绝更进一步的处理事件。如果所有的事件过滤器允许更进一步的处理事件,事件将被发送给目标对象本身。如果其中某个事件停止处理,目标对象和后面一些事件过滤器都接收不到该事件。
bool FilterObject::eventFilter(QObject*object,QEvent*event)
{
if (object == target && event->type() ==QEvent::KeyPress) {
QKeyEvent*keyEvent =static_cast<QKeyEvent*>(event);
if (keyEvent->key() ==Qt::Key_Tab) {
// Special tab handling
returntrue;
} else
returnfalse;
}
returnfalse;
}
以上代码演示了另一种拦截Tab按键事件并发送到特定目标widget的方法。在这种情况下,事件过滤器处理了相关的事件并返回true阻止事件被进一步处理。其他的事件则被忽略,事件过滤器返回false以允许它们被发送到目标widget,通过任何已经安装的事件过滤器。
为整个程序过滤所有的事件也是可能的,通过为 QApplication 或QCoreApplication 安装事件过滤器。这样的全局事件过滤器将会在特定对象的过滤器之前被调用。这很强大,但是也会使得整个程序的事件发送变慢。
Sending Events
很多程序想创建和发送自己的事件。你可以用像Qt的事件循环一样的方法发送事件,通过构造合适的事件对象并用QCoreApplication::sendEvent()和QCoreApplication::postEvent().发送事件。
sendEvent()立即处理事件。当它返回,事件过滤器和对象本身已经处理了事件。对于很多事件类型,有一个isAccepted()函数用来获取最近的处理过程事件是被接受还是不被接受。
postEvent()把事件传递到队列等待分发。下一次主事件循环运行,它进行一些优化将分发所有的队列中的事件。例如,有一些resize 事件,将被压缩成一个事件。同样的应用与paint事件:QWidget::update()调用 postEvent(),它消除闪烁和增加速度以避免多次重绘。
postEvent()在对象初始化过程中也被用到,因为发出的事件将在对象的初始化完成之后立即分发。当实现一个widget,意识到事件可能在其生命期的早期被分发这很重要,在其构造函数中,确保在早期初始化成员变量,在其有机会接收到事件之前。
要创建自定义的事件类型,需要定义一个事件号,必须大于 QEvent::User.
The Event System的更多相关文章
- Building Robust and Flexible Event System in Unity3D
Building Robust and Flexible Event System in Unity3D 1. Prerequisites 1.1 Observer Pattern According ...
- 【SaltStack官方版】—— Events&Reactor系统—EVENT SYSTEM
Events&Reactor系统 EVENT SYSTEM The Salt Event System is used to fire off events enabling third pa ...
- event system
事件的概念 简单来说, 就是应用程序感兴趣的应用内部或者外部的活动结果. 在Qt中, 使用QEvent 抽象这些活动. 事件驱动模型 事件驱动模型现在在计算机很多领域都有使用. 例如 BSD sock ...
- UICamera(NGUI Event system)原理
看了UICamera的源码就显而易见了: UICamera « on: November 21, 2013, 12:21:48 AM » Overview UICamera is a somewh ...
- [React] Normalize Events with Reacts Synthetic Event System
Event handlers are passed an instance of SyntheticEvent in React. In this video we'll take a look at ...
- Spring Application Event Example
Spring Application Event 项目结构 工程下载 https://github.com/xiaoheike/SpringApplicationEventExample.git Sp ...
- spring 事件(Application Event)
spring 事件为bean 与 bean之间传递消息.一个bean处理完了希望其余一个接着处理.这时我们就需要其余的一个bean监听当前bean所发送的事件. spring事件使用步骤如下: 1.先 ...
- 自定义Spring event
通过Spring自定义event 首先我们定义我们的event类 package com.hyenas.spring.custom.event; import org.springframework. ...
- spring集成guava的event bus
Guava的event bus guava, https://github.com/google/guava 是一个非常有名的Java类库,提供了很多在日常开发中常用的集合.函数接口等.此外,guav ...
随机推荐
- 表现层及ASP.NET MVC介绍(一)
表现层及ASP.NET MVC介绍(一) 本文将介绍表现层及ASP.NET MVC的一些要点,特别是ASP.NET MVC的一些抽象和封装技巧,如果你对MVC还不了解,可以参考<ASP.NET ...
- 3-05. 寻求倒数第二链线性表K项目(15)(STL list应用 ZJU_PAT)
主题链接:http://pat.zju.edu.cn/contests/ds/3-05 给定一系列正整数,请设计一个尽可能高效的算法.查找倒数第K个位置上的数字. 输入格式说明: 输入首先给出一个正整 ...
- mongodb操作:利用javaScript封装db.collection.find()后可调用函数源码解读
{ "_mongo" : connection to YOURIP:27017{ SSL: { sslSupport: false, sslPEMKeyFile: "&q ...
- 注意,WebDeploy服务会占用80端口。(Windows关闭了IIS,80端口任然被占用)
最近遇到一个很奇怪的事情,Windows上的 IIS 网站 全关掉了,80端口仍然被占用.然后我新装了一台服务器,一个一个组件地装,装一个测一次,最后发现,WebDeploy这个组件,会占用80端口. ...
- 关于session_start()这个问题
关于session_start()这个问题,其实网上很多解决的方法,论坛也好多人回答这类的问题, 现在的状况是依然有警告提示Warning: session_start() [function.ses ...
- sql点滴40—mysql乱码问题总结
原文:sql点滴40-mysql乱码问题总结 本文将为大家讲解如何处理Java连接过程中的MySQL中文乱码问题.一般MySQL中文乱码问题都是与字符集有关,这里作者的经历也大致差不多. MySQL默 ...
- 在windows server里,对于同一个账号,禁止或允许多个用户使用该账户,同时登录
开始 -> 运行 -> gpedit.msc -> 本地计算机 策略 -> 计算机配置 -> 管理模板 -> Windows 组件 -> 远程桌面服务 -&g ...
- Swift初探一
今天安装了一下Xcode6-Beta版,想来体验一下Swift的魅力:安装Swift系统最低版本号为:10.9.3 仅仅看看一点The Swift Programming Language,以下给大家 ...
- 通过SqlClr制作Sql自动化批量执行脚本
原文:通过SqlClr制作Sql自动化批量执行脚本 通过SqlClr制作Sql自动化批量执行脚本 在与同事一起做项目时,看到同事用sqlclr做批量执行脚本,感觉挺新奇的就上网搜集资料自己模仿跟做了个 ...
- 3DMax的OFusion插件的使用问题
使用OFusion将3D max导出到现场Ogre的Mesh该方法是经常使用的非.的一些问题,在这里为方便摘要. 1.OFusion得到: http://download.csdn.net/detai ...