Qt-事件总结

一、事件简介

QT将系统产生的消息转化为QT事件,QT事件被封装为对象,所有的QT事件均继承抽象类QEvent,用于描述程序内部或外部发生的动作,任意的QObject对象都具备处理QT事件的能力。

事件是由系统或者QT平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如键盘事件等;另一些事件则是由系统自动发出,如计时器事件。常见的Qt事件如下:

  • 键盘事件(QKeyEvent): 处理键盘按键的按下和松开事件
  • 鼠标事件(QMouseEvent): 处理鼠标移动、鼠标按键的按下和松开事件
  • 拖放事件(QDragEvent 和 QDropEvent): 用鼠标进行拖放操作时涉及的事件,包括拖拽和放置
  • 滚轮事件(QWheelEvent): 处理鼠标滚轮的滚动事件
  • 绘图事件(QPaintEvent): 在控件需要重新绘制时触发,用于自定义绘制
  • 定时事件(QTimerEvent): 在定时器到期时触发,用于执行周期性任务
  • 焦点事件(QFocusEvent): 处理键盘焦点的移动,如窗口控件获得或失去焦点
  • 进入和离开事件(QEnterEvent 和 QLeaveEvent): 处理鼠标移入或移出窗口控件的事件
  • 移动事件(QMoveEvent): 处理窗口控件的位置改变事件
  • 大小改变事件(QResizeEvent): 处理窗口控件的大小改变事件
  • 显示和隐藏事件(QShowEvent 和 QHideEvent): 处理窗口控件的显示和隐藏事件
  • 窗口事件(QWindowStateChangeEvent): 处理窗口是否为当前窗口的状态变化事件

常用的鼠标事件

  • void mousePressEvent(QMouseEvent *); 按下
  • void mouseReleaseEvent(QMouseEvent *); 弹起
  • void mouseMoveEvent(QMouseEvent *); 按下时并移动
  • void mouseDoubleClickEvent(QMouseEvent *); 双击(会触发按下和弹起);

通过QMouseEvent 可以判断出是个按键

  • event->button() == Qt::LeftButton
  • event->button() == Qt::RightButton
  • event->button() == Qt::MidButton

常用的键盘事件

  • void keyPressEvent(QKeyEvent *); 按下
  • void keyReleaseEvent(QKeyEvent *); 弹起

通过QKeyEvent 可以判断出按键的键值

  • event->key == Qt::Key_Up;

常用的窗口事件

  • void closeEvent(QCloseEvent *); 窗口关闭
  • void paintEvent(QPaintEvent *); 窗口显示/绘图事件
  • void moveEvent(QMoveEvent *); 窗口移动

二、事件的分类

方式一:根据事件的来源和传递方式,事件可分为以下三大类:

  • 自发事件:这是由窗口系统生成的,这些事件置于系统队列中,并由事件循环一个接一个地处理。
  • 发布的事件(Posted events):该类事件由 Qt 或应用程序(属于自定义事件)生成,这些事件发布后由 Qt 排队,并由事件循环处理。
  • 发送的事件(Sent events):该类事件由 Qt 或应用程序(属于自定义事件)生成,这些事件直接发送到目标对象,不经过事件循环处理。

方式二:事件被细分为很多种类型(有一百多种),每一种类型使用 QEvent 类中的枚举常量进行表示,比如 QMouseEvent 管理的鼠标事件有鼠标双击、移动、按下等类型,这些类型分别使用 QEvent::Type 枚举类型中的枚举常量 MouseButtonDblClick、MouseMove、MouseButtonPress 表示。所有的类型分类请查阅帮助文档。可使用函数Type QEvent::type() const;获取事件的类型。

三、事件处理流程

我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高的)。所以在Qt框架内部为我们提供了一些事件处理机制,当窗口事件产生之后,事件会经过:事件派发(Qt应用程序对象发送的)—>事件过滤—>事件分发—>事件处理几个阶段。

每一个Qt应用程序都对应一个唯一的QApplication应用程序对象,然后调用这个对象的exec()函数,这样Qt框架内部的事件检测就开始了(程序将进入事件循环来监听应用程序的事件)

