QT事件--阐述的比较系统

2023-10-29

转载:http://www.qtcn.org/bbs/simple/?t31383.html

Another Look at Events(再谈Events

        最近在学习Qt事件处理的时候发现一篇很不错的文章,是2004年季刊的一篇文章,网上有这篇文章的翻译版,但是感觉部分地方翻译的比较粗糙,不是很明确。索性重新翻译了一遍,并引用了原翻译版的一段译注。以下都是用自己能理解的方式来翻译的,由于水平有限,有很多不足的地方,希望大家指正。 

Another Look at Events (再谈Events 
by Jasmin Blanchette 


        
什么是自发事件?哪些事件类型可以被传递或压缩到一起?投递(posting)和发射(sending)一个事件的不同点在哪里?我应该什么时候在一个事件中调用accept()ignore()?如果你不知道前面所有的问题,那么请继续阅读下文! 
• 
事件的来源 
• 
手工事件 
• 
自定义事件类型 
• 
事件处接受或忽略? 

事件的来源 
        
事件可以基于产生和发送的方式来分为三种类型: 
• 
自发事件(spontaneous events)由窗口系统所产生。它们被放入一个系统队列,并通过事件循环相继地进行处理 
• 
投递事件(posted events)由Qt应用程序所产生。它们被放入Qt的消息队列中等待,并通过事件循环进行处理。 
• 
发射事件(sent events)由Qt应用程序所产生,但是它们被直接发送给目标对象。 
        
当我们在main()函数的最后调用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 events),直到事件队列为空。然后,它处理自发事件(spontaneous events),直到处理完所有事件。最后,它处理所有在处理自发事件(spontaneous events)过程中所产生的投递事件(posted events)。 
        
发射事件(sent events)不会被事件循环所处理。它们被直接传递给对象。 
        
让我们看看这在绘制事件(paint events)的执行中是如何工作的。当一个窗口小部件(widget)第一次显示时,或者当它被隐藏后又变的可见时,窗口系统会产生一个(自发的)要求程序重绘该窗口小部件的绘制事件(paint event)。最后,事件循环获取该事件,并将它发送给需要重绘的窗口小部件。 
        
不是所有的绘制事件(paint events)都是由窗口系统所产生。当你调用QWidget::update()来重绘一个窗口小部件时,该窗口小部件向自身投递一个绘制事件(paint event)。该绘制事件排队等待,并在最后由事件循环分派。 
        
如果你没有耐心,并且不想等待事件循环去重绘一个窗口小部件,那么理论上,你可以直接调用paintEvent()来强制立即重绘。但是在实际中,这样做并不一定可行,因为paintEvent()是一个受保护的函数。这也将绕过任何现有的事件过滤器。基于这一原因,Qt提供了一个直接发射(sending)事件,而不是投递(posting)事件的机制。QWidget::repaint()使用这一机制来强制进行立即的重绘。 
        
投递事件(posting events)相比于发射(sending)事件的一个优势在于投递(posting)的方式使Qt有机会对事件进行压缩。如果你在同一个窗口小部件(widget)上连续地调用10update(),并且没有返回事件循环(event loop),那么由update()所产生的10次事件将自动被合并为一个单一的事件,这一过程伴随着在它们所有的QPaintEvents对象中指定的区域的合并。 
        
最后,要注意的是你可以在任何时候调用QApplication::sendPostedEvents()以强制Qt处理一个对象的投递事件(posted events)。 

手工事件(即由应用程序主动激发,而不是由外界激发的事件) 
        Qt
应用程序可以产生它们自己的预定义或自定义类型的事件。这是通过创建一个QEvent(或其子类)的对象实例,并调用QApplication::postEvent()  QApplication::sendEvent()来实现的。 
        
这两个函数都有一个QObject *和一个QEvent *类型的参数。如果你调用postEvent(),那么你必须使用new关键字来创建一个事件对象(event object),并且当它被处理完以后,Qt将自动删除它。如果你调用sendEvent(),那么你必须在栈(stack)上创建事件对象。这里有一个投递(posting)一个事件的例子: 

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

        
这里是一个发射(sending)一个事件的例子: 

QKeyEvent event(QEvent::KeyPress, Key_X, 'X', 0); 
QApplication::sendEvent(mainWin, &event); 

        Qt
应用程序很少需要直接调用postEvent()  sendEvent(),因为大多数事件在需要时会由Qt或窗口系统自动产生。在大多数你想发送一个事件的情形中,Qt包含了一个高级的函数来代替它(例如update() repaint())。 

自定义事件类型 
        Qt
使你可以创建自己的事件类型。这一技术在多线程应用程序中特别有用,可以作为一种与GUI线程通信的手段;请参阅C++ GUI Programming with Qt 3 (p. 359)17章的一个例子。 
        
自定义类型在单线程应用程序中也是很有用的,可以作为一种对象间的通信机制。你愿意使用事件而不是标准函数调用或信号与槽的主要原因是事件既可以同步使用,也可以异步使用(取决于你是否调用sendEvent()postEvents()),然而调用一个函数或一个槽就总是同步的。事件的另一个优势是他们可以被过滤。关于这一点更详细的论述在下面的一节。 
        
这里有一个展示如何投递(post)一个自定义事件的代码片段: 
const QEvent::Type MyEvent = (QEvent::Type)1234; 
... 
QApplication::postEvent(obj, new QCustomEvent(MyEvent)); 

        
事件必须是QCustomEvent(或一个子类)的类型。构造函数的参数是事件的类型。1024以下的值被Qt所保留用于预定义的事件类型;其它可以被应用程序所使用。 
        
(译者注:在Qt4中,自定义事件是通过子类化QEvent来创建的。事件特定的数据被按照适合你的应用程序的方式存储。自定义事件仍然被发送给每个对象的customEvent()处理器函数,但是它们被作为QEvent对象而不是已经过时的QCustomEvent对象处理) 
        
为了处理自定义事件类型,需要重载customEvent()函数: 
void MyLineEdit::customEvent(QCustomEvent *event) 

if (event->type() == MyEvent) { 
myEvent(); 
} else { 
QLineEdit::customEvent(event); 



        QCustomEvent
拥有一个void *类型的成员,你可以将其用于自己的目的。如果你想要更多的类型安全,那么你也可以子类化QCustomEvent,并添加其它成员。但是然后你也需要在customEvent()中将QCustomEvent对象指向你特定的类型。 

事件处理和过滤 
        Qt中的事件可以进行5个不同层次的处理: 
• 
重新实现一个指定的事件处理器。 
QObject 
 QWidget为不同的事件类型提供了许多特殊的事件处理器(例如,用于处理绘制事件的paintEvent())。 
• 
重载QObject::event() 
event()
函数是一个对象的所有事件的入口点。QObject  QWidget中的该函数的默认实现只是简单地将事件转发给指定的事件处理器。 
• 
在一个QObject对象中安装一个事件过滤器。事件过滤器是一种对象,它能在另一个对象的事件到达指定目标之前,接收这些事件。 
• 
qApp中安装一个事件过滤器。特别地,一个qApp上的事件过滤器监控所有的发送给应用程序中全部对象的事件。 
• 
重载QApplication::notify()Qt事件循环和sendEvent()调用该函数以分发事件。通过重载它,你可以在其它任何人之前查看事件。 
        
一些事件类型可以被蔓延传播。这意味着如果一个目标对象不处理某个事件,那么Qt设法为事件找到另外一个接收者,并用新的目标对象调用QApplication::notify() 
例如,按键事件被传播;如果拥有焦点的窗口小部件(widget)不处理某一个按键事件,那么Qt会向其父窗口小部件发送一个相同的事件,然后再发送给父窗口小部件的父窗口等等,直到事件到达最顶层的窗口小部件。 

接受或忽略? 
        
能被传播的事件都拥有一个accept()和一个ignore()函数,你可以调用它们来告诉Qt系统你接受忽略该事件。如果一个事件处理器在某个事件上调用accept(),那么该事件就不会被继续传播;如果事件处理器是调用ignore(),那么Qt会设法寻找另一个接收者。 
        
如果你和大多数Qt开发者一样,那么你可能从不会觉得在你的程序中调用accept()ignore()是一件麻烦事。正是这样,Qt是以一种你通常从不需要调用这些函数的方式来进行设计的。默认的值是“accept”,而默认的在QWidget中的事件处理器的执行会调用ignore()。如果你想接受一个事件,那么你仅仅需要重载事件处理器,并且避免调用QWidget的事件处理器。如果你想忽略一个事件,那么只需要简单地将其传递给QWidget的事件处理器。下面的代码片段说明了这一点: 
void MyFancyWidget::keyPressEvent(QKeyEvent *event) 

if (event->key() == Key_Escape) { 
doEscape(); 
} else { 
QWidget::keyPressEvent(event); 



        
在这个例子中,如果用户按下了Esc键,我们就调用doEscape(),并且事件被接受(默认)。该事件不会被继续传播给父窗口小部件。如果用户按下了其他任何一个按键,那么我们调用QWidget的默认事件处理器。 
void QWidget::keyPressEvent(QKeyEvent *event) 

event->ignore(); 


        
由于调用了ignore(),事件将被传播给父窗口小部件。 
        
到目前为止,我们都假设QWidget是基类。但是,通过将QWidget替换为其它基类,同样的用法可以在任何层次上使用。例如: 
void MyFancyLineEdit::keyPressEvent(QKeyEvent *event) 

if (event->key() == Key_SysReq) { 
doSystemRequest(); 
} else { 
QLineEdit::keyPressEvent(event); 



        
如果由于某些原因,你使用event()函数代替特定的事件处理器(例如keyPressEvent())来处理事件,那么程序就稍微有点不同。event()函数会返回一个布尔值来告诉调用者某个事件是否被接受或忽略(true表示接受)。在event()中调用一个事件上的accept()ignore()是没有意义的。“accept”标记是特定的事件处理器和event()之间的一种通信机制,而event()返回的布尔值被用于同QApplication::notify()的通信。QWidget中默认的event()“accept”标识转换为一个布尔值的执行过程如下所示: 

bool QWidget::event(QEvent *event) 

switch (e->type()) { 
case QEvent::KeyPress: 
keyPressEvent((QKeyEvent *)event); 
if (!((QKeyEvent *)event)->isAccepted()) 
return false; 
break; 
case QEvent::KeyRelease: 
keyReleaseEvent((QKeyEvent *)event); 
if (!((QKeyEvent *)event)->isAccepted()) 
return false; 
break; 
... 

return true; 


        
到目前为止所讨论的内容不仅适用于按键事件,也适用于鼠标、滚轮、手写板和上下文菜单(即右键菜单)事件。 
        
关闭事件的工作方式有所不同。调用QCloseEvent::ignore()可以取消关闭操作,但是通常accept()告诉Qt继续执行关闭操作。为了避免任何的混乱,在你重载后的closeEvent()中明确地调用accept()ignore()是一个好办法,就像这样: 

void MainWindow::closeEvent(QCloseEvent *event) 

if (userReallyWantsToQuit()) { 
event->accept(); 
} else { 
event->ignore(); 

}





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT事件--阐述的比较系统 的相关文章

  • 使用Qt开发绘制多个设备的流量曲线图(附带项目图)

    一 说明 在实际项目中 主要是使用Qt开发CS程序 当然主要是客户端 公司项目中有这个需求是实时显示多个设备的流量曲线图 设备将流量信息发给服务端 服务端再将信息通过Socket发给Qt客户端 Qt客户端通过Socket接收后实时显示在程序
  • QT学习之三:Qt Creator2.4.1的开发环境的配置和测试

    1 系统环境 主机操作系统 ubuntu10 04 主机编译器 gcc4 4 3 交叉编译器 arm linux gcc 4 3 2 前提条件 搭建好qt4 6 3的三个编译版本 PC X86 ARM 2 安装 Qt SDK Lin32 o
  • [Qt教程] 第2篇 在Ubuntu14.04上创建Qt 5.4.0开发环境

    导语 上一篇安装好了Ubuntu系统 在正式进行嵌入式开发之前 我们先在Ubuntu上安装Qt开发环境 确保可以正常进行桌面程序的开发 毕竟程序首先是要在桌面上测试的 这里我们使用最新的Qt 5 4 0版本 正文 一 下载并安装Qt 1 下
  • 使用setStyleSheet来设置图形界面的外观

    关于QPushButton的问题 hover press我用setStyleSheet为一个QPushButton贴了一个背景图片 但是 当点了按钮之后 会出现虚线框 这样看起来就很丑 不逼真了 我不希望这个虚线框出现 有什么好的解决方法吗
  • Qt之键盘事件无法响应问题

    Qt之键盘事件无法响应问题 概述 代码 over 文末一句话 概述 新公司的加班第一天 在调试公司项目代码时发现个小问题 鼠标 键盘事件都已写好 但是键盘事件无效无法进入断点 接来下去查文档并没有查到相关说明 翻阅百度翻到如下代码 并进行测
  • QWidget的背景颜色和背景图片的设置

    首先设置autoFillBackground属性为真 然后定义一个QPalette对象 设置QPalette对象的背景属性 颜色或图片 最后设置QWidget对象的Palette 实例 QWidget widget new QWidget
  • 编译qt的pc版本X11出错:Basic XLib functionality test failed!

    Basic XLib functionality test failed You might need to modify the include and library search paths by editin 这个错误主要是因为 X
  • Qt动画效果展示

    在上一篇博文 Qt动画框架 原创翻译 中 我给大家原创翻译了Qt动画框架并且有文字和代码以及图片共同描述 今天在这篇博文中 主要实践Qt动画 做一个实例来讲解Qt动画使用 其界面如下图所示 由于没有录制为gif动画图片 所以请各位下载查看效
  • QT布局

    布局管理 以下是Qt手册中的 布局管理 的译文 在一个Widget中 Qt布局管理系统提供了一个简单而有效的方式来自动组织子widget 以保证他们能够很好地利用可用空间 介绍 Qt包含一个布局管理类的集合 它们被用来描述widgets如何
  • 数码相框实现遍历文件夹图片文件

    遍历文件夹图片文件 一 功能介绍 在为数码相框所在文件系统实现U盘自动挂载之后 将U盘自动挂载在开发板上文件系统中的 mnt usb目录 故还需为数码相框添加遍历 mnt usb路径下的文件夹内图片文件 暂定为扫描指定目录下一层文件夹内的图
  • qt的QLabel中的字体越界

    今天使用文泉驿的中文库wqy zenhei ttc 发现QLabel中的汉字上面切顶了 但是如果一个QLabel和一个QLineEdit并排就不会出现这种现象 最后对QLabel使用样式解决了这个问题 MyLabel gt setStyle
  • 关于Qt 中update()和repaint()的区别

    void QWidget repaint int x int y int w int h bool erase TRUE 槽 通过立即调用paintEvent 来直接重新绘制窗口部件 如果erase为真 Qt在paintEvent 调用之前
  • Qt中的焦点事件

    在应用程序中 都会有一个当前窗口 即当前获得焦点事件的窗口 这个窗口可以接受键盘的输入 当应用有多个窗口时就要使用焦点事件了 Qt中有很好的焦点事件管理 我在这里抛砖引玉了 一个空间要先设置它焦点事件的模式 即窗口如何接受焦点事件 通过鼠标
  • 解决QT Creator交叉编译提示make:arm-linux-g++:Command not found 命令找不到

    解决QT Creator交叉编译提示make arm linux g Command not found 命令找不到 初学QT 用QT Creator写了一个小程序 使用ubuntu 11 编译工具使用arm none linux gnue
  • Qt之QTextEdit

    关于QTextEdit Qt5对Qt4的做了一些小的改动 看上去很多方法都发生了变化 但万变不离其中 如 槽函数setFontFamily const QFont 变为setFontFamily const QString fontFami
  • Qt浅谈之二十二Qt样式表

    一 简介 不断总结好的样式表 美化自己的界面 在实际工作中会不断的更新 二 详解 1 加载样式表文件 html view plain copy QFile file qss stylesheet qss file open QFile Re
  • Qt中图像的显示与基本操作

    Qt可显示基本的图像类型 利用QImage QPxmap类可以实现图像的显示 并且利用类中的方法可以实现图像的基本操作 缩放 旋转 1 Qt可显示的图像类型 参考Qt的帮助文档 可支持的类型 即可以直接读取并显示的格式有BMP GIF JP
  • 【转】QT中QWS的含义

    QT编程和文档中的术语QWS的全称是Qt windows system 是QT自行开发的窗口系统 体系结构类似X Windows 是一个C S结构 由QWS Server在物理设备上显示 由QWS Client实现界面 两者通过socket
  • 【Qt】Qt事件系统

    00 目录 文章目录 00 目录 01 Qt事件系统概述 02 事件如何传递 03 事件类型 04 事件处理 05 事件过滤器 06 事件发送 附录 01 Qt事件系统概述 Qt 5 12 Qt Core The Event System
  • QString::arg() 函数

    例 setWindowTitle tr 1 2 arg shownName arg tr Spreadsheet QString arg 函数用第一个arg 调用会替换 1 第2个arg 调用会替换 2 上面的例子其实可以写作 setWin

随机推荐

  • spring底层核心原理解析

    目录 一 Spring如何创建一个对象 二 Bean的创建生命周期 三 推断构造方法 四 Spring的构造方法设计 五 利用cglib进行Aop的流程 六 spring判断对象要不要进行aop 一 Spring如何创建一个对象 Annot
  • 阿里云轻量应用服务器和云服务器ECS区别(终于懂了)

    阿里云服务器ECS和轻量应用服务器有什么区别 云服务器ECS是明星级云服务器 轻量应用服务器可以理解为简化版的云服务器ECS 轻量适用于单机应用 云服务器ECS适用于集群类高可用高容灾应用 阿里云百科来详细说下阿里云轻量应用服务器和云服务器
  • 腾讯云服务器ubuntu18.04搭建FastDFS文件服务器

    腾讯云服务器ubuntu18 04搭建FastDFS文件服务器 FastDFS简介 FastDFS是用c语言编写的一款开源的分布式文件系统 FastDFS为互联网量身定制 充分考虑了冗余备份 负载均衡 线性扩容等机制 并注重高可用 高性能等
  • 华为OD机试 - 消消乐游戏(Java)

    题目描述 游戏规则 输入一个只包含英文字母的字符串 字符串中的两个字母如果相邻且相同 就可以消除 在字符串上反复执行消除的动作 直到无法继续消除为止 此时游戏结束 输出最终得到的字符串长度 输入描述 输入原始字符串 str 只能包含大小写英
  • 2022西山居seed游戏开发训练营笔试复盘

    1 c基础 char arr1 a b c b char arr2 abcd int arr3 10 0 arr1和arr2的区别 cout lt lt sizeof arr1 lt lt endl cout lt lt sizeof ar
  • gcc 选项

    1 c选项 gcc命令后直接跟源文件会对源文件进行预处理 编译 链接生成默认名为a out的可执行文件 而 c选项会处理到编译环节终止 生成一个目标文件 默认名为filename o 它必须再经过链接才最终生成可执行文件 2 g选项 创建符
  • scss、less

    SCSS 是 Sass 3 引入新的语法 是Sassy CSS的简写 是CSS3语法的超集 其语法完全兼容 CSS3 并且继承了 Sass 的强大功能 可以简单理解为scss是sass的一个升级版本 完全兼容sass之前的功能 又有了些新增
  • 吃鸡服务器维护7月5号,绝地求生7月5日更新到几点好?更新进不去怎么办?

    绝地求生7月5日更新内容 绝地求生7月5日更新到几点好 更新进不去怎么办 在绝地求生大逃杀中 为了让大家有个更好的游戏体验环境 绝地求生将于7月5日对游戏进行停机更新 本次更新到几点 很多玩家都不知道 下面就和小编一起去看看 绝地求生正式版
  • SpringBoot 用户登录(二)登录增加验证码

    一 需求分析 SpringBoot 用户登录 一 基础登录 在登录的基础上加上验证码验证 验证码过期时间为一分钟 二 解决思路 在后台生成UUID和验证码返回到前台 并将UUID作为key 验证码内容作为value存入redis 设置过期时
  • ajax获取后台图片数据流如何处理?

    当我们利用ajax从后台获取图片的时候 一般有两种方法 一种是获取后台传递过来的图片的url 一种是获取后台传递过来的图片数据流 当我们获取图片数据流的时候 应该这样处理这些数据流 让它在前台展示出图片 HTML img src alt J
  • 用apache james做简单的垃圾邮件过滤网关(转)

    网络环境如下 三台服务器 1 网关 公网IP 2 domino邮件服务器 3 另一台服务器 通过把网关的端口25 映射到domino服务器上 让domino服务器可以收发邮件 同时domino服务器还要把部分邮件转发到服务器3上 大家的发邮
  • 801冠号大全及桃花荧光

    第一 存量少是801升值的基本依据 801共158个冠号 天蓝 荧光 冠号去除一部分 桃花荧光油墨的占到801的总量的80 以上 有荧光满版网格的又分为 1 满版红桃花荧光 满版底纹网格荧光 2 满版金桃花荧光 满版底纹网格荧光 3 满版桃
  • JavaWeb——SSJDBC(struts2,spring,jdbc)框架,正向工程

    原文地址 http blog csdn net sapce fish article details 52900750 本文采用struts2 spring jdbc搭建web框架 使用正向工程 IDE用myeclipse 数据库用Mysq
  • 实时汇率转换小程序(c++爬虫)

    实时汇率转换小程序 c 爬虫 利用c 网络爬虫爬取网页的实时汇率进行汇率的转换 其中也利用了QT进行了页面设计 define SILENCE STDEXT HASH DEPRECATION WARNINGS include
  • Linux下安装过程中编译PHP时报错:configure: error: jpeglib.h not found.

    今天在搭建LNMP编译PHP时 报错 configure error jpeglib h not found root cac3 php 5 6 22 configure gt prefix usr local php5 gt enable
  • Java Thread Join

    join方法的作用 在A线程中调用了B线程的join 方法时 表示只有当B线程执行完毕时 A线程才能继续执行
  • Opencv之答题卡识别判卷

    项目要求 提供一张答题卡图像 通过图像处理识别出答题卡上每个题的选项 与正确答案对比 得出分数并写在答题卡上 代码实现过程 1 引入需要的库 import numpy as np import cv2 as cv 2 定义绘图函数 def
  • 下代码下代码下代码

    https modelzoo co
  • linux c语言编译成exe,C/C++程序从编译到最终生成可执行文件的过程分析

    C C 程序编译步骤 如何生成可执行文件 电子计算机所使用的是由 0 和 1 组成的二进制数 二进制是计算机的语言的 基础 计算机发明之初 人们只能降贵纡尊 用计算机的语言去命令计算机干这干那 一 句话 就是写出一串串由 0 和 1 组成的
  • QT事件--阐述的比较系统

    转载 http www qtcn org bbs simple t31383 html Another Look at Events 再谈Events 最近在学习Qt事件处理的时候发现一篇很不错的文章 是2004年季刊的一篇文章 网上有这篇