【Qt 事件】—— 详解Qt事件处理

2024-09-02 06:52
文章标签 详解 qt 事件 事件处理

本文主要是介绍【Qt 事件】—— 详解Qt事件处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

 (一)事件介绍 

(二)事件的处理

(三)按键事件 

3.1 单个按键

3.2 组合按键

(四)鼠标事件

4.1 鼠标单击事件

4.2 鼠标释放事件

 4.3 鼠标双击事件

4.4 鼠标移动事件 

4.5 滚轮事件 

(五) 定时器

5.1 QTimerEvent类

5.2 QTimer类

(六)事件分发器 

6.1 概述

6.2 事件分发器工作原理

(七)事件过滤器 

总结


【前情提示】

信号槽:

  • 用户进行的各种操作,就可能会产生出信号.可以给某个信号指定槽函数. 当信号触发时,就能够自动的执行到对应的槽函数.

事件非常类似

  • 用户进行的各种操作,也会产生事件.程序员同样可以给事件关联上处理函数(处理的逻辑),当事件触发的时候,就能够执行到对应的代码。

事件本身是操作系统提供的机制.Qt 也同样把操作系统事件机制进行了封装.但是由于事件对应的代码编写起来不是很方便.Qt 对于事件机制又进行了进一步的封装,就得到了信号槽。

⭐️⭐️ 信号槽就是对于事件的进一步封装;事件是信号槽的底层机制.

实际 Qt 开发程序过程中,绝大部分和用户之问进行的交互都是通过“信号槽”来完成的。
有些特殊情况下,信号槽不一定能搞定.(某个用户的动作行为,Qt 没有提供对应的信号….)此时就需要通过重写事件处理函数的形式,来手动处理事件的响应逻辑。

 (一)事件介绍 

事件是应用程序内部或者外部产生的事情或者动作的统称在Qt中使用⼀个对象来表示⼀个事件。所有的Qt事件均继承于抽象类QEvent。事件是由系统或者Qt平台本⾝在不同的时刻发出的。当用户 按下⿏标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出⼀个相应的事件。⼀些事件是在用户操作时发出,如键盘事件、⿏标事件等,另⼀些事件则是由系统本⾝⾃动发出,如定时器事件。常见的Qt事件如下:

 常见事件描述:

事件名称描述
⿏标事件⿏标左键、⿏标右键、⿏标滚轮,⿏标的移动,⿏标按键的按下和松开
键盘事件按键类型、按键按下、按键松开
定时器事件定时时间到达
进入离开事件⿏标的进入和离开
滚轮事件⿏标滚轮滚动
绘屏事件重绘屏幕的某些部分
显示隐藏事件窗口的显示和隐藏
移动事件窗口位置的变化
窗口事件是否为当前窗口
大小改变事件窗口大小改变
焦点事件键盘焦点移动
拖拽事件用⿏标进⾏拖拽

(二)事件的处理

事件处理⼀般常用的方法为:重写相关的Event函数

在Qt中,几乎所有的Event函数都是虚函数,所以可以重新实现。如:在实现⿏标的进⼊和离开事件 时,直接重新实现enterEvent()和 leaveEvent()即可。enterEvent()和 leaveEvent()函数原型如 下 :

示例如下:

  •  1、新建Qt项⽬,基类选择QWidget,同时勾选UI界⾯⽂件,如下图示:

  • 2、设计UI⽂件,如下图示;

 

  • 3、在项目中新添加⼀个类:MyLabel; 先选中项目名称QEvent,点击⿏标右键,选择addnew...,弹出如下对话框: 

  •  4、选择:Choose....,弹出如下界面:

  • 5、此时项目中会新添加以下两个文件: 

  • 6、在帮助文档中查找对应的内容; 

  • 7、点击"显示"之后,出现如下内容: 

  •  8、复制enterEvent(),粘贴在项目文件mylabel.h中;

  •  9、重写enterEvent()⽅法;

  •  10、在UI文件中选中Label,右键------>提升为...

  • 11、当点击"提升为..."之后,弹出如下对话框: 

  •  12、修改基类:

  •  13、执行效果如下:当鼠标进入设计好的标签之后,就会在应用程序输出栏中打印:鼠标进入(同理鼠标离开也是一样)


示例2:鼠标左键点击时,打印对应的坐标值;鼠标右键点击时,打印基于屏幕的坐标,点击完毕显示释放操作

  •  1、在上述示例的基础上,在mylabel.h中声明mousePressEvent()⽅法;
//当⿏标点击时,获取对应的坐标值
void mousePressEvent(QMouseEvent *event);
//鼠标释放操作
void mouseReleaseEvent(QMouseEvent *event);
  •  2、在mylabel.cpp中重写mousePressEvent()⽅法;
void mylabel::mousePressEvent(QMouseEvent *event)
{//按下右键if(event->button() == Qt::RightButton){//基于globalqDebug() << "鼠标右键已经按下 x = "<<event->globalX();qDebug() << "鼠标右键已经按下 x = "<<event->globalY();}//按下左键if(event->button() == Qt::LeftButton){//基于窗口的坐标qDebug() << "鼠标左键已经按下 x = "<<event->x();qDebug() << "鼠标左键已经按下 x = "<<event->y();}//按下中间键if(event->button() == Qt::MidButton){qDebug() << "鼠标已经按下 x = "<<event->x();qDebug() << "鼠标已经按下 x = "<<event->y();}
}void mylabel::mouseReleaseEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){qDebug() << "左键被释放";}else if(event->button() == Qt::RightButton){qDebug() << "右键被释放";}else if(event->button() == Qt::MidButton){qDebug() << "中键被释放";}
}

 实现效果如下:


(三)按键事件 

在Qt框架中,处理按键事件是交互式应用程序的一个重要方面。按键事件主要涉及QKeyEvent类,它提供了关于键盘事件的信息,如按键的类型、状态等。

当键盘上的按键被按下或者被释放时,键盘事件便会触发。在帮助文档中查找QKeyEvent类如下:

查找按键事件中所有的按键类型:在帮助文档中输⼊:Qt::Key,如下图: 

 


3.1 单个按键

示例:当某个按键被按下时,输出:某个按键被按下了;

  • 1、新建项目,在头文件widget.h中声明虚函数keyPressEvent();如下图: 

  •  2、在widget.cpp⽂件中重写keyPressEvent()虚函数;


3.2 组合按键

在Qt助手中搜索:Qt::KeyboardModifier,如下图示:

Qt::KeyboardModifier 中定义了在处理键盘事件时对应的修改键。在Qt中,键盘事件可以与修改键 ⼀起使用,以实现⼀些复杂的交互操作。KeyboardModifier 中修改键的具体描述如下: 

示例如下:


(四)鼠标事件

在Qt框架中,处理鼠标事件是创建交互式图形用户界面的关键部分。鼠标事件包括鼠标点击、双击、移动、滚轮滚动等。这些事件由QMouseEvent类表示,它提供了关于鼠标事件的详细信息,如鼠标位置、按钮状态等。

利⽤QMouseEvent类可以获取⿏标的哪个键被按下了以及⿏标的当前位置等信息。在Qt帮助⽂档中 查找QMouseEvent类如下:

 


鼠标单击和释放操作代码在上述已经完成,下述就不在展示代码!!

4.1 鼠标单击事件

在Qt中,⿏标按下是通过虚函数mousePressEvent()来捕获的。mousePressEvent()函数原型如 下:

 [virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)

⿏标左右键及滚的表示如下:

  • Qt::LeftButton ⿏标左键
  • Qt::RightButton ⿏标右键
  • Qt::MidButton ⿏标滚轮

4.2 鼠标释放事件

⿏标释放事件是通过虚函数mouseReleaseEvent()来捕获的。mouseReleaseEvent()函数原型如 下:

 [virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)

 4.3 鼠标双击事件

⿏标双击事件是通过虚函数:mouseDoubleClickEvent()来实现的。mouseDoubleClickEvent() 函数原型如下:

[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
void mylabel::mouseDoubleClickEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){qDebug() << "左键被双击";}else if(event->button() == Qt::RightButton){qDebug() << "右键被双击";}else if(event->button() == Qt::MidButton){qDebug() << "中键被双击";}
}

4.4 鼠标移动事件 

⿏标移动事件是通过虚函数:mouseMoveEvent()来实现的。同时为了实时捕获⿏标位置信息,需要 通过函数setMouseTracking()来追踪⿏标的位置。mouseMoveEvent()函数原型如下:

[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent*event)///
//setMouseTracking()函数原型如下:
void setMouseTracking(bool enable)说明:
setMouseTracking() 函数默认是false,需要设置为true,才能实时捕获⿏标位置信息;
否则只有当⿏标按下时才能捕获其位置信息。

示例如下:


4.5 滚轮事件 

在Qt中,⿏标滚轮事件是通过QWheelEvent类来实现的。滚轮滑动的距离可以通过delta()函数获 取。delta()函数原型如下:

int QGraphicsSceneWheelEvent::delta() const
  • 其中返回值代表滚轮滑动的距离。正数表示滚轮相对于用户向前滑动,负数表示滚轮相对于用户向后滑动。
void Widget::wheelEvent(QWheelEvent *event)
{//滚轮事件static int x = 0;x += event->delta();if(event->delta() > 0){qDebug() << "滚轮向前移动了" << x;}else if(event->delta() < 0){qDebug() << "滚轮向后移动了" << x;}
}

执行效果如下: 


(五) 定时器

Qt 中在进行窗口程序的处理过程中,经常要周期性的执行某些操作,或者制作⼀些动画效果,使用定时器就可以实现。所谓定时器就是在间隔⼀定时间后,去执行某⼀个任务。定时器在很多场景下都会使用到,如弹窗自动关闭之类的功能等。

Qt中的定时器分为QTimerEventQTimer这2个类。

  • QTimerEvent类⽤来描述⼀个定时器事件。在使⽤时需要通过startTimer()函数来开启⼀个定时器,这个函数需要输⼊⼀个以毫秒为单位的整数作为参数来表明设定的时间,它返回的整型值代表 这个定时器。当定时器溢出时(即定时时间到达)就可以在timerEvent()函数中获取该定时器的编号来进行相关操作。
  • QTimer类来实现⼀个定时器,它提供了更⾼层次的编程接⼝,如:可以使⽤信号和槽,还可以设置只运⾏⼀次的定时器。

