lv_obj_create 创建流程学习文档
一、整体流程总览
一句话概括:
lv_obj_create = 按类分配对象内存并挂到父对象(或屏幕)→ 运行构造函数链 → 应用主题 → 刷新样式与尺寸 → 通知父对象并触发重绘。
主要调用链:
lv_obj_create(parent)
├── lv_obj_class_create_obj(MY_CLASS, parent) // 分配 + 挂接父子树
└── lv_obj_class_init_obj(obj) // 主题、构造、样式、尺寸、通知
二、入口:lv_obj_create
位置:src/core/lv_obj.c
lv_obj_t * lv_obj_create(lv_obj_t * parent)
{
LV_LOG_INFO("begin");
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
LV_ASSERT_NULL(obj);
if(obj == NULL) return NULL;
lv_obj_class_init_obj(obj);
return obj;
}
- 不直接分配/初始化结构体,而是通过类系统两步完成:
- lv_obj_class_create_obj:只负责“创建 + 挂接父子树”
- lv_obj_class_init_obj:负责“主题、构造链、样式、尺寸、事件通知”
三、对象创建:lv_obj_class_create_obj
位置:src/core/lv_obj_class.c
3.1 获取实例大小
get_instance_size(class_p)从当前类向上查找第一个instance_size非 0 的类- 基类
lv_obj的instance_size = sizeof(lv_obj_t) - 自定义控件可定义更大的结构体,通过类统一分配
3.2 分配并设置基本属性
lv_malloc_zeroed(s):分配并清零对象内存obj->class_p = class_p:绑定类obj->parent = parent:设置父对象
3.3 区分“屏幕”与“普通子对象”
| parent | 行为 |
|---|---|
parent == NULL | 作为 Screen:加入 disp->screens[],坐标设为全屏 [0,0] ~ [hor_res-1, ver_res-1] |
parent != NULL | 普通对象:为 parent 分配/扩展 spec_attr->children[],将 obj 加入末尾 |
小结:本步完成 内存 + 类信息 + 父子树 +(屏幕时)初始坐标,尚未做样式、标志位等初始化。
四、初始化:lv_obj_class_init_obj
位置:src/core/lv_obj_class.c
void lv_obj_class_init_obj(lv_obj_t * obj)
{
lv_obj_mark_layout_as_dirty(obj);
lv_obj_enable_style_refresh(false);
lv_theme_apply(obj);
lv_obj_construct(obj->class_p, obj);
lv_obj_enable_style_refresh(true);
lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY);
lv_obj_refresh_self_size(obj);
// 默认 group
lv_group_t * def_group = lv_group_get_default();
if(def_group && lv_obj_is_group_def(obj))
lv_group_add_obj(def_group, obj);
lv_obj_t * parent = lv_obj_get_parent(obj);
if(parent) {
lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj);
lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, obj);
lv_obj_invalidate(obj);
}
}
4.1 标记布局脏
lv_obj_mark_layout_as_dirty(obj):表示该对象布局待重算,后续布局系统会重新排版
4.2 暂停样式刷新
lv_obj_enable_style_refresh(false):初始化阶段会改很多样式,先关闭刷新避免重复计算
4.3 应用主题
lv_theme_apply(obj):根据当前 theme 为对象附加默认样式(颜色、字体、padding 等)
4.4 运行构造函数链:lv_obj_construct
逻辑:从基类到派生类依次调用各类的 constructor_cb。
static void lv_obj_construct(const lv_obj_class_t * class_p, lv_obj_t * obj)
{
if(obj->class_p->base_class) {
obj->class_p = obj->class_p->base_class;
lv_obj_construct(class_p, obj); // 先构造基类
obj->class_p = original_class_p;
}
if(obj->class_p->constructor_cb)
obj->class_p->constructor_cb(class_p, obj);
}
对 lv_obj_create 而言,最终会执行基类的 lv_obj_constructor。
lv_obj_constructor 做了什么(src/core/lv_obj.c)
-
初始坐标(有 parent 时)
- 以父的
coords+pad_top/pad_left为基准,减去父的scroll_left/scroll_top - 先设
y2 = y1 - 1、x2 = x1 - 1(零面积),后续由布局/尺寸计算再更新
- 以父的
-
设置默认 flags
LV_OBJ_FLAG_CLICKABLE、LV_OBJ_FLAG_SNAPPABLE- 有 parent 时:
LV_OBJ_FLAG_PRESS_LOCK、LV_OBJ_FLAG_SCROLL_CHAIN、LV_OBJ_FLAG_GESTURE_BUBBLE LV_OBJ_FLAG_CLICK_FOCUSABLELV_OBJ_FLAG_SCROLLABLE、LV_OBJ_FLAG_SCROLL_ELASTIC、LV_OBJ_FLAG_SCROLL_MOMENTUM、LV_OBJ_FLAG_SCROLL_WITH_ARROW
-
可选:
LV_OBJ_ID_AUTO_ASSIGN时自动分配 ID(调试/打印树用)
4.5 恢复样式刷新并刷新样式
lv_obj_enable_style_refresh(true)lv_obj_refresh_style(obj, LV_PART_ANY, LV_STYLE_PROP_ANY):根据 state 和所有样式计算最终绘制属性
4.6 计算自身尺寸
lv_obj_refresh_self_size(obj):根据 class 的 width_def/height_def、样式中的 width/height 及 LV_SIZE_CONTENT 等,得到宽高并更新 coords
4.7 默认 group(可选)
- 若对象类为
group_def且存在默认lv_group,则lv_group_add_obj(def_group, obj),便于键盘/编码器导航
4.8 通知父对象并触发重绘
lv_obj_send_event(parent, LV_EVENT_CHILD_CHANGED, obj):父可触发布局更新lv_obj_send_event(parent, LV_EVENT_CHILD_CREATED, obj):父可知有新子对象创建lv_obj_invalidate(obj):标记需重绘,下一帧会画出
五、流程速记(7 步)
| 步骤 | 内容 |
|---|---|
| 1 | 按类的 instance_size 分配并清零内存 |
| 2 | 挂接父子树:parent==NULL 则挂到 display->screens,否则加入 parent->children |
| 3 | 标记布局脏:lv_obj_mark_layout_as_dirty(obj) |
| 4 | 应用主题:lv_theme_apply(obj) |
| 5 | 构造链:先基类再当前类,基类设置初始坐标与默认 flags |
| 6 | 打开样式刷新 → lv_obj_refresh_style → lv_obj_refresh_self_size |
| 7 | 可选加入默认 group;给父发 CHILD_CHANGED / CHILD_CREATED;lv_obj_invalidate |
六、相关文件索引
| 文件 | 作用 |
|---|---|
src/core/lv_obj.c | lv_obj_create、lv_obj_constructor、lv_obj_destructor、事件与绘制 |
src/core/lv_obj_class.c | lv_obj_class_create_obj、lv_obj_class_init_obj、lv_obj_construct |
src/core/lv_obj_private.h / lv_obj_class_private.h | 对象/类内部结构定义 |
1229

被折叠的 条评论
为什么被折叠?