事件传递基本原则:

  • 若事件未被目标对象处理,则把事件传递给其父对象处理,若父对象仍未处理,则再传递给父对象的父对象处理,重复这个过程,直至这个事件被处理或到达顶级对象为止。注意事件是在对象间传递的,这里是指对象的父子关系,而不是指类的父子关系
  • 在 Qt 中有一个事件循环,该循环负责从可能产生事件的地方捕获各种事件,并把这些事件转换为带有事件信息的对象,然后由 Qt 的事件处理流程分发给需要处理事件的对象来处理事件。

事件在Qt中产生之后,其分发过程是这样的:
1)通过调用 QCoreApplication::exec()函数启动事件主循环,主循环从事件队列中获取事件,然后创建一个合适的 QEvent 对象或其子类类型的对象来表示该事件,在此步骤中,事件循环首先处理所有发布的事件,直到队列为空,然后处理自发的事件,最后处理在自发事件期间产生的已发布事件。注意:发送的事件不由事件循环处理,该类事件会被直接传递给对象

2)当事件产生之后,Qt使用应用程序对象调用notify()函数将事件发送到指定的窗口;

3)事件在发送过程中可以通过事件过滤器eventFilter()函数进行过滤,默认不对任何产生的事件进行过滤;

4)当事件发送到指定窗口后,窗口的事件分发器event()函数(每一个窗口都有)会对收到的事件进行分类;

5)事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件。。。)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函数),比如鼠标事件。

每个事件处理器函数都对应一个唯一的事件,这为我们重写定义事件的处理动作提供了便利。Qt提供的这些事件处理器函数都是回调函数,也就是说作为使用者我们只需要指定函数的处理动作,关于函数的调用是不需要操心的,当某个事件被触发,Qt框架会调用对应的事件处理器函数。

Qt里的事件基本都是在Protected Functions,要想调用这些基本,其必须是继承QObject或QWidget

窗口的事件处理器非常好找,规律是这样的:1)受保护的虚函数;2)函数名分为2部分:事件描述+Event;3)函数带一个事件类型的参数。

定时器事件
Qt里定时器设置2种方法:1种是调用QTimer类,另外一种是就是调用QObject类的Protected Function函数里的TimerEvent()事件(定时器事件)。

四、事件循环机制

Qt中的事件循环(Event Loop)是一种机制,用于处理事件和信号,并且驱动应用程序的整个事件处理过程。

事件循环主要由Qt的事件系统和对象的信号与槽机制组成。

以下是关于事件循环机制的一些说明:
1.事件处理流程:在事件循环机制下,Qt应用程序会进入一个无限循环,该循环会不断处理各种事件,直到应用程序退出。在事件循环中,Qt会不停的检查事件是否发生,然后会分发相应的事件到合适的对象进行处理。

2.事件源:事件源是导致事件发生的对象,可以是用户操作、系统事件或其他应用程序内部事件。列如,按钮的点击、定时器的超时、网络数据的到达等都可以作为事件源。

3.事件类型和事件过滤器:Qt事件系统提供了一系列事件类型,用于标识不同类型的事件,列如鼠标点击事件、键盘事件、定时器事件等。事件过滤器可以被用来截获和修改事件的处理过程。通过重写事件过滤器函数,可以在对象处理事件之前先拦截和处理事件。

4.事件分发和派发:当事件发生时,Qt会将事件分发给合适的对象进行处理。事件的分发是根据事件分发规则和事件传递机制来进行的。经过事件分发后,事件最终会被派发到目标对象的事件处理函数(列如QWidget的事件处理函数)进行具体的处理。

5.信号和槽机制:信号与槽机制是一种Qt特有的机制,用于对象之间的通信和事件处理。当对象发生某个特定的事件或者状态发生变化时,可以通过发射信号来通知其他对象。其他对象可以将自己的槽函数与信号进行连接,以响应信号的发射并执行相应的处理逻辑。

6.线程和事件循环:每个线程都有一个独立的事件循环,这是关键!!!在多线程应用程序中,每个线程通常都有自己的事件循环,用来处理来自线程内部或外部的事件和信号.线程之间可以通过信号与槽机制进行异步的事件通信

五、事件与信号区别

Qt 的事件和Qt中的signal不一样. 信号通常用来"使用"widget, 而事件用来"实现" widget。比如一个按钮, 我们使用这个按钮的时候, 我们只关心他clicked()的signal, 至于这个按钮如何接收处理鼠标事件,再发射这个信号,我们是不用关心的。但是如果我们要重载一个按钮的时候,我们就要面对event了。 比如我们可以改变它的行为,在鼠标按键按下的时候(mouse press event) 就触发clicked()的signal而不是通常在释放的( mouse release event)时候.。

信号通过事件实现,事件可以过滤,事件更底层,事件是基础,信号是扩展

信号和槽机制用于对象之间的通信,而事件机制用于对象的行为和状态变化的处理

信号是由对象产生的,而事件则不一定是由对象产生的(比如由鼠标产生的事件),事件通常来自底层的窗口系统,但也可以手动发送自定义的事件,可见信号和事件的来源是不同的

事件既可以同步使用,也可以异步使用 (取决于调用 sendEvent()还是 postEvents()),而使用信号和槽总是同步的。事件的另一个好处是可以被过滤。

六、常用事件函数(系统定义)

Qt 事件对象(QEvent)的两个函数:

  • accept() 通知QT平台,事件处理函数要处理这个事件
  • ignore() 则通知QT平台,事件处理函数不处理这个事件
    如果一个事件处理函数调用了一个事件对象的accept()函数,这个事件就不会被继续传播给其父组件;如果事件对象调用了事件的ignore()函数,QT平台会从其父组件中寻找另外的接受者。

在事件处理函数中,可以使用isAccepted()来查询某个事件是不是已经被接受

通常很少会使用accept()和ignore()函数,如果希望忽略事件,只要调用父类的相应事件处理函数即可。

由于无法确认父类中相应的事件处理函数有没有额外的操作,如果在子类中直接使用ignore()函数忽略事件,QT会去寻找其他的接受者,父类的操作会被忽略(因为没有调用父类的同名函数),这可能会有潜在的危险。

为了避免子类去调用accept()和ignore()函数,而是尽量调用父类实现,QT做了特殊的设计:事件对象默认是accept的,而作为所有组件的父类QWidget的默认实现则是调用ignore()。

因此,如果子类重新实现事件处理函数,不调用QWidget的默认实现,就等于接受事件;如果要忽略事件,只需调用QWidget的默认事件处理函数实现。

七、常用事件函数(自定义重写)

事件分发器event

事件对象创建完毕后,QT将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型分发给不同的事件处理器(event handler)。event()函数主要用于事件的分发。如果期望在事件分发前做一些操作,可以重写event()函数。
举例如下:
/* 在QWidget组件中监听左键按下事件 */

bool MyWidget::event(QEvent *event)
{
   
    if (event
  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中,可以通过重写控件的鼠标事件函数来实现对鼠标事件的响应。常见的鼠标事件包括鼠标进入控件事件、鼠标离开控件事件、控件内按下鼠标事件和控件内释放鼠标事件。 对于控件内的鼠标按下事件,可以通过判断事件类型(event->type())是否为QEvent::MouseButtonPress来进行处理。 对于控件内的鼠标释放事件,可以通过判断事件类型(event->type())是否为QEvent::MouseButtonRelease来进行处理。 可以根据具体的需求,在控件的鼠标事件函数中编写相应的代码来处理对应的鼠标事件。例如,你可以在鼠标按下事件中执行某些操作,或者在鼠标释放事件中执行其他操作。 需要注意的是,不同的控件可能会有不同的鼠标事件函数名称和参数,具体可以根据Qt文档或相关教程来查找相应的函数并进行重写。 总结来说,通过重写控件的鼠标事件函数,可以将鼠标事件与控件的响应行为进行绑定,实现对鼠标事件的处理和控制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Qt5.9的鼠标事件:鼠标进入控件事件、鼠标离开控件事件、鼠标摁下控件事件、鼠标释放控件事件](https://blog.csdn.net/naibozhuan3744/article/details/82154880)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值