当前位置: 首页 > news >正文

QT事件机制

事件就是从抽象QEvent类中派生的对象,表示发生在应用程序内部或由于应用程序需要了解的外部活动而发生的事情。例如当用户按下鼠标、敲下键盘就会产生QMouseEvent和QKeyEvent;系统自动发出的QTimerEvent事件等。Qt事件系统是依托于元对象系统的,所有的QObject类都可以接收/处理QEvent事件。

1,事件的产生

事件就是对象,派生自QEvent抽象类,事件的产生,就是创建一个对象。例如在一个窗口界面,当我们鼠标点击、双击、移动等,就会产生一个QMouseEvent事件对象。事件的来源一般分为三个,来自窗口系统,例如鼠标键盘产生的QMouseEvent和QKeyEvent;来自其他程序,比如 QTimerEvent;来自Qt程序本身,一些自定义的事件等。

2, 事件类和事件类型

Qt中所有事件类都是继承QEvent,用户输入类事件继承关系。事件类都有个唯一身份值:type 值,也就是事件类型。需要注意有些事件类可能对应于多个事件类型,例如QMouseEvent类对应于鼠标按压事件,鼠标双击事件,鼠标移动事件等。

 3,事件派发

当事件发生时Qt通过构造适当的QEvent子类的实例来表示一个事件,并通过调用其event()函数将其传递到 QObject的特定实例 (或其子类之一)。event()函数不处理事件本身,而是根据所传递事件的类型,调用对应的事件处理程序,并根据该事件被接受还是忽略,发送响应。许多应用程序都希望创建并发送自定义的事件,Qt提供了一些事件发送函数:

static bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event);
static bool QCoreApplication::postEvent(QObject *receiver, QEvent *event);
static void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type);

(1)sendEvent()直接将event事件发送给receiver接受者,立即处理事件。返回值是事件过滤器
和/或对象本身已经处理了该事件。对于许多事件类,有一个称为 isAccepted()的函数,该
函数告诉该事件是被最后一个调用的处理程序接受还是拒绝。
(2)postEvent()将接受者receiver和事件event发布到队列中,以供以后分派。下次Qt的主事件循环运行时,它将分派所有已发布的事件,并进行一些优化。例如,如果有多个调整大小事件,它们将被视为为一个。这同样适用于绘画事件中,如QWidget:: update()调用postEvent(),通过避免多次重新绘画来消除闪烁并提高速度。

(3)sendPostedEvents函数将事件队列中的接受者为receiver,事件类似为event_type的所有事件立即发送给 receiver进行处理。来自窗口系统的事件是由processEvent()进行处理。

void MainWindow::handletimeout()
{myevent *mypostEvent = new myevent();//使用postevent方式发送,事件添加到事件队列,此事件分配给this来处理,系统会自动释放的。QCoreApplication::postEvent(this, mypostEvent);
}

4,事件处理

一个类接收到应用程序派发来的事件后,调用其event()函数处理,该函数是QObject类中定义的一个虚函数。任何从QObject派生的类都可以重新实现该函数。在event()函数中我们可以设置是否接收事件,QEvent类中有accept()函数,表示接收事件并对事件进行处理,ignore()函数,表示不接收该事件。不接受的事件将会传播到接受者的父容器组件中,由父容器的event()函数去处理。QWidget类是所有窗口类的基类,它重新实现了event()函数,并对一些典型的事件定义了专门处理函数,event()函数会根据事件的类型自动去运行相应的事件处理函数,这些处理函数是pro-tected virtual, 不能被外部调用,但可以被派生类重新实现。每个事件都有关联的类型,在 QEvent::Type中定义了相关类型,并且可以用作运行时类型信息的便捷来源,以确定构造给定事件对象的子类。

void mousePressEvent(QMouseEvent *event); // 鼠标按下,对应事件类型
QEvent::MouseButtonPress
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void keyPressEvent(QKeyEvent *event);
void closeEvent(QCloseEvent *event);
void resizeEvent(QResizeEvent *event);
void paintEvent(QPaintEvent *event);

5,事件过滤器

事件会被派发给接受者,接受者通过event函数处理。在Qt还设计eventFilter()函数, 可以将一个对象的事件委托给另一个对象监视和处理,实现更灵活的事件过滤;QObject::installEventFilter()函数将自己注册给监视对象,监视对象重新实现QObject::event-Filter()函数,对监视的事件进行处理。

void QObject::installEventFilter(QObject *filterObj)
bool QObject::eventFilter(QObject *watched, QEvent *event)

事件过滤器可以在目标对象之前处理事件,从而使它可以根据需要检查和丢弃事件,可以使用
QObject :: removeEventFilter()函数删除现有的事件过滤器。调用过滤器对象的 eventFilter()实现时,它可以接受或拒绝事件,并允许或拒绝事件的进一步处理,如果所有事件过滤器都允许进一步处理事件(每次返回 false),则事件将发送到目标对象本身。如果其中一个停止处理(返回 true),则目标过滤器和任何以后的事件过滤器将根本看不到该事件。一般我们通过QApplication 或QCoreApplication对象上安装事件过滤器,还可以过滤整个应用程序的所有事件。此类全局事件过滤器在特定于对象的过滤器之前被调用。这是非常强大的功能,但是它也会减慢整个应用程序中每个事件的事件传递速度。

举例:过滤按键事件,如果是按下空格键,就往界面输出信息,自行处理事件。其他事件通过返回QWid-get::eventFilter(object,event),交给父类的eventFilter()函数处理。

bool Widget::eventFilter(QObject *object, QEvent *event)
{if (object == this && event->type() == QEvent::KeyPress) //判断是该事件的对象是不是 Widget,并且要是 QEvent::KeyPress{QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);if (keyEvent->key() == Qt::Key_Space) {QString mesg=QString("空格按键");ui->textEdit->append(QString("[%1] %2").arg(QDateTime::currentDateTime().toString("hh:mm:ss")).arg(mesg));return true;} else{return false;}return QWidget::eventFilter(object,event); //返回父类的eventFilter()函数执行结果
}

相关文章:

  • 在Linux上使用nginx反向代理部署Docker网站
  • 【Java扫盲篇】String、String Buffer和String Builder的区别
  • iOS开发 - 转源码 - __weak问题解决
  • spikingjelly学习-使用单层全连接snn脉冲神经网络识别mnist数据集
  • websocket 内的操作码fin和opcode
  • 数据结构万字总结(超级详细)第二章——线性表
  • JVM虚拟机-实战篇
  • AI+云平台|全闪云底座迎战
  • 自媒体用ChatGPT批量洗稿软件V5.9环境配置/软件设置教程【汇总】
  • UE5C++学习(四)--- SaveGame类存储和加载数据
  • Sql Server小技能:row_number()函数
  • 【Vue】Vue集成Element-UI框架
  • 深圳区块链交易所app系统开发,撮合交易系统开发
  • 服务器总是宕机问题记录
  • 【WPF应用7】 基本控件-Grid 布局的详解与示例
  • [case10]使用RSQL实现端到端的动态查询
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【RocksDB】TransactionDB源码分析
  • 345-反转字符串中的元音字母
  • axios请求、和返回数据拦截,统一请求报错提示_012
  •  D - 粉碎叛乱F - 其他起义
  • Electron入门介绍
  • JavaScript 基本功--面试宝典
  • rabbitmq延迟消息示例
  • Web设计流程优化:网页效果图设计新思路
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 安卓应用性能调试和优化经验分享
  • 大快搜索数据爬虫技术实例安装教学篇
  • 对超线程几个不同角度的解释
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 王永庆:技术创新改变教育未来
  • scrapy中间件源码分析及常用中间件大全
  • 交换综合实验一
  • ​ArcGIS Pro 如何批量删除字段
  • ​flutter 代码混淆
  • (C语言)球球大作战
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (离散数学)逻辑连接词
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (三分钟)速览传统边缘检测算子
  • (转)EOS中账户、钱包和密钥的关系
  • (转)大道至简,职场上做人做事做管理
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • .NET gRPC 和RESTful简单对比
  • .NET微信公众号开发-2.0创建自定义菜单
  • .net中应用SQL缓存(实例使用)
  • /usr/bin/env: node: No such file or directory
  • @cacheable 是否缓存成功_Spring Cache缓存注解
  • @我的前任是个极品 微博分析
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [codevs 1296] 营业额统计