【奶茶Beta专项】【LVGL9.4源码分析】09-core-obj_event
- 📖 简介
- 1. 设计意图与框架定位
- 1.1 核心设计意图
- 1.2 在框架中的定位
- 2. 核心架构分析
- 2.1 事件数据结构
- 2.1.1 事件描述符
- 2.1.2 事件对象
- 2.1.3.2 current_target 字段(当前处理对象)
- 2.1.3.3 字段差异对比
- 2.1.3.4 事件冒泡过程中的变化
- 2.1.3.5 实际应用场景
- 2.2 事件处理流程
- 2.2.1 事件发送流程
- 2.2.2 事件处理优先级
- 3. APIs速查表
- 3.1 事件注册与管理
- 3.2 事件发送与控制
- 3.3 事件信息获取
- 3.4 专用事件信息获取
- 3.5 事件代码分类
- 3.5.1 输入设备事件
- 3.5.2 焦点事件
- 3.5.3 绘制事件
- 3.5.4 状态变化事件
- 3.5.5 生命周期事件
- 3.5.6 特殊事件
- 4. 设计优势与缺点分析
- 4.1 设计优势
- 4.1.1 灵活的事件过滤机制
- 4.1.2 完善的事件冒泡机制
- 4.1.3 内存高效的事件存储
- 4.2 设计缺点
- 4.2.1 事件处理顺序不直观
- 4.2.2 内存管理复杂
- 4.2.3 缺乏事件优先级控制
- 5. 改进空间分析
- 5.1 性能优化方向
- 5.1.1 事件回调查找优化
- 5.1.2 减少内存分配
- 5.1.3 事件合并处理
- 5.2 代码结构优化
- 5.2.1 事件系统解耦
- 5.2.2 类型安全增强
- 6. 横向对比分析
- 6.1 与AWTK事件系统的对比
- 6.1.1 AWTK事件系统特点
- 6.1.2 LVGL相对优势
- 6.2 与Qt事件系统的对比
- 6.2.1 Qt事件系统特点
- 6.2.2 LVGL相对优势
- 6.3 与Android事件系统的对比
- 6.3.1 Android事件特点
- 6.3.2 LVGL相对优势
- 6.4 与HTML/CSS事件系统的对比
- 6.4.1 HTML事件特点
- 6.4.2 LVGL相对优势
- 7. 纵向对比分析
- 7.1 LVGL 8.4 vs 9.4 事件系统对比
- 7.1.1 架构演进
- 7.1.2 API变化对比
- 7.1.3 性能对比
- 7.1.4 内存使用对比
- 8. 专项分析:事件生命周期
- 8.1 按钮组件事件生命周期
- 8.2 滚动容器事件生命周期
- 8.3 屏幕切换生命周期
- 8.4 对象生命周期事件序列
- 8.4.1 对象创建序列
- 8.4.2 对象销毁序列
- 8.4.3 布局变化序列
- 附录
- A. 参考文档
- B. 相关资源
文档版本: 1.0
更新日期: 2025年12月
适用对象: GUI框架开发工程师、LVGL源码研究者
📖 简介
本文档深入分析LVGL 9.4版本对象事件系统(lv_obj_event)的设计原理、实现机制和应用场景。作为LVGL框架的核心组件之一,事件系统负责处理用户交互、状态变化和组件生命周期管理,为整个GUI框架提供了灵活的事件驱动架构。
1. 设计意图与框架定位
1.1 核心设计意图
LVGL对象事件系统作为框架的核心交互机制,其设计意图主要体现在以下三个方面:
事件驱动架构:采用观察者模式实现组件间的松耦合通信,通过事件机制将用户输入、状态变化和组件生命周期有机统一。
层次化事件处理:支持多层级事件处理,从对象自身到父类继承再到事件冒泡,形成完整的事件处理链路。
类型安全的事件系统:通过强类型事件代码和参数传递机制,确保事件处理的类型安全性和扩展性。
1.2 在框架中的定位
事件系统在LVGL整体架构中扮演着"神经中枢"的角色:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 输入设备 │───▶│ 事件系统 │───▶│ 显示输出 │ └─────────────┘ └─────┬───────┘ └─────────────┘ │ ▼ ┌─────────────────────┐ │ UI更新 │ └─────────┬───────────┘ │ ┌──────────────┼──────────────┐ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 对象处理 │ │ 状态管理 │ │ 生命周期 │ └─────────────┘ └─────────────┘ └─────────────┘2. 核心架构分析
2.1 事件数据结构
2.1.1 事件描述符
typedefstruct_lv_event_dsc_t{lv_event_cb_tcb;// 回调函数指针void*user_data;// 用户数据lv_event_code_tfilter:8;// 事件过滤器}lv_event_dsc_t;2.1.2 事件对象
typedefstruct_lv_event_t{lv_obj_t*target;// 原始目标对象lv_obj_t*current_target;// 当前处理对象lv_event_code_tcode;// 事件代码void*user_data;// 回调用户数据void*param;// 事件参数lv_event_t*prev;// 链表前驱uint8_tdeleted:1;// 删除标记uint8_tstop_processing:1;// 停止处理标记uint8_tstop_bubbling:1;// 停止冒泡标记}lv_event_t;####2.1.3关键字段详解:target vs current_target LVGL事件系统中 `target` 和 `current_target` 两个字段是理解事件冒泡机制的关键,它们在事件传递过程中扮演着不同的角色。 #####2.1.3.1target 字段(原始目标对象)**定义**:指向最初接收事件的原始对象,无论事件是否冒泡,`target` 始终保持不变。**作用**:-标识事件最初的触发目标-在整个事件处理链中保持不变-用于确定事件发生的原始位置**获取方式**: ```clv_obj_t*original_target=lv_event_get_target(e);2.1.3.2 current_target 字段(当前处理对象)
定义:指向当前正在处理事件的活动对象,会随着事件冒泡而改变。
作用:
- 标识当前事件回调所属的对象
- 在事件冒泡过程中动态更新
- 决定当前回调函数的执行上下文
获取方式:
lv_obj_t*current_handler=lv_event_get_current_target(e);2.1.3.3 字段差异对比
| 特性 | target | current_target |
|---|---|---|
| 不变性 | 始终不变 | 随冒泡改变 |
| 含义 | 事件源头 | 当前处理者 |
| 作用域 | 全局事件上下文 | 当前回调上下文 |
| 使用场景 | 事件源追踪、原始位置判断 | 对象关系判断、局部处理 |
2.1.3.4 事件冒泡过程中的变化
// 假设有这样的对象层级:// 屏幕(screen) -> 容器(container) -> 按钮(button)// 当点击按钮时的事件传递过程:voidbutton_event_handler(lv_event_t*e){lv_obj_t*original=lv_event_get_target(e);// 始终是 buttonlv_obj_t*current=lv_event_get_current_target(e);// 当前是 button// 如果按钮没有停止冒泡,事件会传递到容器}voidcontainer_event_handler(lv_event_t*e){lv_obj_t*original=lv_event_get_target(e);// 仍然是 button(原始目标)lv_obj_t*current=lv_event_get_current_target(e);// 现在是 container(当前处理者)// 容器可以根据原始目标和当前目标的关系做出不同处理}2.1.3.5 实际应用场景
场景1:事件源追踪
staticvoidevent_handler(lv_event_t*e){lv_obj_t*event_source=lv_event_get_target(e);lv_obj_t*current_obj=lv_event_get_current_target(e);if(event_source==current_obj){// 这是原始目标对象的回调printf("事件发生在对象自身\n");}else{// 这是父对象的冒泡回调printf("事件从子对象冒泡上来\n");}}场景2:条件处理逻辑
staticvoidcontainer_event_handler(lv_event_t*e){lv_obj_t*original_target=lv_event_get_target(e);lv_obj_t*current_target=lv_event_get_current_target(e);// 如果事件来自特定的子对象,执行特殊处理if(lv_obj_is_child_of(original_target,current_target)){if(lv_event_get_code(e)==LV_EVENT_CLICKED){// 处理来自子对象的点击事件handle_child_click(original_target);}}}场景3:事件委托模式
staticvoidlist_item_handler(lv_event_t*e){lv_obj_t*clicked_item=lv_event_get_target(e);// 被点击的列表项lv_obj_t*list_container=lv_event_get_current_target(e);// 列表容器// 容器统一处理所有列表项的事件intitem_index=get_item_index(list_container,clicked_item);handle_list_selection(list_container,item_index);}场景4:防止重复处理
staticvoidglobal_event_handler(lv_event_t*e){staticlv_obj_t*last_processed_target=NULL;lv_obj_t*current=lv_event_get_current_target(e);if(current==last_processed_target){// 同一个对象的重复处理,跳过return;}last_processed_target=current;// 执行处理逻辑}通过正确使用target和current_target,开发者可以实现复杂的事件处理逻辑,包括事件委托、条件响应和冒泡控制等高级功能。
2.2 事件处理流程
2.2.1 事件发送流程
应用程序 ────── lv_event_send() ──────▶ 事件系统 │ │ │ ▼ │ ┌─────────────────┐ │ │ 预处理回调 │ │ └─────────────────┘ │ │ │ ▼ │ ┌─────────────────┐ │ │ 基类事件处理 │ │ └─────────────────┘ │ │ │ ▼ │ ┌─────────────────┐ │ │ 普通事件回调 │ │ └─────────────────┘ │ │ │ 冒泡启用时继续 ▼ │ ┌─────────────────┐ └─────────────────────────────▶│ 父对象处理 │ └─────────────────┘2.2.2 事件处理优先级
- 预处理回调(LV_EVENT_PREPROCESS标志)
- 基类事件处理(通过类继承链)
- 普通事件回调
- 事件冒泡(可选)
3. APIs速查表
3.1 事件注册与管理
| API函数 | 功能描述 | 参数说明 | 返回值 |
|---|---|---|---|
lv_obj_add_event_cb | 添加事件回调 | obj, callback, filter, user_data | lv_event_dsc_t* |
lv_obj_remove_event_cb | 移除事件回调 | obj, callback | bool |
lv_obj_remove_event_cb_with_user_data | 按用户数据移除回调 | obj, callback, user_data | bool |
lv_obj_remove_event_dsc | 移除事件描述符 | obj, event_dsc | bool |
lv_obj_get_event_user_data | 获取回调用户数据 | obj, callback | void* |
3.2 事件发送与控制
| API函数 | 功能描述 | 参数说明 | 返回值 |
|---|---|---|---|
lv_event_send | 发送事件 | obj, event_code, param | lv_res_t |
lv_event_stop_bubbling | 停止事件冒泡 | event | void |
lv_event_stop_processing | 停止事件处理 | event | void |
lv_obj_event_base | 调用基类事件处理 | class_p, event | lv_res_t |
3.3 事件信息获取
| API函数 | 功能描述 | 参数说明 | 返回值 |
|---|---|---|---|
lv_event_get_target | 获取事件目标 | event | lv_obj_t* |
lv_event_get_current_target | 获取当前目标 | event | lv_obj_t* |
lv_event_get_code | 获取事件代码 | event | lv_event_code_t |
lv_event_get_param | 获取事件参数 | event | void* |
lv_event_get_user_data | 获取用户数据 | event | void* |
3.4 专用事件信息获取
| API函数 | 功能描述 | 参数说明 | 返回值 |
|---|---|---|---|
lv_event_get_indev | 获取输入设备 | event | lv_indev_t* |
lv_event_get_draw_ctx | 获取绘制上下文 | event | lv_draw_ctx_t* |
lv_event_get_key | 获取按键值 | event | uint32_t |
lv_event_get_scroll_anim | 获取滚动动画 | event | lv_anim_t* |
lv_event_get_cover_area | 获取覆盖区域 | event | lv_area_t* |
3.5 事件代码分类
3.5.1 输入设备事件
| 事件代码 | 描述 | 触发时机 |
|---|---|---|
LV_EVENT_PRESSED | 对象被按下 | 触摸/点击开始 |
LV_EVENT_PRESSING | 对象正在被按下 | 按下过程中持续 |
LV_EVENT_PRESS_LOST | 按下丢失 | 手指/光标滑出 |
LV_EVENT_SHORT_CLICKED | 短点击 | 快速按下释放 |
LV_EVENT_LONG_PRESSED | 长按 | 按下超过阈值 |
LV_EVENT_CLICKED | 点击完成 | 任何按下释放 |
LV_EVENT_RELEASED | 释放 | 按下结束 |
LV_EVENT_SCROLL_BEGIN | 开始滚动 | 滚动开始 |
LV_EVENT_SCROLL | 滚动中 | 滚动过程 |
LV_EVENT_SCROLL_END | 结束滚动 | 滚动结束 |
LV_EVENT_GESTURE | 手势 | 识别到手势 |
LV_EVENT_KEY | 按键 | 键盘输入 |
3.5.2 焦点事件
| 事件代码 | 描述 | 触发时机 |
|---|---|---|
LV_EVENT_FOCUSED | 获得焦点 | 对象被聚焦 |
LV_EVENT_DEFOCUSED | 失去焦点 | 对象失去焦点 |
LV_EVENT_LEAVE | 离开 | 焦点离开但仍选中 |
3.5.3 绘制事件
| 事件代码 | 描述 | 触发时机 |
|---|---|---|
LV_EVENT_COVER_CHECK | 覆盖检查 | 检查对象是否覆盖区域 |
LV_EVENT_REFR_EXT_DRAW_SIZE | 扩展绘制尺寸 | 获取额外绘制区域 |
LV_EVENT_DRAW_MAIN_BEGIN | 开始主绘制 | 绘制开始 |
LV_EVENT_DRAW_MAIN | 主绘制 | 执行主绘制 |
LV_EVENT_DRAW_MAIN_END | 结束主绘制 | 绘制完成 |
LV_EVENT_DRAW_POST_BEGIN | 开始后绘制 | 子对象绘制后 |
LV_EVENT_DRAW_POST | 后绘制 | 执行后绘制 |
LV_EVENT_DRAW_POST_END | 结束后绘制 | 后绘制完成 |
LV_EVENT_DRAW_PART_BEGIN | 开始部分绘制 | 绘制部分开始 |
LV_EVENT_DRAW_PART_END | 结束部分绘制 | 绘制部分完成 |
3.5.4 状态变化事件
| 事件代码 | 描述 | 触发时机 |
|---|---|---|
LV_EVENT_VALUE_CHANGED | 值改变 | 对象值发生变化 |
LV_EVENT_READY | 就绪 | 异步操作完成 |
LV_EVENT_CANCEL | 取消 | 操作被取消 |
3.5.5 生命周期事件
| 事件代码 | 描述 | 触发时机 |
|---|---|---|
LV_EVENT_DELETE | 删除 | 对象被删除 |
LV_EVENT_CHILD_CREATED | 子对象创建 | 子对象被创建 |
LV_EVENT_CHILD_DELETED | 子对象删除 | 子对象被删除 |
LV_EVENT_CHILD_CHANGED | 子对象变化 | 子对象属性变化 |
LV_EVENT_SIZE_CHANGED | 尺寸变化 | 对象尺寸改变 |
LV_EVENT_STYLE_CHANGED | 样式变化 | 对象样式改变 |
LV_EVENT_LAYOUT_CHANGED | 布局变化 | 子对象布局改变 |
LV_EVENT_GET_SELF_SIZE | 获取自身尺寸 | 计算对象尺寸 |
3.5.6 特殊事件
| 事件代码 | 描述 | 触发时机 |
|---|---|---|
LV_EVENT_INSERT | 插入 | 文本插入 |
LV_EVENT_REFRESH | 刷新 | 需要刷新对象 |
LV_EVENT_SCREEN_UNLOAD_START | 屏幕卸载开始 | 屏幕切换开始 |
LV_EVENT_SCREEN_LOAD_START | 屏幕加载开始 | 屏幕加载开始 |
LV_EVENT_SCREEN_LOADED | 屏幕已加载 | 屏幕加载完成 |
LV_EVENT_SCREEN_UNLOADED | 屏幕已卸载 | 屏幕卸载完成 |
LV_EVENT_HIT_TEST | 点击测试 | 高级点击测试 |
4. 设计优势与缺点分析
4.1 设计优势
4.1.1 灵活的事件过滤机制
优势:通过事件过滤器实现精确的事件订阅,避免不必要的回调处理。
// 只监听点击事件lv_obj_add_event_cb(btn,click_handler,LV_EVENT_CLICKED,NULL);// 监听所有事件lv_obj_add_event_cb(obj,all_handler,LV_EVENT_ALL,NULL);4.1.2 完善的事件冒泡机制
优势:支持事件从子对象向父对象传播,实现组件间的协作。
// 启用事件冒泡lv_obj_add_flag(container,LV_OBJ_FLAG_EVENT_BUBBLE);// 子对象点击事件会冒泡到容器4.1.3 内存高效的事件存储
优势:使用动态分配的事件描述符数组,仅在需要时分配内存。
// 事件描述符动态管理obj->spec_attr->event_dsc_cnt++;obj->spec_attr->event_dsc=lv_mem_realloc(...);4.2 设计缺点
4.2.1 事件处理顺序不直观
缺点:预处理回调、基类处理、普通回调的执行顺序可能导致调试困难。
4.2.2 内存管理复杂
缺点:频繁的事件增删可能导致内存碎片,事件描述符数组的 realloc 操作效率较低。
4.2.3 缺乏事件优先级控制
缺点:同一类型事件的所有回调函数执行顺序固定,无法自定义优先级。
5. 改进空间分析
5.1 性能优化方向
5.1.1 事件回调查找优化
当前问题:线性遍历事件描述符数组查找匹配回调。
改进方案:
// 使用哈希表优化查找typedefstruct{lv_event_code_tcode;lv_event_cb_tcb;// hash table for fast lookup}lv_event_hash_table_t;5.1.2 减少内存分配
当前问题:频繁的 realloc 导致内存碎片。
改进方案:
// 预分配事件池#defineLV_EVENT_POOL_SIZE16staticlv_event_dsc_tevent_pool[LV_EVENT_POOL_SIZE];5.1.3 事件合并处理
当前问题:每个事件独立处理,缺乏批处理机制。
改进方案:
// 事件队列批处理voidlv_event_process_batch(lv_event_t*events,uint32_tcount);5.2 代码结构优化
5.2.1 事件系统解耦
当前问题:事件处理逻辑与对象系统紧密耦合。
改进方案:
// 独立的事件管理器typedefstruct{lv_event_queue_tqueue;lv_event_handler_t*handlers;lv_event_filter_t*filters;}lv_event_manager_t;5.2.2 类型安全增强
当前问题:事件参数使用 void* 指针,缺乏类型检查。
改进方案:
// 模板化事件参数#defineLV_EVENT_PARAM(type)type*LV_EVENT_PARAM(lv_point_t)touch_point=lv_event_get_param(e);6. 横向对比分析
6.1 与AWTK事件系统的对比
6.1.1 AWTK事件系统特点
- 优势:XML配置驱动,事件绑定声明式
- 劣势:运行时动态解析,性能开销较大
6.1.2 LVGL相对优势
// LVGL: 编译时类型安全lv_obj_add_event_cb(btn,handler,LV_EVENT_CLICKED,NULL);// AWTK: 字符串绑定,运行时解析widget_on(widget,EVT_CLICK,handler,NULL);案例分析:在物联网设备上,LVGL的事件系统内存占用更小,执行效率更高。
6.2 与Qt事件系统的对比
6.2.1 Qt事件系统特点
- 优势:信号槽机制,支持多线程事件传递
- 劣势:对象继承体系复杂,学习曲线陡峭
6.2.2 LVGL相对优势
// LVGL: 轻量级事件处理staticvoidevent_handler(lv_event_t*e){if(lv_event_get_code(e)==LV_EVENT_CLICKED){// 处理逻辑}}// Qt: 信号槽机制connect(button,&QPushButton::clicked,this,&MainWindow::onButtonClicked);案例分析:在嵌入式GUI应用中,LVGL避免了Qt庞大的继承体系,更适合资源受限环境。
6.3 与Android事件系统的对比
6.3.1 Android事件特点
- 优势:丰富的触摸手势支持,事件分发机制完善
- 劣势:虚拟机开销,内存占用大
6.3.2 LVGL相对优势
// LVGL: 直接事件处理caseLV_EVENT_GESTURE:lv_dir_tdir=lv_indev_get_gesture_dir(indev);break;// Android: 复杂的事件分发链@Override public booleanonTouchEvent(MotionEvent event){// 处理逻辑}案例分析:LVGL在单片机环境下的手势识别比Android更直接高效。
6.4 与HTML/CSS事件系统的对比
6.4.1 HTML事件特点
- 优势:声明式绑定,事件委托机制
- 劣势:浏览器兼容性问题,性能依赖JS引擎
6.4.2 LVGL相对优势
// LVGL: 编译时绑定lv_obj_add_event_cb(btn,click_handler,LV_EVENT_CLICKED,NULL);// HTML: 运行时绑定document.getElementById('btn').addEventListener('click',handler);案例分析:LVGL的事件系统在嵌入式设备上提供了更好的性能保证和可预测性。
7. 纵向对比分析
7.1 LVGL 8.4 vs 9.4 事件系统对比
7.1.1 架构演进
LVGL 8.4事件系统:
- 基于函数指针的简单回调机制
- 缺乏统一的事件描述符管理
- 事件过滤功能有限
LVGL 9.4事件系统:
- 引入结构化的事件描述符
- 支持复杂的事件过滤和冒泡
- 完善的事件生命周期管理
7.1.2 API变化对比
| 功能 | LVGL 8.4 | LVGL 9.4 | 改进点 |
|---|---|---|---|
| 事件注册 | lv_obj_set_event_cb | lv_obj_add_event_cb | 支持多回调 |
| 事件发送 | lv_event_send | lv_event_send | 参数更丰富 |
| 事件过滤 | 无 | 事件代码过滤 | 精确控制 |
| 冒泡控制 | 有限 | lv_event_stop_bubbling | 更灵活 |
7.1.3 性能对比
LVGL 8.4:
// 单一回调函数lv_obj_set_event_cb(obj,event_handler);LVGL 9.4:
// 多回调支持,但增加管理开销lv_obj_add_event_cb(obj,handler1,LV_EVENT_CLICKED,NULL);lv_obj_add_event_cb(obj,handler2,LV_EVENT_PRESSED,NULL);性能影响:9.4版本在多回调场景下有轻微性能开销,但提供了更好的灵活性。
7.1.4 内存使用对比
| 版本 | 事件描述符大小 | 管理开销 | 优势 |
|---|---|---|---|
| 8.4 | 单个函数指针 | 最小 | 内存效率 |
| 9.4 | 动态数组 | 动态分配 | 功能丰富 |
演进原因分析:
- 复杂应用需求:现代GUI应用需要更复杂的事件处理逻辑
- 组件化发展:LVGL向组件化方向演进,需要更灵活的事件机制
- 生态完善:为第三方组件提供更好的事件扩展能力
8. 专项分析:事件生命周期
8.1 按钮组件事件生命周期
| 当前状态 | 事件/条件 | 下一状态 | 说明 |
|---|---|---|---|
| 初始状态 | - | Idle | 按钮空闲状态 |
| Idle | 按下开始 | Pressed | 触发 LV_EVENT_PRESSED |
| Pressed | 持续按下 | Pressing | 触发 LV_EVENT_PRESSING |
| Pressing | 长按时间到达 | LongPressed | 触发 LV_EVENT_LONG_PRESSED |
| LongPressed | 长按重复时间到达 | LongPressedRepeat | 触发 LV_EVENT_LONG_PRESSED_REPEAT |
| Pressing | 手指离开 | Released | - |
| LongPressed | 手指离开 | Released | - |
| LongPressedRepeat | 手指离开 | Released | - |
| Released | 释放完成 | Clicked | 触发 LV_EVENT_CLICKED |
| Released | 短点击完成 | ShortClicked | 触发 LV_EVENT_SHORT_CLICKED |
| Clicked | - | 初始状态 | 完成点击 |
| ShortClicked | - | 初始状态 | 完成短点击 |
| Pressed | 手指滑出 | PressLost | 触发 LV_EVENT_PRESS_LOST |
| PressLost | - | 初始状态 | 按下丢失 |
8.2 滚动容器事件生命周期
| 当前状态 | 事件/条件 | 下一状态 | 说明 |
|---|---|---|---|
| 初始状态 | - | Idle | 容器空闲状态 |
| Idle | 开始滚动 | ScrollBegin | 触发 LV_EVENT_SCROLL_BEGIN |
| ScrollBegin | 正在滚动 | Scrolling | 触发 LV_EVENT_SCROLL |
| ScrollBegin | 快速滚动结束 | ScrollEnd | 快速滚动直接结束 |
| Scrolling | 滚动停止 | ScrollEnd | 触发 LV_EVENT_SCROLL_END |
| Scrolling | 继续滚动 | Scrolling | 持续触发 LV_EVENT_SCROLL |
| ScrollEnd | - | 初始状态 | 滚动完成 |
8.3 屏幕切换生命周期
| 当前状态 | 事件 | 下一状态 | 说明 |
|---|---|---|---|
| 初始状态 | - | ScreenUnloadStart | 触发 LV_EVENT_SCREEN_UNLOAD_START |
| ScreenUnloadStart | 屏幕卸载开始 | ScreenLoadStart | 触发 LV_EVENT_SCREEN_LOAD_START |
| ScreenLoadStart | 屏幕加载开始 | ScreenLoaded | 触发 LV_EVENT_SCREEN_LOADED |
| ScreenLoaded | 屏幕已加载 | ScreenUnloaded | 触发 LV_EVENT_SCREEN_UNLOADED |
| ScreenUnloaded | - | 初始状态 | 屏幕切换完成 |
8.4 对象生命周期事件序列
8.4.1 对象创建序列
LV_EVENT_CHILD_CREATED(父对象接收)LV_EVENT_SIZE_CHANGED(尺寸初始化)LV_EVENT_STYLE_CHANGED(样式应用)LV_EVENT_DRAW_MAIN_BEGIN(首次绘制)
8.4.2 对象销毁序列
LV_EVENT_DELETE(对象自身)LV_EVENT_CHILD_DELETED(父对象接收)- 事件系统清理(自动)
8.4.3 布局变化序列
LV_EVENT_SIZE_CHANGED(尺寸变化)LV_EVENT_LAYOUT_CHANGED(布局重算)LV_EVENT_CHILD_CHANGED(子对象调整)LV_EVENT_REFRESH(界面刷新)
附录
A. 参考文档
- LVGL 9.4官方文档 - API参考 - LVGL官方API文档和事件系统说明
- LVGL事件系统源码分析 - LVGL事件处理机制详细文档
- GUI框架设计模式分析 - 嵌入式GUI框架事件系统对比研究
B. 相关资源
- LVGL GitHub源码仓库 - LVGL项目源码和示例代码
- LVGL官方论坛 - LVGL开发者社区和技术讨论
- AWTK开源GUI框架 - 国产嵌入式GUI框架源码
- Qt信号槽机制官方文档 - Qt框架事件系统参考