5.1 QTimerEvent类

示例:在UI界⾯上放置控件,程序启动开始倒计时操作

void Widget::timerEvent(QTimerEvent *event)
{//先判定触发的是否为想要触发的if(event->timerId() != this->timerid){return;}int value = ui->lcdNumber->intValue();if(value <= 0){//停止定时器this->killTimer(this->timerid);return;}value -= 1;ui->lcdNumber->display(value);
}

 实现效果如下:

 


5.2 QTimer类

示例:在UI界面放置⼀个Label标签,两个按钮,分别是"开始"和"停止",当点击"开始"按钮时, 开始每隔1秒计数⼀次,点击"停止"按钮时,暂停计数。

    ui->setupUi(this);QTimer *time = new QTimer(this);connect(ui->btn1 , &QPushButton::clicked,[=](){time->start(1000);});connect(time , &QTimer::timeout,[=](){static int num = 1;ui->label->setText(QString::number (num++));});connect(ui->btn2 , &QPushButton::clicked,[=](){time->stop();});

 实现效果如下:


(六)事件分发器 

6.1 概述

在Qt中,事件分发器(EventDispatcher)是⼀个核心概念,⽤于处理GUI应用程序中的事件。事件分发器负责将事件从⼀个对象传递到另⼀个对象,直到事件被处理或被取消。每个继承自QObject类或 QObject类本⾝都可以在本类中重写boolevent(QEvent*e)函数,来实现相关事件的捕获和拦截。

6.2 事件分发器工作原理

在Qt中,我们发送的事件都是传给了QObject对象,更具体点是传给了QObject对象的event()函 数。所有的事件都会进入到这个函数里面,那么我们处理事件就要重写这个event()函数。event()函数本身不会去处理事件,是而根据事件类型(type值)调用不同的事件处理函数。事件分发器就是工作在应用程序向下分发事件的过程中,如下图:

 如上图,事件分发器用于分发事件。在此过程中,事件分发器也可以做拦截操作。事件分发器主要是 通过boolevent(QEvent*e)函数来实现。其返回值为布尔类型,若为ture,代表拦截,不向下分发。

Qt 中的事件是封装在QEvent类中,在Qt助手中输入QEvent可以查看其所包括的事件类型,如下图示:

示例:

  • 1、在widget.h头文件中声明鼠标点击事件和事件分发器;如下图示:

  • 2、在widget.cpp文件中实现鼠标点击事件和拦截事件; 

 

 执行结果如下:


(七)事件过滤器 

在Qt中,⼀个对象可能经常要查看或拦截另外⼀个对象的事件,如对话框想要拦截按键事件,不让别的组件接收到,或者修改按键的默认值等。通过上面的学习,我们已经知道,Qt创建了QEvent事件对象之后,会调用QObject的event()函数处理事件的分发。显然,我们可以在event()函数中实现拦 截的操作。由于event()函数是protected的,因此,需要继承已有类。如果组件很多,就需要重写很多个event()函数。这当然相当麻烦,更不用说重写event()函数还得小心⼀堆问题。好在Qt提供了另外⼀种机制来达到这⼀目的:事件过滤器

 事件过滤器是在应用程序分发到event事件分发器之前,再做⼀次更高级的拦截。如下图示:

 

事件过滤器的⼀般使⽤步骤:

  • 1、安装事件过滤器;
  • 2、重写事件过滤器函数:eventfilter()。 

示例如下:

  • 1、新建Qt项目,基类选择QWidget,同时勾选UI界面⽂件,如下图; 

 

  • 2、设计UI⽂件,如下图; 

  • 3、在项目新添加⼀个类:MyLabel; 先选中项名目称QEvent,点击⿏标右键,选择addnew...,弹出如下对话框: 

  •  4、选择:Choose....,弹出如下界面:

  • 5、此时项目中会新添加以下两个文件;在UI文件中选中Label,右键------>提升为... 

  • 6、当点击"提升为..."之后,弹出如下对话框: 

  • 7、在mylabel.h中声明鼠标点击事件和事件分发器; 

  • 8、在mylabel.cpp⽂件中实现鼠标点击事件和事件分发器; 

  • 9、在widget.h头文件中声明事件过滤器函数; 

  • 10、在widget.cpp⽂件中实现事件过滤器的两个步骤;

 执行结果如下:


总结

Qt的事件处理机制非常灵活,通过事件循环、事件对象、信号与槽机制以及事件过滤器,可以高效地处理各种用户交互和系统事件。理解这些概念对于开发复杂的Qt应用程序至关重要。

这篇关于【Qt 事件】—— 详解Qt事件处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129307

相关文章

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

python logging模块详解及其日志定时清理方式

《pythonlogging模块详解及其日志定时清理方式》:本文主要介绍pythonlogging模块详解及其日志定时清理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录python logging模块及日志定时清理1.创建logger对象2.logging.basicCo

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行