计算机
c base
c++ 基础 作用域及生命周期
c++ template
c++ 内存视角
c++ 函数
c++ 基础 基础语法
c++ 性能
c++ 类 基础
c++ 类 对象模型 类析构
c++ 类 设计模式
C++ STL
cmake
CMAKE环境搭建 windows
创建第一个cmakelists.txt
构建稍复杂的项目
动态链接库
EX1
EX1 START
EX1 ANSWER
EX2
EX2 START
EX2 ANSWER
EX3
EX3 START
EX3 ANSWER
变量
控制流程
函数和宏
查找和使用外部库
生成器表达式
qt
qt c++
qt index
qt qml quick
qt ui
qt 多线程
理解QObject 1
理解QObject 4
C++ 技巧 反射
理解QObject 2
理解QObject 3
理解QObject 6
理解 QObject 5
QCoreApplication
QApplication
数据结构
PC问题监控及排查
PC程序性能优化
OS
TOOL
编程漫谈
sealos+frp,搭建内网穿透
host主机配置
C++实战 主题
多线程
生产者-消费者流水线
IO
网络
Bilinotes搭建
编译原理
WEB开发
TS
HTML CSS JAVASCRIPT
本站点使用 MrDoc 构建
-
+
理解QObject 6
### 目录 - [1. 对象名管理](#1-对象名管理-content-0027) - [2. 父子关系管理](#2-父子关系管理-content-0103) - [3. 事件处理机制](#3-事件处理机制-content-0204) - [3.1 event() 方法](#31-event-方法-content-0204) - [3.2 事件过滤器 eventFilter()](#32-事件过滤器-eventfilter-content-0331) - [3.3 安装事件过滤器 installEventFilter()](#33-安装事件过滤器-installeventfilter-content-0454) - [4. 线程与定时器](#4-线程与定时器-content-0617) - [4.1 线程移动 moveToThread()](#41-线程移动-movetothread-content-0617) - [4.2 定时器机制](#42-定时器机制-content-0705) - [5. 查找子对象](#5-查找子对象-content-0850) - [6. 信号与槽的连接](#6-信号与槽的连接-content-1052) - [7. 动态属性与用户数据](#7-动态属性与用户数据-content-1323) - [8. 信号槽连接通知回调](#8-信号槽连接通知回调-content-1737) - [9. QObject 核心作用总结](#9-qobject-核心作用总结-content-1930) --- ### 1. 对象名管理 [原片 @ 00:27](https://www.bilibili.com/video/BV1MN411z71P?t=27)* - **属性获取与修改**: - `objectName()`: 读取当前对象的名称。 - `setObjectName(const QString &name)`: 修改对象的名称。 - **信号通知**: - 当对象名称被修改后,`QObject` 会自动发出 `objectNameChanged` 信号。 - 开发者可以通过连接这个信号来监听对象名称的变化。 ### 2. 父子关系管理 [原片 @ 01:03](https://www.bilibili.com/video/BV1MN411z71P?t=63)* - **建立关系**: - **构造函数**:在创建 `QObject` 子类实例时,可以通过构造函数传入父对象指针 (`parent`)。这使得对象之间形成树状结构(对象树)。 - **setParent()**: 后续可以通过 `setParent(QObject *parent)` 方法动态设置或修改父对象。 - **解除关系**: - 如果向 `setParent()` 传递空指针 (`nullptr`),则解除当前的父子关系。 - **意义**: - 建立了所有权关系,父对象可以管理子对象的生命周期(例如父对象删除时自动删除子对象,虽然视频中未详述析构部分,但这是对象树的核心概念)。 ### 3. 事件处理机制 [原片 @ 02:04](https://www.bilibili.com/video/BV1MN411z71P?t=124)* #### 3.1 event() 方法 [原片 @ 02:04](https://www.bilibili.com/video/BV1MN411z71P?t=124)* - **作用**:`QObject` 能接收各种各样的事件。 - **实现原理**: - `QEvent` 是一个抽象基类,不同的具体事件由不同的子类表示(如 `QMouseEvent`, `QKeyEvent` 等)。 - `event()` 方法是事件分发的核心。它接收一个 `QEvent *` 参数。 - 内部根据事件的类型 (`type`) 调用对应的具体处理方法(如 `mousePressEvent`, `keyPressEvent` 等)。 - 常见的虚函数包括 `event()`, `childEvent()`, `customEvent()` 等。 #### 3.2 事件过滤器 eventFilter() [原片 @ 03:31](https://www.bilibili.com/video/BV1MN411z71P?t=211)* - **作用**:允许一个对象拦截并过滤发往另一个对象的事件。 - **机制**: - 如果对象 A 安装了对象 B 作为其事件过滤器,那么发往 B 的所有事件都会先经过 A 的 `eventFilter(QObject *obj, QEvent *event)` 方法。 - 返回值 `bool`: - `true`: 阻止事件继续传播给目标对象(即目标对象收不到该事件)。 - `false`: 允许事件继续传递给目标对象处理。 - **应用场景**:例如 C 对象想过滤掉发给 B 对象的事件,可以将 C 安装到 B 上(注意:通常是接受者安装过滤器,或者更准确地说是“观察者”模式的一种变体,视频中描述为“C对象要过滤A对象发给B对象的事件...把C对象安装到B对象上...C的eventFilter会先执行”)。*修正理解:通常是接收方安装过滤器,或者发送方安装过滤器?视频中例子是:C想过滤发给B的事件,所以把C作为过滤器安装到B上。这意味着B的事件流会先经过C。* #### 3.3 安装事件过滤器 installEventFilter() [原片 @ 04:54](https://www.bilibili.com/video/BV1MN411z71P?t=294)* - **用法**:`installEventFilter(QObject *filterObj)`。 - **逻辑**: - 假设 B 对象调用了 `b->installEventFilter(c)`。 - 此时,发往 B 的事件会先到达 C 的 `eventFilter`。 - 如果 C 返回 `false`,事件才会到达 B 的 `event` 处理流程。 - 如果 C 返回 `true`,事件在 C 处被截断,B 无法处理该事件。 - **移除**:`removeEventFilter(QObject *filterObj)`。 ### 4. 线程与定时器 [原片 @ 06:17](https://www.bilibili.com/video/BV1MN411z71P?t=377)* #### 4.1 线程移动 moveToThread() [原片 @ 06:17](https://www.bilibili.com/video/BV1MN411z71P?t=377)* - **作用**:将对象移动到指定的线程 (`QThread *targetThread`)。 - **影响**: - 默认情况下,对象在其创建的线程中运行(通常是主线程)。 - 移动后,该对象的事件循环 (`event loop`) 将在新线程中执行。这意味着该对象的 `event()` 处理函数将在新线程中被调用。 - **限制**: - 如果对象有父对象,通常不能直接移动该对象(除非移动整棵树)。视频中提到:“在对象树中,只有根节点可以 movetothread,将整棵树从一个线程移动到另外一个线程”。 - 如果试图移动有父对象的子对象,可能会失败或产生未定义行为(具体取决于 Qt 版本和实现,通常建议移动根节点)。 #### 4.2 定时器机制 [原片 @ 07:05](https://www.bilibili.com/video/BV1MN411z71P?t=425)* - **启动定时器**: - `int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer)`。 - 返回一个唯一的定时器 ID。 - 可以开启多个定时器,只要间隔不同。 - **处理定时器事件**: - `virtual void timerEvent(QTimerEvent *event)`。 - 当定时器超时触发时,调用此函数。 - 通过 `event->timerId()` 可以区分是哪个定时器触发的。 - **停止定时器**: - `void killTimer(int id)`。停止指定 ID 的定时器。 - **高精度定时器**: - 可以使用 `std::chrono` 相关的重载版本 `startTimer(std::chrono::milliseconds time)`。 ### 5. 查找子对象 [原片 @ 08:50](https://www.bilibili.com/video/BV1MN411z71P?t=530)* - **findChild()**: - 根据对象名称查找**第一个**匹配的子对象(递归查找)。 - 模板函数:`T findChild(const QString &name = QString(), Qt::FindChildOptions options = ...) const`。 - 默认 `options` 是递归查找 (`FindChildrenRecursively`)。 - **findChildren()**: - 查找**所有**匹配的子对象,返回 `QList<T>`。 - 支持按名称查找,也支持按类型查找。 - 支持正则表达式查找:`findChildren(const QRegularExpression &re, Qt::FindChildOptions options = ...) const`。 ### 6. 信号与槽的连接 [原片 @ 10:52](https://www.bilibili.com/video/BV1MN411z71P?t=652)* - **connect() 重载版本**: - **字符串版本**:`connect(sender, SIGNAL(signal()), receiver, SLOT(slot()))` (旧式语法,不推荐但存在)。 - **函数指针版本**:`connect(sender, &SenderClass::signal, receiver, &ReceiverClass::slot)` (编译期检查,推荐)。 - **Lambda 版本**:`connect(sender, &SenderClass::signal, [=]() { ... })`。 - **静态 connect**:`QObject::connect(...)`。 - **disconnect()**: - 用于断开信号和槽的连接。 - 也有多种重载形式,对应 connect 的参数。 - **连接类型**: - `Qt::AutoConnection` (默认): 根据发送者和接收者是否在同一个线程自动选择 DirectConnection 或 QueuedConnection。 - `Qt::DirectConnection`: 立即调用槽函数(在发送者线程)。 - `Qt::QueuedConnection`: 将事件放入接收者线程的事件队列(在接收者线程)。 - `Qt::BlockingQueuedConnection`: 类似 Queued,但发送者线程会阻塞直到槽函数执行完毕(跨线程时使用需谨慎)。 ### 7. 动态属性与用户数据 [原片 @ 13:23](https://www.bilibili.com/video/BV1MN411z71P?t=803)* - **动态属性 (Dynamic Properties)**: - `bool setProperty(const char *name, const QVariant &value)`: 动态设置属性。 - `QVariant property(const char *name) const`: 动态获取属性。 - `QList<QByteArray> dynamicPropertyNames() const`: 获取所有动态属性的名称列表。 - 这些属性存储在元对象系统中,可以被 QML 访问或在 Qt Designer 中绑定。 - **用户数据 (User Data)**: - `static uint registerUserData()`: 注册一个新的用户数据类型 ID。 - `void setUserData(uint id, QObjectUserData *data)`: 设置关联的用户数据。 - `QObjectUserData *userData(uint id) const`: 获取关联的用户数据。 - `QObjectUserData` 是一个抽象基类,用户可以继承它来存储任何自定义的上下文信息(Context)。这相当于一个通用的 `void*` 映射表。 ### 8. 信号槽连接通知回调 [原片 @ 17:37](https://www.bilibili.com/video/BV1MN411z71P?t=1057)* - **connectNotify()**: - 虚函数:`virtual void connectNotify(const MetaMethod &signal) override`。 - 当某个信号被连接到一个槽时,此函数会被调用(站在发送者角度)。 - 可以用于统计有多少个连接,或者执行自定义的初始化逻辑。 - **disconnectNotify()**: - 虚函数:`virtual void disconnectNotify(const MetaMethod &signal) override`。 - 当信号的所有连接都被断开时,此函数会被调用。 ### 9. QObject 核心作用总结 [原片 @ 19:30](https://www.bilibili.com/video/BV1MN411z71P?t=1170)* `QObject` 是 Qt 核心类的基类,主要提供了以下五大类功能: 1. **对象树 (Object Tree)**:父子关系管理,自动内存管理。 2. **事件框架 (Event Framework)**:`event()`, `eventFilter()` 等事件处理机制。 3. **信号与槽 (Signals and Slots)**:解耦的对象间通信机制。 4. **线程支持 (Threading)**:`moveToThread()`, 线程亲和性。 5. **属性系统 (Property System)**:动态属性,支持反射和元对象系统。 6. **定时器 (Timers)**:内置的事件驱动定时器。 --- ### AI 总结 本视频详细介绍了 `QObject` 类的核心功能。首先讲解了对象名的读写及相应的信号通知。接着深入探讨了父子关系的建立(构造函数与 `setParent`)及其在对象树中的作用。重点分析了事件处理机制,包括 `event()` 方法的分发逻辑以及 `eventFilter()` 如何拦截和处理其他对象的事件。随后介绍了多线程环境下的对象移动 `moveToThread()` 及其限制(通常只能移动无父对象的根节点或整棵树),以及定时器 `startTimer` / `timerEvent` 的使用。此外,还涵盖了子对象的查找(`findChild`)、信号槽连接的多种重载方式(字符串、函数指针、Lambda)、动态属性系统的操作以及用户数据的存取。最后总结了 `QObject` 作为 Qt 核心基类,提供对象树、事件、信号槽、线程支持和属性系统等关键基础设施的作用。
peipeo
2026年5月27日 17:49
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码