LVGL 8.3中lv_obj_set_grid_dsc_array函数参数错误解决

4 次阅读

LVGL 8.3版本中,lv_obj_set_grid_dsc_array 是用于设置对象 Grid 布局描述数组的重要函数。很多开发者在使用该函数配置界面布局时,会遇到参数错误、编译失败或者运行异常等问题。通常情况下,这些问题并不是函数本身存在缺陷,而是由于参数类型、数组定义方式以及LVGL版本接口理解错误导致的。

本文将详细分析 lv_obj_set_grid_dsc_array 函数的参数要求、常见错误原因以及正确解决方法,帮助开发者快速排查LVGL Grid布局配置问题。

lv_obj_set_grid_dsc_array函数作用介绍

LVGL 8.3引入并完善了基于Grid的布局管理方式,通过行和列描述数组,可以快速实现类似CSS Grid的界面排列效果。

函数原型如下:

C
void lv_obj_set_grid_dsc_array(lv_obj_t * obj, const lv_coord_t col_dsc[], const lv_coord_t row_dsc[]);

其中:

  • obj:需要应用Grid布局的LVGL对象。

  • col_dsc:列描述数组,用于定义每一列的宽度。

  • row_dsc:行描述数组,用于定义每一行的高度。

Grid描述数组并不是普通的尺寸数组,而是由尺寸参数和结束标志组成。

例如:

C
static lv_coord_t col_dsc[] = {
    100,
    100,
    LV_GRID_TEMPLATE_LAST
};

static lv_coord_t row_dsc[] = {
    50,
    50,
    LV_GRID_TEMPLATE_LAST
};

lv_obj_set_grid_dsc_array(obj, col_dsc, row_dsc);

表示创建两列、两行的Grid布局。

常见的lv_obj_set_grid_dsc_array参数错误

1. 忘记添加LV_GRID_TEMPLATE_LAST结束标记

这是最常见的问题之一。

错误示例:

C
static lv_coord_t col_dsc[] = {
    80,
    80
};

static lv_coord_t row_dsc[] = {
    40,
    40
};

lv_obj_set_grid_dsc_array(obj, col_dsc, row_dsc);

虽然代码可以通过编译,但是LVGL无法判断数组结束位置,可能导致:

  • 布局计算异常;

  • 访问非法内存;

  • 子对象显示错乱;

  • 随机崩溃。

正确写法:

C
static lv_coord_t col_dsc[] = {
    80,
    80,
    LV_GRID_TEMPLATE_LAST
};

static lv_coord_t row_dsc[] = {
    40,
    40,
    LV_GRID_TEMPLATE_LAST
};

LV_GRID_TEMPLATE_LAST本质上是一个特殊结束值,用于告诉LVGL Grid解析器数组已经结束。


2. 数组类型定义错误

lv_obj_set_grid_dsc_array要求传入:

C
const lv_coord_t []

而部分开发者会错误使用:

C
int col_dsc[] = {
    100,
    100,
    LV_GRID_TEMPLATE_LAST
};

虽然某些平台上可能可以运行,但存在类型不匹配风险。

推荐使用:

C
lv_coord_t col_dsc[] = {
    100,
    100,
    LV_GRID_TEMPLATE_LAST
};

lv_coord_t是LVGL内部用于表示坐标和尺寸的数据类型,根据配置可能是16位或32位整数,使用统一类型可以避免兼容性问题。


3. 使用了LVGL 7版本的布局代码

LVGL 8.x相比7.x有较大变化。

一些旧代码可能使用:

C
lv_obj_set_layout(obj, LV_LAYOUT_GRID);

然后直接调用旧版本接口。

在LVGL 8.3中,需要确认相关头文件和布局宏是否正确:

C
#include "lvgl.h"

并确保开启Grid布局支持:

C
#define LV_USE_GRID 1

如果配置文件中关闭了Grid功能,可能出现:

  • 函数不存在;

  • 宏未定义;

  • 编译报错。


正确配置Grid布局的完整示例

下面是一个LVGL 8.3中常用的Grid布局示例:

C
static lv_coord_t col_dsc[] = {
    120,
    120,
    LV_GRID_TEMPLATE_LAST
};

static lv_coord_t row_dsc[] = {
    60,
    60,
    LV_GRID_TEMPLATE_LAST
};

lv_obj_t * cont = lv_obj_create(lv_scr_act());

lv_obj_set_size(cont, 260, 140);

lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);

lv_obj_set_layout(cont, LV_LAYOUT_GRID);

创建子对象:

C
lv_obj_t * btn1 = lv_btn_create(cont);

lv_obj_set_grid_cell(
    btn1,
    LV_GRID_ALIGN_STRETCH,
    0,
    1,
    LV_GRID_ALIGN_STRETCH,
    0,
    1
);

这样按钮会自动放置在第一列第一行。


lv_obj_set_grid_dsc_array参数数量错误分析

部分开发者会误认为数组数量需要通过参数传入,例如:

错误理解:

C
lv_obj_set_grid_dsc_array(
    obj,
    col_dsc,
    3,
    row_dsc,
    2
);

实际上该函数并不接收行列数量。

LVGL通过:

C
LV_GRID_TEMPLATE_LAST

自动识别数组长度。

因此函数调用固定为:

C
lv_obj_set_grid_dsc_array(
    obj,
    col_dsc,
    row_dsc
);

如果增加额外参数,会直接导致:

too many arguments to function 'lv_obj_set_grid_dsc_array'

编译错误。


LVGL 8.3中动态生成Grid数组注意事项

如果Grid尺寸需要动态变化,可以使用动态数组:

C
lv_coord_t * col_dsc;

col_dsc = lv_malloc(sizeof(lv_coord_t) * 4);

col_dsc[0] = 80;
col_dsc[1] = 80;
col_dsc[2] = 80;
col_dsc[3] = LV_GRID_TEMPLATE_LAST;

lv_obj_set_grid_dsc_array(obj, col_dsc, row_dsc);

需要注意:

  1. 内存生命周期必须覆盖Grid使用周期;

  2. 不能使用局部临时数组;

  3. 删除对象前需要释放动态内存。

错误示例:

C
void create_grid()
{
    lv_coord_t col_dsc[] = {
        100,
        LV_GRID_TEMPLATE_LAST
    };

    lv_obj_set_grid_dsc_array(obj, col_dsc, row_dsc);
}

函数结束后:

C
col_dsc

所在栈空间失效,可能造成随机显示异常。


lv_obj_set_grid_dsc_array运行异常排查步骤

遇到Grid布局异常时,可以按照以下顺序检查:

第一步:确认LVGL版本

查看:

C
LVGL_VERSION_MAJOR
LVGL_VERSION_MINOR

确保当前使用的是8.3版本。


第二步:检查配置文件

确认:

C
#define LV_USE_GRID 1

已经开启。


第三步:检查描述数组

确认:

  • 使用 lv_coord_t 类型;

  • 最后存在 LV_GRID_TEMPLATE_LAST;

  • 数组没有越界。


第四步:确认布局模式

仅设置Grid描述数组还不够,需要:

C
lv_obj_set_layout(obj, LV_LAYOUT_GRID);

否则对象不会按照Grid规则排列。


lv_obj_set_grid_dsc_array与lv_obj_set_grid_cell的关系

lv_obj_set_grid_dsc_array负责定义整体布局结构,相当于设置:

  • 有多少列;

  • 有多少行;

  • 每行每列尺寸。

而:

C
lv_obj_set_grid_cell()

负责指定具体控件位置。

二者需要配合使用。

例如:

C
lv_obj_set_grid_cell(
    label,
    LV_GRID_ALIGN_CENTER,
    0,
    1,
    LV_GRID_ALIGN_CENTER,
    0,
    1
);

表示:

  • 位于第0列;

  • 占用1列;

  • 位于第0行;

  • 占用1行。

如果只调用:

C
lv_obj_set_grid_dsc_array()

而不设置子对象Grid位置,控件不会自动完成排列。


总结

LVGL 8.3中的 lv_obj_set_grid_dsc_array 参数错误问题,主要集中在函数参数理解错误、Grid描述数组定义不规范以及版本配置不正确几个方面。

使用该函数时需要重点注意:

  1. 函数只接收三个参数:对象、列描述数组、行描述数组;

  2. 描述数组必须使用 lv_coord_t 类型;

  3. 数组末尾必须添加 LV_GRID_TEMPLATE_LAST;

  4. 开启 LV_USE_GRID 配置;

  5. 配合 lv_obj_set_layout(obj, LV_LAYOUT_GRID) 使用。

掌握这些关键点后,可以有效避免LVGL 8.3 Grid布局开发中的编译错误和运行异常,提高嵌入式GUI开发效率。