qt5---资源文件

一、QApplication、QGuiApplication、QCoreApplication 简介

1、继承关系见下图,其中左侧为顶级父类
QObject  <----- QCoreApplication  <-----  QGuiApplication  <-----  QApplication  
2、一个程序中只能有一个 QCoreApplication 及其子类的对象
3、QCoreApplication:主要提供无 GUI 程序的事件循环
4、QGuiApplication:用于管理 GUI 程序的控制流和主要设置
5、QApplication:该类专门为 QGuiApplication 提供基于 QWidget 的程序所需的一些功能,主
要用于处理部件的初始化、最终化。主要职责如下:
使用用户的桌面设置初始化应用程序
执行事件处理,也就是说该类能从底层系统接收并分发事件。比如,使用QCoreApplication::sendEvent()或 QCoreApplication::postEvent()函数分发自定义事件
解析常用命令行参数并设置其内部状态
定义了应用程序的界面外观,可使用 QApplication::setStyle()进行更改
指定应程程序如何分配颜色
使用 QCoreApplication::translate()函数对字符串进行转换
通过 QApplication::desktop()函数处理桌面,通过 QCoreApplication::clipboard()函数处理剪贴板
管理应用程序的鼠标光标。比如使用 QGuiApplication::setOverrideCuresor()函数设置光标等
 

二、Qt 对事件的描述及分类

1、事件:是由程序内部或外部产生的事情或某种动作的通称。比如用户按下键盘或鼠标,就会产生一个键盘事件或鼠标事件(这是由程序外部产生的事件);再如,当窗口第一次显示时,会产生一个绘制事件,以通知窗口需要重新绘制其自身,从而使该窗口可见(这是由程序内部产生的事件)
2、事件和信号:
他们两个是不同的概念,不要弄混淆。信号是由对象产生的,而事件则不一定是由对象产生的(比如由鼠标产生的事件),事件通常来自底层的窗口系统,但也可以手动发送自定义的事件,可见信号和事件的来源是不同的
事件既可以同步使用,也可以异步使用 (取决于调用 sendEvent()还是 postEvents()),而使用信号和槽总是同步的。事件的另一个好处是可以被过滤
3、Qt 中使用 QEvent 及其子类来描述事件(其继承关系见下图),比如 QMouseEvent 类用于描述与鼠标相关的事件,该类保存了与鼠标相关的大量信息,比如是哪一个键激发了该事件、产生该事件时鼠标的位置等
 
QEvent事件类型表:

 

4、事件的分类:
①、方式一:根据事件的来源和传递方式,事件可分为以下三大类
自发事件:这是由窗口系统生成的,这些事件置于系统队列中,并由事件循环一个接一个地处理。
发布的事件(Posted events):该类事件由 Qt 或应用程序生成,这些事件由 Qt 排队,并由事件循环处理
发送的事件(Sent events):该类事件由 Qt 或应用程序生成,这些事件直接发送到目标对象,不经过事件循环处理
②、方式二:事件被细分为很多种类型(有一百多种),每一种类型使用 QEvent 类中的枚举常量进行表示,比如 QMouseEvent 管理的鼠标事件有鼠标双击、移动、按下等类型,这些类型分别使用 QEvent::Type 枚举类型中的枚举常量 MouseButtonDblClick、MouseMove、MouseButtonPress 表示。所有的类型分类请查阅帮助文档。可使用函数Type QEvent::type() const;获取事件的类型
5、使用 Qt 编程,几乎不需考虑事件,因为当产生某种事件时,Qt 窗口部件都会发射一个相应的信号(即 Qt 会把事件转换为一个对应的信号),比如按钮被按下时,会产生一个MouseButtonPress 事件,Qt 会处理这一事件,并且会发射一个 clicked()单击信号,程序员可以直接处理 clicked()信号,而不必处理底层的事件
6、对于事件,我们不需要知道 Qt 是怎样把事件转换为 QEvent 或其子类类型的对象的,程序员只需要知道怎样传递和处理这些事件即可。比如对于按下鼠标事件,不需要知道 Qt是怎样把该事件转换为 QMouseEvent 类型的对象的,只需要知道怎样传递和处理该事件即可
三、事件的传递(或分发)及处理
1、事件传递步骤(见下图):

 

 

①、基本规则:若事件未被目标对象处理,则把事件传递给其父对象处理,若父对象仍未处理,则再传递给父对象的父对象处理,重复这个过程,直至这个事件被处理或到达顶级对象为止。注意:事件是在对象间传递的,这里是指对象的父子关系,而不是指类的父子关系
②、在 Qt 中有一个事件循环,该循环负责从可能产生事件的地方捕获各种事件,并把这些事件转换为带有事件信息的对象,然后由 Qt 的事件处理流程分发给需要处理事件的对象来处理事件
③、通过调用 QCoreApplication::exec()函数启动事件主循环,主循环从事件队列中获取事件,然后创建一个合适的 QEvent 对象或其子类类型的对象来表示该事件,在此步骤中,事件循环首先处理所有发布的事件,直到队列为空,然后处理自发的事件,最后处理在自发事件期间产生的已发布事件。注意:发送的事件不由事件循环处理,该类事件会被直接传递给对象
④、然后,Qt 会调用 QCoreApplication::notify()函数对事件进行传递(或分发)
⑤、最后,QObject 对象调用 QObject::event()函数接收事件
 
event()函数是一个虚函数,是 QObject 对象处理事件的入口
在 QObject 的子类中通常会重写 event()函数,比如 QWidget 类就重写了 event()函数。
event()函数与事件处理函数的关系:event()函数负责把事件传递给目标对象并调用对应的事件处理函数处理事件,比如调用 QWidget::keyPressEvent()函数处理键盘按下事件等,注意,Object 中的 event()函数并不能实现该功能,这是通过QObject 的子类中重写的 event()函数实现的,比如调用 QWidget::keyPressEvent()函数,就是由在 QWidget 类中重写的 event()函数来完成的。
event()函数对大多数事件都调用了默认的处理函数,但并不能包括全部的事件,因此,有时我们需要重写该函数,这也是我们处理 Qt 事件的方式之一。
注意:event()函数不会处理事件,他只是根据事件的类型进行事件的传递(或分发),若返回 true 则表示这个事件被接受并进行了处理,否则事件未被处理,需进行进一步传递或丢弃
2、事件的处理
①、任何 QObject 的子类都可以处理事件,QEvent 及其子类虽然可以描述一个事件,但并不对事件进行处理
②、事件处理函数
事件是由类的成员函数(通常为虚函数)处理的,通常把处理事件的成员函数称为事件处理函数。由此可见,处理事件需要两个要求:处理该事件的对象和该对象中用于处理该事件的事件处理函数。
Qt 中对绝大多数常用类型的事件提供了默认的事件处理函数,并作了默认处理,这些事件处理函数位于 QObject 的子类中,比如 QWidget::mousePressEvent()函数用于处理鼠标按下事件,Widget::keyPressEvent()用于处理键盘按下事件等。对这些默认事件处理函数的调用是通过 QObject::event()虚函数进行的,因此若默认的事件处理函数不能满足用户要求(比如对 Tab 键的处理),则可以通过重新实现 event()函数来达到目的
下面为 QWidget 类的部分源代码(qwidget.cpp)
bool QWidget::event(QEvent *event){
……
switch (event->type()) {
……
//调用 QWidget 类的默认事件处理函数
case QEvent::MouseButtonPress:
 mousePressEvent((QMouseEvent*)event); break;
 case QEvent::MouseButtonRelease:
 mouseReleaseEvent((QMouseEvent*)event);
break;
……
}
…… }
3、由事件传递过程可见,Qt 可以使用以下 5 种方式来处理事件
①、重新实现各部件内部默认的事件处理函数,比如重新实现 paintEvent()、mousePressEvent()等事件处理函数,这是最常用、最简单的方式
②、重新实现 QObject::event()函数(需继承 QObject 类),使用该方式,可以在事件到达默认的事件处理函数之前捕获到该事件。该方式常被用来处理 Tab 键的默认意义。在重新实现 event()函数时,必须对未明确处理的事件调用基类的 event()函数,比如,若子类化 QWidget,并重写了 event()函数,但未调用父类的 event()函数,则程序可能会不能正常显示界面
③、在 QObject 对象上安装(或称为注册)事件过滤器。对象一旦使用installEventFilter()注册,传递给目标对象的所有事件都会先传递给这个监视对象的eventFilter()函数。或同一对象上安装了多个事件处理器,则按照安装的逆序依次激活这些事件处理器
④、在 QApplication 上安装(或称为注册)事件过滤器。该方式与重新实现 notify 函数一样强大。一旦在 QApplication 对象(程序中只有一个这种类型的对象)上注册了事件过滤器,则程序中每个对象的每个事件都会在发送到其他事件过滤器之前,发送到这个eventFilter()函数。该方式对于调试非常有用
⑤、子类化 QApplication,并重新实现 QCoreApplication::notify()函数,由事件传递过程可知,该函数提供了对事件的完全控制,因此功能非常强大,所以重写该函数会很复杂,也因此此方法很少被使用。这是唯一能在事件过滤器之前捕获到事件的方式
⑥、注意:exec()、notify()和 event()函数都不会处理事件,他们只是根据事件的类型进行事件的传递(或分发)。
 
 
 
 
 

 

  

 

posted @   天子骄龙  阅读(517)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示

目录导航