虽然 Qt 是跨平台的 C++ 开发框架,Qt 有很多能力其实是操作系统提供的,只不过 Qt 封装了系统的 API
程序时运行在操作系统上的,需要系统给我们提供支撑!
- 事件
- 文件操作
- 多线程编程
- 网络编程
- 多媒体(音频,视频)
Qt 事件
事件介绍
信号槽:用户进行的各种操作可能会产生出信号,我们可以给某个信号指定槽函数,当信号触发时,就能够自动的执行到对应的槽函数!
事件也是非常类似的,用户进行的各种操作,也会产生事件,程序员同样可以给事件关联上处理函数(处理的逻辑),当事件触发的时候,就能够执行到对应的代码!
事件本身是操作系统提供的机制,Qt 也同样把操作系统事件进行了封装,拿到了 Qt 中!但是由于事件对应的代码编写不是很方便,所以 Qt 对于事件这样的机制又进行了封装,就得到了信号槽!
所以事件就是信号槽的底层机制!实际 Qt 开发程序过程中,绝大部分和用户之间进行的交互是通过“信号槽”来完成的!但是对于有些特殊情况,信号槽不一定能搞定(某个用户的动作行为,Qt 没有提供对应的信号...这时候我们就需要通过重写事件的处理函数的形式,来手动处理事件的响应逻辑)
事件是应用程序内部或者外部产生的事情或者动作的统称。在 Qt 中使用一个对象来表示一个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件是在用户操作时发出,如键盘事件、鼠标事件等,另一些事件则是由系统本身自动发出,如定时器事件。常见的 Qt 事件如下:
常见事件描述:
事件名称 | 描述 |
---|---|
鼠标事件 | 鼠标左键、鼠标右键、鼠标滚轮,鼠标的移动,鼠标按键的按下和松开 |
键盘事件 | 按键类型、按键按下、按键松开 |
定时器事件 | 定时时间到达 |
进入离开事件 | 鼠标的进入和离开 |
滚轮事件 | 鼠标滚轮滚动 |
绘屏事件 | 重绘屏幕的某些部分 |
显示隐藏事件 | 窗口的显示和隐藏 |
移动事件 | 窗口位置的变化 |
窗口事件 | 是否为当前窗口 |
大小改变事件 | 窗口大小改变 |
焦点事件 | 键盘焦点移动 |
拖拽事件 | 用鼠标进行拖拽 |
事件的处理
让一段代码和某一个事件关联起来,当事件触发的时候,就能指定到这段代码
之前信号槽是通过 connect 来完成上述关联的!对于事件来说,还不太一样:
事件处理一般常用的方法为:重写相关的 Event 函数。(用到了面向对象的多态的机制:创建子类,然后继承自 Qt 中已有的类,在子类中重写父类的事件处理函数,后续事件出发过程中,就会通过多态这样的机制,执行到咱们自己写的子类的函数中!)
在 Qt 中,几乎所有的 Event 函数都是虚函数,所以可以重新实现。如:在实现鼠标的进入和离开控件时,直接重新实现 enterEvent() 和 leaveEvent() 即可。enterEvent() 和 leaveEvent() 函数原型如下:
[virtual protected] void QWidget::enterEvent(QEvent *event)
This event handler can be reimplemented in a subclass to receive widget enter events which are passed in the
event
parameter. An event is sent to the widget when the mouse cursor enters the widget.See also leaveEvent(), mouseMoveEvent(), and event().
[virtual protected] void QWidget::leaveEvent(QEvent *event)
This event handler can be reimplemented in a subclass to receive widget leave events which are passed in the
event
parameter. A leave event is sent to the widget when the mouse cursor leaves the widget.See also enterEvent(), mouseMoveEvent(), and event().
示例1:
1. 新建 Qt 项目,基类选择 QWidget,同时勾选 UI 界面文件,如下图所示:
2. 设计 ui 文件,如下所示:
3. 在项目中新添加一个类:MyLabel;
创建 QLable 子类,重写 enterEvent 和 leaveEvent!
先选中项目名称 QEvent,点击鼠标右键,选择 add new ...,弹出如下对话框:
4. 选择:Choose ...,弹出如下界面:
5. 此时项目会新增如下两个文件:
6. 在帮助文档中查找对应的内容:
7. 点击“显示”之后,出现如下内容:
[virtual protected] void QWidget::enterEvent(QEvent *event)
This event handler can be reimplemented in a subclass to receive widget enter events which are passed in the
event
parameter. An event is sent to the widget when the mouse cursor enters the widget.See also leaveEvent(), mouseMoveEvent(), and event().
8. 复制 enterEvent() ,粘贴在项⽬⽂件 "mylabel.h" 中:
9. 重写 enterEvent() ⽅法:
10. 在 UI ⽂件中选中 Label,右键 ------> 提升为...
我们直接执行是不行的!
因为当前界面上创建的这个 label 其实是QLabel,不是我们自己写的 MyLabel!
必须要确保界面上的这个 label 是一个咱们自己定义的 Mylabel 的示例,才会执行到!
11. 当点击 "提升为... " 之后,弹出如下对话框:
12. 修改基类:
13. 执⾏效果如下:当⿏标进⼊设计好的标签之后,就会在应⽤程序输出栏中打印:⿏标进⼊:
示例2:当鼠标点击时,获取对应的坐标值
1. 在上述示例的基础上,在 mylabel.h
中声明 mousePressEvent()
方法:
#ifndef MYLABEL_H
#define MYLABEL_H#include <QLabel>class MyLabel : public QLabel
{Q_OBJECT
public:explicit MyLabel(QWidget *parent = nullptr);// 鼠标进入事件void enterEvent(QEvent *ev);// 鼠标移动事件void mousePressEvent(QMouseEvent *ev);signals:};#endif // MYLABEL_H
2. 在 mylabel.cpp
中重写 mousePressEvent()
方法:
#include "mylabel.h"
#include <QDebug>
#include <QMouseEvent>MyLabel::MyLabel(QWidget *parent) : QLabel(parent)
{
}void MyLabel::enterEvent(QEvent *ev)
{qDebug() << "鼠标进入";
}void MyLabel::mousePressEvent(QMouseEvent *ev)
{// Qt中的格式化字符串QString str1 = QString("鼠标按下了 x = %1, y = %2").arg(ev->x()).arg(ev->y());qDebug() << str1;
}
实现效果如下:
鼠标进入
"鼠标按下了 x = 54, y = 61"
"鼠标按下了 x = 234, y = 15"
"鼠标按下了 x = 393, y = 51"
"鼠标按下了 x = 180, y = 140"
"鼠标按下了 x = 488, y = 146"
示例:鼠标左键点击时,打印对应的坐标值,鼠标右键点击时,打印基于屏幕的坐标
void MyLabel::mousePressEvent(QMouseEvent *ev)
{// 鼠标左键if(ev->button() == Qt::LeftButton){// x,y为基于窗口的坐标QString str = QString("鼠标左键:x = %1, y = %2").arg(ev->x()).arg(ev->y());qDebug() << str.toUtf8().data();}// 鼠标右键if(ev->button() == Qt::RightButton){// globalX,globalY为基于屏幕的坐标QString str = QString("鼠标右键:x = %1, y = %2").arg(ev->globalX()).arg(ev->globalY());qDebug() << str.toUtf8().data();}
}
按键事件
Qt 中的按键事件是通过 QKeyEvent
类来实现的。当键盘上的按键被按下或者被释放时,键盘事件便会触发。在帮助文档中查找 QKeyEvent
类如下:
查找按键事件中所有的按键类型:在帮助⽂档中输⼊:Qt::Key,如下图:
单个按键事件处理
示例:当某个按键被按下时,输出提示信息:“某个按键被按下了”。
1. 新建项目:在项目的头文件 widget.h
中声明一个虚函数 keyPressEvent()
。
2. 在 "widget.cpp" ⽂件中重写 keyPressEvent() 虚函数;
组合按键
在 Qt 助⼿中搜索:Qt::KeyboardModifier,如下图⽰:
在Qt中,键盘事件可以通过Qt::KeyboardModifier
枚举来处理,该枚举定义了在处理键盘事件时对应的修饰键。以下是Qt::KeyboardModifier
中定义的修饰键及其描述:
常量 | 描述 |
---|---|
Qt::NoModifier | 无修改键 |
Qt::ShiftModifier | Shift 键 |
Qt::ControlModifier | Ctrl 键 |
Qt::AltModifier | Alt 键 |
Qt::MetaModifier | Meta键(在Windows上指Windows键,在macOS上指Command键) |
Qt::KeypadModifier | 使用键盘上的数字键盘进行输入时,Num Lock键处于打开状态 |
Qt::GroupSwitchModifier | 用于在输入法组之间切换 |
这些修饰键在Qt中可以与键盘事件一起使用,以实现一些复杂的交互操作。例如,在处理键盘事件时,可以通过检查这些修饰键的状态来判断用户是否同时按下了特定的组合键。
示例:
鼠标事件
在 Qt 中,鼠标事件是用 QMouseEvent 类来实现的。当在窗口中按下鼠标或者移动鼠标时,都会产生鼠标事件。
利用 QMouseEvent 类可以获取鼠标的哪个键被按下了以及鼠标的当前位置等信息。在 Qt 帮助文档中查找QMouseEvent类 如下图所示:
鼠标单击事件
在 Qt 中,鼠标按下是通过虚函数 mousePressEvent() 来捕获的。mousePressEvent() 函数原型如下:
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)
鼠标左右键及滚的表示如下:
Qt::LeftButton 鼠标左键
Qt::RightButton 鼠标右键
Qt::MidButton 鼠标滚轮
示例1:鼠标左键
1. 在 "widget.h" 头文件中声明鼠标按下事件;
2. 在 "widget.cpp" ⽂件中重新实现 mousePressEvent() 函数;
实现效果如下:
示例2:鼠标右键
实现效果如下:
示例3:鼠标滚轮
实现效果如下:
鼠标释放事件
鼠标释放事件是通过虚函数 mouseReleaseEvent() 来捕获的。mouseReleaseEvent() 函数原型如下:
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)
示例:
执行效果如下:
鼠标双击事件
鼠标双击事件是通过虚函数:mouseDoubleClickEvent() 来实现的。mouseDoubleClickEvent() 函数原型如下:
[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
示例:鼠标左键双击
执行效果如下:
鼠标移动事件
鼠标移动事件是通过虚函数:mouseMoveEvent() 来实现的。同时为了实时捕获鼠标位置信息,需要通过函数 setMouseTracking() 来追踪鼠标的位置。mouseMoveEvent() 函数原型如下:
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)
setMouseTracking() 函数原型如下:
void setMouseTracking(bool enable)
说明:
setMouseTracking() 函数默认是 false,需要设置为 true,才能实时捕获鼠标位置信息。否则只有当鼠标按下时才能捕获其位置信息。
示例:
执行效果:
滚轮事件
在 Qt 中,鼠标滚轮事件是通过 QWheelEvent 类来实现的。滚轮滑动的距离可以通过 delta() 函数获取。delta() 函数原型如下:
int QGraphicsSceneWheelEvent::delta() const
其中返回值代表滚轮滑动的距离。正数表示滚轮相对于用户向前滑动,负数表示滚轮相对于用户向后滑动。
示例:
执行效果如下: