
🎬 个人主页 :艾莉丝努力练剑
❄专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平
🎬 艾莉丝的简介:

文章目录
- 导入
- [1 ~> 事件基本概念](#1 ~> 事件基本概念)
-
- [1.1 事件与信号槽的本质关系](#1.1 事件与信号槽的本质关系)
- [1.2 QEvent类体系](#1.2 QEvent类体系)
- [1.3 事件的核心处理机制](#1.3 事件的核心处理机制)
- [2 ~> 鼠标事件详解](#2 ~> 鼠标事件详解)
-
- [2.1 鼠标进入与离开事件](#2.1 鼠标进入与离开事件)
-
- [2.1.1 函数原型](#2.1.1 函数原型)
- [2.1.2 完整实现步骤](#2.1.2 完整实现步骤)
- [2.2 鼠标点击事件](#2.2 鼠标点击事件)
-
- [2.2.1 函数原型与参数](#2.2.1 函数原型与参数)
- [2.2.2 鼠标按键类型判断](#2.2.2 鼠标按键类型判断)
- [2.2.3 实现代码](#2.2.3 实现代码)
- [2.3 鼠标释放与双击事件](#2.3 鼠标释放与双击事件)
-
- [2.3.1 鼠标释放事件](#2.3.1 鼠标释放事件)
- [2.3.2 鼠标双击事件](#2.3.2 鼠标双击事件)
- [2.3.3 重要注意事项](#2.3.3 重要注意事项)
- [2.4 鼠标移动事件](#2.4 鼠标移动事件)
-
- [2.4.1 默认行为与鼠标追踪](#2.4.1 默认行为与鼠标追踪)
- [2.4.2 实现代码](#2.4.2 实现代码)
- [2.5 鼠标滚轮事件](#2.5 鼠标滚轮事件)
-
- [2.5.1 函数原型与delta()方法](#2.5.1 函数原型与delta()方法)
- [2.5.2 累计滚动距离实现](#2.5.2 累计滚动距离实现)
- [3 ~> 键盘事件详解](#3 ~> 键盘事件详解)
-
- [3.1 键盘事件的触发条件](#3.1 键盘事件的触发条件)
- [3.2 单个按键的捕获与判断](#3.2 单个按键的捕获与判断)
- [3.3 组合键(快捷键)的处理](#3.3 组合键(快捷键)的处理)
- [3.4 与QShortCut的对比](#3.4 与QShortCut的对比)
- [4 ~> 定时器事件详解](#4 ~> 定时器事件详解)
-
- [4.1 QTimerEvent的使用](#4.1 QTimerEvent的使用)
-
- [4.2.1 核心函数](#4.2.1 核心函数)
- [4.2.2 定时器ID的作用](#4.2.2 定时器ID的作用)
- [4.2.3 倒计时功能完整实现](#4.2.3 倒计时功能完整实现)
- [4.3 QTimer与QTimerEvent的对比](#4.3 QTimer与QTimerEvent的对比)
- [5 ~> 窗口事件详解](#5 ~> 窗口事件详解)
-
- [5.1 窗口移动事件moveEvent](#5.1 窗口移动事件moveEvent)
- [5.2 窗口大小改变事件resizeEvent](#5.2 窗口大小改变事件resizeEvent)
- [6 ~> 事件分发器简介](#6 ~> 事件分发器简介)
-
- [6.1 事件分发器的工作原理](#6.1 事件分发器的工作原理)
- [6.2 event()函数的作用](#6.2 event()函数的作用)
- [6.3 使用注意事项](#6.3 使用注意事项)
- 全文总结
- 结尾

导入

思维导图
bash
Qt事件机制
├─ 1 事件基本概念
│ ├─ 1.1 事件与信号槽关系
│ │ ├─ 信号槽是事件的上层封装
│ │ ├─ 事件是信号槽的底层机制
│ │ └─ 特殊场景需直接使用事件
│ ├─ 1.2 QEvent类体系
│ │ ├─ 基类QEvent
│ │ ├─ 子类:QMouseEvent/QKeyEvent等
│ │ └─ 事件对象携带交互信息
│ ├─ 1.3 常见事件类型
│ │ ├─ 鼠标/键盘/定时器事件
│ │ ├─ 进入离开/滚轮/绘屏事件
│ │ └─ 窗口移动/大小改变/焦点事件
│ └─ 1.4 事件处理核心
│ ├─ 重写父类虚函数
│ ├─ 利用C++多态机制
│ └─ 控件提升为自定义类
├─ 2 鼠标事件详解
│ ├─ 2.1 进入离开事件
│ │ ├─ enterEvent()/leaveEvent()
│ │ └─ 控件提升操作步骤
│ ├─ 2.2 点击事件mousePressEvent
│ │ ├─ 局部坐标x()/y()
│ │ ├─ 全局坐标globalX()/globalY()
│ │ └─ 按键类型判断Qt::MouseButton
│ ├─ 2.3 释放与双击事件
│ │ ├─ mouseReleaseEvent()
│ │ ├─ mouseDoubleClickEvent()
│ │ └─ 单击与双击冲突问题
│ ├─ 2.4 移动事件mouseMoveEvent
│ │ ├─ 默认不追踪鼠标移动
│ │ └─ setMouseTracking(true)开启
│ └─ 2.5 滚轮事件wheelEvent
│ ├─ delta()获取滚动距离
│ └─ 累计滚动实现功能
├─ 3 键盘事件详解
│ ├─ 3.1 keyPressEvent()/keyReleaseEvent()
│ ├─ 3.2 单个按键判断Qt::Key_*枚举
│ ├─ 3.3 组合键处理modifiers()
│ │ └─ Qt::ControlModifier/ShiftModifier
│ └─ 3.4 与QShortCut的对比
├─ 4 定时器事件详解
│ ├─ 4.1 两种实现方式
│ │ ├─ QTimer(高层接口,推荐)
│ │ └─ QTimerEvent(底层事件)
│ ├─ 4.2 QTimerEvent核心
│ │ ├─ startTimer(ms)返回timerId
│ │ ├─ killTimer(timerId)停止
│ │ └─ timerEvent()中区分定时器
│ └─ 4.3 倒计时功能完整实现
├─ 5 窗口事件详解
│ ├─ 5.1 moveEvent()窗口移动
│ │ └─ oldPos()/pos()获取新旧位置
│ └─ 5.2 resizeEvent()大小改变
│ └─ oldSize()/size()获取新旧尺寸
└─ 6 事件分发器
├─ 6.1 所有事件经event()函数分发
├─ 6.2 可重写event()拦截所有事件
└─ 6.3 使用不当会影响原有逻辑
导入语
Qt作为主流的GUI开发框架,其核心交互能力建立在事件机制之上。我们日常使用的按钮点击、文本输入、窗口拖动等所有用户交互,本质上都是操作系统产生事件,再由Qt封装并传递给应用程序处理的过程。虽然绝大多数场景下我们使用更便捷的信号槽机制就能完成开发,但当需要实现高度自定义的交互效果------比如自定义按钮的悬停动画、全局键盘快捷键拦截、鼠标拖拽绘制图形、精准的定时器控制等------信号槽就显得力不从心,此时必须深入到事件机制层面进行开发。
本文将系统梳理Qt事件机制的完整知识体系,从事件与信号槽的本质关系入手,详细讲解各类常见事件的处理方法、代码实现和注意事项,最后介绍事件分发器的工作原理。所有内容均结合实际开发案例,确保学完后既能理解底层逻辑,又能直接应用到项目中。
1 ~> 事件基本概念
1.1 事件与信号槽的本质关系
用户的所有操作(点击鼠标、按下键盘、移动窗口等)都会先产生操作系统级别的事件,Qt将这些原生事件进行了第一层封装,形成了Qt的事件体系。在此基础上,Qt为了简化开发,又对常用事件进行了第二层封装,得到了我们熟悉的信号槽机制。
- 本质关系 :信号槽是事件的进一步封装,事件是信号槽的底层支撑。例如按钮的
clicked()信号,本质上就是mousePressEvent和mouseReleaseEvent两个事件的组合。 - 使用场景 :
- 90%以上的常规交互使用信号槽即可完成,代码更简洁易维护
- 当Qt没有提供对应信号、或需要实现高度自定义的交互逻辑时,必须直接使用事件机制
- 事件机制允许开发者进行更深度的定制化开发,实现信号槽无法完成的功能
1.2 QEvent类体系
Qt中所有事件都继承自QEvent基类,不同类型的事件由对应的子类表示,每个事件对象都会携带本次交互的详细信息。
核心事件子类及对应场景:
| 事件子类 | 触发场景 | 携带的核心信息 |
|---|---|---|
| QMouseEvent | 鼠标点击、移动、释放 | 坐标位置、按下的按键、全局/局部坐标 |
| QKeyEvent | 键盘按键按下、释放 | 按键编码、修饰键(Ctrl/Shift等) |
| QTimerEvent | 定时器时间到达 | 定时器ID |
| QWheelEvent | 鼠标滚轮滚动 | 滚动距离、滚动方向 |
| QPaintEvent | 窗口需要重绘 | 重绘区域 |
| QMoveEvent | 窗口位置移动 | 新旧位置坐标 |
| QResizeEvent | 窗口大小改变 | 新旧尺寸 |
1.3 事件的核心处理机制
Qt中处理事件的核心方法是重写父类的虚事件处理函数,这依赖于C++的多态机制:
- 创建自定义类,继承自Qt提供的标准控件类(如QLabel、QWidget、QPushButton等)
- 在自定义类中重写父类对应的虚事件处理函数(如
enterEvent()、mousePressEvent()等) - 将UI设计器中拖放的标准控件提升为自定义类的实例
- 当事件触发时,Qt会通过多态机制自动调用我们重写的函数
注意:重写事件函数时,必须保证函数名、参数类型和个数与父类完全一致,否则无法触发多态。特别注意函数名的大小写,Qt的事件函数均以小写字母开头。
2 ~> 鼠标事件详解
鼠标事件是GUI开发中最常用的事件类型,涵盖了鼠标的进入、离开、点击、移动、滚轮等所有操作。
2.1 鼠标进入与离开事件
用于检测鼠标光标进入或离开某个控件的区域,常用于实现悬停效果、提示信息等。
2.1.1 函数原型
cpp
// 鼠标进入控件时触发
[virtual protected] void QWidget::enterEvent(QEvent *event);
// 鼠标离开控件时触发
[virtual protected] void QWidget::leaveEvent(QEvent *event);
2.1.2 完整实现步骤
- 创建自定义Label类,继承自QLabel
- 头文件
label.h:
- 头文件
cpp
#ifndef LABEL_H
#define LABEL_H
#include <QLabel>
class Label : public QLabel
{
Q_OBJECT
public:
Label(QWidget *parent = nullptr);
protected:
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
};
#endif // LABEL_H
- 源文件
label.cpp:
cpp
#include "label.h"
#include <QDebug>
Label::Label(QWidget *parent) : QLabel(parent)
{
}
void Label::enterEvent(QEvent *event)
{
(void)event; // 消除未使用参数的警告
qDebug() << "鼠标进入Label区域";
}
void Label::leaveEvent(QEvent *event)
{
(void)event;
qDebug() << "鼠标离开Label区域";
}
- 控件提升操作
- 在UI设计器中拖放一个QLabel控件
- 右键点击该控件,选择"提升为"
- 在弹出的对话框中,基类名称选择"QLabel",提升的类名称填写"Label",头文件填写"label.h"
- 点击"添加",然后点击"提升"
- 此时UI中的QLabel就变成了我们自定义的Label类实例,运行程序即可看到效果
2.2 鼠标点击事件
用于捕获鼠标按键的按下操作,可以获取点击位置和按下的按键类型。
2.2.1 函数原型与参数
cpp
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
参数QMouseEvent* event携带了本次点击的所有信息:
event->x()/event->y():点击位置相对于控件左上角的局部坐标event->globalX()/event->globalY():点击位置相对于屏幕左上角的全局坐标event->button():返回按下的鼠标按键,类型为Qt::MouseButton枚举
2.2.2 鼠标按键类型判断
Qt::MouseButton枚举定义了所有支持的鼠标按键:
cpp
Qt::LeftButton // 左键 0x00000001
Qt::RightButton // 右键 0x00000002
Qt::MiddleButton // 中键(滚轮)0x00000004
Qt::BackButton // 侧键后退 0x00000008
Qt::ForwardButton // 侧键前进 0x00000010
2.2.3 实现代码
在自定义Label类中添加:
cpp
// label.h
protected:
void mousePressEvent(QMouseEvent *event) override;
// label.cpp
#include <QMouseEvent>
void Label::mousePressEvent(QMouseEvent *event)
{
// 判断按下的按键
if (event->button() == Qt::LeftButton) {
qDebug() << "按下鼠标左键";
} else if (event->button() == Qt::RightButton) {
qDebug() << "按下鼠标右键";
} else if (event->button() == Qt::MiddleButton) {
qDebug() << "按下鼠标中键";
}
// 输出坐标信息
qDebug() << "局部坐标:" << event->x() << "," << event->y();
qDebug() << "全局坐标:" << event->globalX() << "," << event->globalY();
}
2.3 鼠标释放与双击事件
2.3.1 鼠标释放事件
cpp
// 函数原型
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
// 实现代码
void Label::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
qDebug() << "释放鼠标左键";
} else if (event->button() == Qt::RightButton) {
qDebug() << "释放鼠标右键";
}
}
2.3.2 鼠标双击事件
cpp
// 函数原型
[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event);
// 实现代码
void Label::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
qDebug() << "双击鼠标左键";
}
}
2.3.3 重要注意事项
双击操作会先触发两次单击事件(按下+释放),然后才触发双击事件。如果同时实现了单击和双击逻辑,需要注意避免冲突,例如可以通过定时器延迟判断是单击还是双击。
2.4 鼠标移动事件
用于实时获取鼠标的移动位置,常用于实现拖拽、绘制等功能。
2.4.1 默认行为与鼠标追踪
Qt默认情况下不会追踪鼠标移动,只有当鼠标按键按下时才会触发mouseMoveEvent。如果需要在鼠标未按下时也能追踪移动,必须显式开启鼠标追踪:
cpp
// 在控件的构造函数中添加
this->setMouseTracking(true);
2.4.2 实现代码
cpp
// widget.h
protected:
void mouseMoveEvent(QMouseEvent *event) override;
// widget.cpp
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
this->setMouseTracking(true); // 开启鼠标追踪
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << "鼠标移动到:" << event->x() << "," << event->y();
}
注意:鼠标移动事件触发频率非常高,如果在处理函数中执行复杂逻辑,可能会导致程序卡顿,应尽量优化处理逻辑。
2.5 鼠标滚轮事件
用于捕获鼠标滚轮的滚动操作,常用于实现缩放、滚动列表等功能。
2.5.1 函数原型与delta()方法
cpp
[virtual protected] void QWidget::wheelEvent(QWheelEvent *event);
event->delta()返回滚轮滚动的距离,单位为1/8度:
- 向上滚动:返回正值(通常为120)
- 向下滚动:返回负值(通常为-120)
2.5.2 累计滚动距离实现
cpp
// widget.h
private:
int totalDelta = 0;
protected:
void wheelEvent(QWheelEvent *event) override;
// widget.cpp
#include <QWheelEvent>
void Widget::wheelEvent(QWheelEvent *event)
{
totalDelta += event->delta();
qDebug() << "本次滚动距离:" << event->delta();
qDebug() << "累计滚动距离:" << totalDelta;
}
3 ~> 键盘事件详解
键盘事件用于捕获用户的键盘输入,支持单个按键和组合键的处理。
3.1 键盘事件的触发条件
键盘事件只有在控件或窗口处于激活状态时才会触发。如果焦点在其他控件或程序上,键盘事件会被其他程序捕获。
3.2 单个按键的捕获与判断
cpp
// 函数原型
[virtual protected] void QWidget::keyPressEvent(QKeyEvent *event);
[virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event);
event->key()返回按下的按键编码,对应Qt::Key_*枚举:
cpp
// 实现代码
#include <QKeyEvent>
void Widget::keyPressEvent(QKeyEvent *event)
{
qDebug() << "按下按键编码:" << event->key();
// 判断具体按键
if (event->key() == Qt::Key_A) {
qDebug() << "按下了A键";
} else if (event->key() == Qt::Key_Escape) {
qDebug() << "按下了ESC键";
this->close(); // 按下ESC关闭窗口
}
}
3.3 组合键(快捷键)的处理
使用event->modifiers()获取修饰键状态,对应Qt::KeyboardModifier枚举:
Qt::ControlModifier:Ctrl键Qt::ShiftModifier:Shift键Qt::AltModifier:Alt键
cpp
// 处理Ctrl + A组合键
void Widget::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_A && event->modifiers() == Qt::ControlModifier) {
qDebug() << "按下了Ctrl+A组合键";
// 实现全选逻辑
}
}
3.4 与QShortCut的对比
- 对于简单的快捷键功能,推荐使用
QShortCut类(信号槽机制),代码更简洁 - 当需要处理复杂的键盘逻辑(如连续按键、按键长按等)时,使用键盘事件更灵活
4 ~> 定时器事件详解
定时器用于周期性执行任务,常用于实现动画、倒计时、定时刷新等功能。Qt提供了两种定时器实现方式:高层接口QTimer和底层事件QTimerEvent。
4.1 QTimerEvent的使用
QTimerEvent是Qt定时器的底层实现,所有定时器最终都会触发该事件。
4.2.1 核心函数
int startTimer(int interval):开启定时器,参数为间隔时间(毫秒),返回唯一的定时器IDvoid killTimer(int id):根据定时器ID停止定时器void timerEvent(QTimerEvent *event):定时器事件处理函数,所有定时器触发时都会调用该函数
4.2.2 定时器ID的作用
- 每个
startTimer调用都会返回一个唯一的ID,用于区分不同的定时器 - 定时器ID类似于Linux中的文件描述符,是定时器的身份标识
- 当程序中有多个定时器时,必须在
timerEvent中通过ID判断是哪个定时器触发
4.2.3 倒计时功能完整实现
cpp
// widget.h
private:
Ui::Widget *ui;
int timerId; // 保存定时器ID
protected:
void timerEvent(QTimerEvent *event) override;
// widget.cpp
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置LCD初始值为10
ui->lcdNumber->display(10);
// 开启1秒间隔的定时器
timerId = this->startTimer(1000);
}
Widget::~Widget()
{
delete ui;
}
void Widget::timerEvent(QTimerEvent *event)
{
// 区分定时器
if (event->timerId() != this->timerId) {
return; // 不是我们的定时器,直接忽略
}
// 获取当前LCD显示的数值
int value = ui->lcdNumber->intValue();
if (value <= 0) {
// 倒计时结束,停止定时器
this->killTimer(this->timerId);
qDebug() << "倒计时结束";
return;
}
// 数值减1并更新显示
value--;
ui->lcdNumber->display(value);
}
4.3 QTimer与QTimerEvent的对比
- QTimer:高层接口,使用信号槽机制,每个定时器对应一个对象,代码更清晰易维护,是实际开发中的首选
- QTimerEvent:底层事件,需要手动管理定时器ID,多个定时器共用一个处理函数,代码相对复杂,但更灵活
5 ~> 窗口事件详解
窗口事件用于捕获窗口的位置和大小变化,常用于实现自适应布局、窗口状态监控等功能。
5.1 窗口移动事件moveEvent
当窗口被拖动改变位置时触发:
cpp
// 函数原型
[virtual protected] void QWidget::moveEvent(QMoveEvent *event);
// 实现代码
#include <QMoveEvent>
void Widget::moveEvent(QMoveEvent *event)
{
qDebug() << "窗口旧位置:" << event->oldPos();
qDebug() << "窗口新位置:" << event->pos();
}
5.2 窗口大小改变事件resizeEvent
当窗口被拖动改变大小时触发:
cpp
// 函数原型
[virtual protected] void QWidget::resizeEvent(QResizeEvent *event);
// 实现代码
#include <QResizeEvent>
void Widget::resizeEvent(QResizeEvent *event)
{
qDebug() << "窗口旧尺寸:" << event->oldSize();
qDebug() << "窗口新尺寸:" << event->size();
qDebug() << "新宽度:" << event->size().width();
qDebug() << "新高度:" << event->size().height();
}
6 ~> 事件分发器简介
6.1 事件分发器的工作原理
Qt中所有事件都会先传递到QObject::event()函数,该函数是事件分发的总入口。它不会直接处理事件,而是根据事件的类型(event->type())调用对应的具体事件处理函数(如mousePressEvent()、keyPressEvent()等)。
6.2 event()函数的作用
我们可以重写event()函数,在事件分发之前拦截所有事件,实现全局的事件处理或过滤:
cpp
bool Widget::event(QEvent *event)
{
// 拦截所有鼠标按下事件
if (event->type() == QEvent::MouseButtonPress) {
qDebug() << "拦截到鼠标按下事件";
// 返回true表示事件已处理,不再向下分发
return true;
}
// 其他事件交给父类处理
return QWidget::event(event);
}
6.3 使用注意事项
- 重写
event()函数会影响所有事件的分发,使用不当会破坏Qt原有的事件体系 - 除非有特殊需求,否则不建议重写该函数
- 如果确实需要拦截事件,一定要记得将不需要处理的事件交给父类的
event()函数处理
全文总结
本文系统梳理了Qt事件机制的完整知识体系,核心重点总结如下:
- 本质关系:信号槽是事件的上层封装,事件是信号槽的底层支撑。常规场景用信号槽,自定义场景用事件。
- 核心处理方式:通过继承标准控件类,重写对应的虚事件处理函数,再将UI控件提升为自定义类实例。
- 鼠标事件 :
- 进入离开:
enterEvent()/leaveEvent() - 点击释放:
mousePressEvent()/mouseReleaseEvent(),可获取局部/全局坐标和按键类型 - 移动事件:默认不追踪,需调用
setMouseTracking(true)开启 - 滚轮事件:
wheelEvent(),通过delta()获取滚动距离
- 进入离开:
- 键盘事件 :
keyPressEvent()/keyReleaseEvent(),通过key()判断单个按键,modifiers()判断组合键。 - 定时器事件 :
- 高层接口
QTimer(推荐),底层事件QTimerEvent QTimerEvent需手动管理定时器ID,在timerEvent()中区分不同定时器
- 高层接口
- 窗口事件 :
moveEvent()捕获位置变化,resizeEvent()捕获大小变化。 - 事件分发器 :所有事件经
event()函数分发,可重写该函数拦截事件,但需谨慎使用。
实际开发中,应遵循"优先使用信号槽,必要时使用事件"的原则,在保证代码简洁性的同时,实现所需的功能效果。掌握事件机制是深入Qt开发的必经之路,它能让你真正理解GUI程序的交互本质,实现更灵活、更强大的自定义控件和交互效果。
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!"
"技术之路难免有困惑,但同行的人会让前进更有方向。" |
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!
往期回顾:
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა
