lv_obj_create 创建

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;
}
  • 不直接分配/初始化结构体,而是通过类系统两步完成:
    1. lv_obj_class_create_obj:只负责“创建 + 挂接父子树”
    2. 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_objinstance_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)
  1. 初始坐标(有 parent 时)

    • 以父的 coords + pad_top/pad_left 为基准,减去父的 scroll_left/scroll_top
    • 先设 y2 = y1 - 1x2 = x1 - 1(零面积),后续由布局/尺寸计算再更新
  2. 设置默认 flags

    • LV_OBJ_FLAG_CLICKABLELV_OBJ_FLAG_SNAPPABLE
    • 有 parent 时:LV_OBJ_FLAG_PRESS_LOCKLV_OBJ_FLAG_SCROLL_CHAINLV_OBJ_FLAG_GESTURE_BUBBLE
    • LV_OBJ_FLAG_CLICK_FOCUSABLE
    • LV_OBJ_FLAG_SCROLLABLELV_OBJ_FLAG_SCROLL_ELASTICLV_OBJ_FLAG_SCROLL_MOMENTUMLV_OBJ_FLAG_SCROLL_WITH_ARROW
  3. 可选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_stylelv_obj_refresh_self_size
7可选加入默认 group;给父发 CHILD_CHANGED / CHILD_CREATED;lv_obj_invalidate

六、相关文件索引

文件作用
src/core/lv_obj.clv_obj_createlv_obj_constructorlv_obj_destructor、事件与绘制
src/core/lv_obj_class.clv_obj_class_create_objlv_obj_class_init_objlv_obj_construct
src/core/lv_obj_private.h / lv_obj_class_private.h对象/类内部结构定义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值