Lvgl8.3 自定义矩形按键的标签,图标 lv_btnmatrix

效果图
在这里插入图片描述

主要实现自定义标签/图标,位置,字体可以随意修改


/**
 * @brief 事件回调函数
 *
 * @param e
 */
static void event_cb(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t *obj = lv_event_get_target(e);

    // 按键点击事件
    if (code == LV_EVENT_VALUE_CHANGED)
    {
        uint32_t id = lv_btnmatrix_get_selected_btn(obj);
        const char *txt = lv_btnmatrix_get_btn_text(obj, id);

        LV_LOG("%s was pressed \n", txt);
    }

    else if (code == LV_EVENT_DRAW_PART_BEGIN)
    {
        lv_obj_draw_part_dsc_t *dsc = lv_event_get_draw_part_dsc(e);
        if (dsc->class_p == &lv_btnmatrix_class && dsc->type == LV_BTNMATRIX_DRAW_PART_BTN)
        {
            dsc->label_dsc->opa = LV_OPA_0;                                      // 隐藏原来的文字标签
            dsc->rect_dsc->radius = 0;                                           // 圆角半径
            if (lv_btnmatrix_get_selected_btn(obj) == dsc->id)                   // 选中颜色
                dsc->rect_dsc->bg_color = lv_palette_darken(LV_PALETTE_GREY, 1); // 选中颜色
            else                                                                 //
                dsc->rect_dsc->bg_color = lv_color_hex(0x698B69);                // 未选中颜色
        }
    }

    else if (code == LV_EVENT_DRAW_PART_END)
    {
        lv_obj_draw_part_dsc_t *dsc = lv_event_get_draw_part_dsc(e);
        /*当按钮矩阵绘制按钮时*/
        if (dsc->class_p == &lv_btnmatrix_class && dsc->type == LV_BTNMATRIX_DRAW_PART_BTN)
        {
            /*在绘制按钮时添加自定义内容*/
            {
                { /* 自定义标签 ******************************************************************************* */
                    char buf[8];
                    const char *txt = lv_btnmatrix_get_btn_text(obj, dsc->id); // 获取按键标签文本
                    lv_snprintf(buf, sizeof(buf), "%s", txt);

                    lv_point_t text_size;
                    lv_txt_get_size(&text_size, buf, LV_FONT_DEFAULT, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
                    lv_area_t txt_area;
                    txt_area.x1 = dsc->draw_area->x1 + lv_area_get_width(dsc->draw_area) / 2 - text_size.x / 2; // 计算标签居中位置
                    txt_area.x2 = txt_area.x1 + text_size.x;
                    txt_area.y2 = dsc->draw_area->y1 - 50; // 往上偏移50
                    txt_area.y1 = txt_area.y2 - text_size.y;

                    lv_draw_label_dsc_t label_dsc;
                    lv_draw_label_dsc_init(&label_dsc);
                    label_dsc.color = lv_color_white(); // 文字的颜色为白色
                    lv_draw_label(dsc->draw_ctx, &label_dsc, &txt_area, buf, NULL);
                }

                { /* 自定义图标 ******************************************************************************* */
                    LV_IMG_DECLARE(img_star);
                    lv_img_header_t header;
                    lv_res_t res = lv_img_decoder_get_info(&img_star, &header);
                    if (res != LV_RES_OK)
                        return;
                    lv_area_t a; // 计算图标居中位置
                    a.x1 = dsc->draw_area->x1 + (lv_area_get_width(dsc->draw_area) - header.w) / 2;
                    a.x2 = a.x1 + header.w - 1;
                    a.y1 = dsc->draw_area->y1 + (lv_area_get_height(dsc->draw_area) - header.h) / 2 + 50; // 图标往下偏移
                    a.y2 = a.y1 + header.h - 1;

                    lv_draw_img_dsc_t img_draw_dsc;
                    lv_draw_img_dsc_init(&img_draw_dsc);
                    img_draw_dsc.recolor = lv_color_black();
                    if (lv_btnmatrix_get_selected_btn(obj) == dsc->id)
                        img_draw_dsc.recolor_opa = LV_OPA_30;

                    lv_draw_img(dsc->draw_ctx, &img_draw_dsc, &a, &img_star);
                }
            }
        }
    }
}

/**
 * @brief 矩阵按键(自定义的标签,图标)
 *
 */
void lv_display_6but(void)
{

    // 矩阵样式初
    static lv_style_t style_bg;
    lv_style_init(&style_bg);
    lv_style_set_pad_all(&style_bg, 10); // 矩阵四周的间距
    lv_style_set_pad_gap(&style_bg, 10); // 按键之间的间距
    // lv_style_set_clip_corner(&style_bg, true);        // 开启圆角裁剪
    // lv_style_set_radius(&style_bg, LV_RADIUS_CIRCLE); // 设置背景为圆形
    lv_style_set_border_width(&style_bg, 0); // 设置边框宽度为0

    // 按键样式
    static lv_style_t style_btn;
    lv_style_init(&style_btn);                //
    lv_style_set_radius(&style_btn, 0);       // 设置按钮无圆角
    lv_style_set_border_width(&style_btn, 0); // 设置边框宽度
    // lv_style_set_border_opa(&style_btn, LV_OPA_0); // 设置边框透明度
    // lv_style_set_border_color(&style_btn, lv_palette_main(LV_PALETTE_GREY)); //
    // lv_style_set_border_side(&style_btn, LV_BORDER_SIDE_INTERNAL);           // 设置边框位于内部

    static const char *map[] = {"clock", "image", "weather", "gif", "about", "set up", ""};

    lv_obj_t *btnm = lv_btnmatrix_create(lv_scr_act());
    lv_btnmatrix_set_map(btnm, map);
    lv_obj_add_style(btnm, &style_bg, 0);                    // 矩阵样式
    lv_obj_add_style(btnm, &style_btn, LV_PART_ITEMS);       // 按键样式
    lv_obj_add_event_cb(btnm, event_cb, LV_EVENT_ALL, NULL); // 注册回调函数
    lv_obj_set_size(btnm, 135 * 6, 240);                     // 矩阵大小

    lv_btnmatrix_set_btn_ctrl_all(btnm, LV_BTNMATRIX_CTRL_CHECKABLE); // 所有按钮可选
    lv_btnmatrix_set_one_checked(btnm, true);                         // 设置按钮矩阵允许单选

    lv_obj_center(btnm);
}
<think>我们之前讨论的是在LVGL 8.3中设置表格指定行列的文本和背景颜色。用户现在提到在LVGL 8.3中没有`lv_table_set_cell_style`方法,这确实是一个问题,因为在LVGL 8.3中,表格控件的样式设置方式与后续版本不同。 在LVGL 8.3中,表格控件并没有提供直接设置单个单元格样式的函数(如`lv_table_set_cell_style`)。实际上,在LVGL 8.3中,表格的样式是通过不同的“部分”(parts)和“状态”(states)来设置的,而且样式是应用于整个表格或者整行/整列(通过使用不同的部分)的。 根据LVGL 8.3的文档,表格控件有以下部分(parts): - `LV_TABLE_PART_BG`: 背景(整个表格) - `LV_TABLE_PART_CELL1`: 奇数行(或第一行)的单元格 - `LV_TABLE_PART_CELL2`: 偶数行的单元格 - `LV_TABLE_PART_CELL3`: 特殊强调的单元格(需要额外设置) - `LV_TABLE_PART_CELL4`: 另一种特殊单元格 在LVGL 8.3中,我们通常通过给表格的不同部分添加样式来实现不同行的颜色交替。如果要设置单个单元格的样式,官方并没有提供直接的API。但是,我们可以通过一些技巧来实现类似的效果。 解决方案思路: 1. **使用自定义绘制事件**:我们可以为表格控件添加一个绘图事件回调,在绘制每个单元格时,根据行列索引动态修改绘制属性(如背景色和文本色)。这种方法较为底层,但灵活。 2. **利用多个样式部分**:在LVGL 8.3中,表格的每个单元格可以属于四个不同的部分(`CELL1`到`CELL4`)。我们可以通过`lv_table_set_cell_type(table, row, col, type)`来设置单元格的类型(1,2,3,4),然后为每种类型设置不同的样式。这样,我们可以将需要特殊样式的单元格设置为类型3或4,然后定义这些类型的样式。 由于用户需要设置指定行列的颜色,这里推荐第二种方法,因为相对简单且不需要处理底层绘制事件。 具体步骤: 步骤1:创建表格并设置行列数。 步骤2:为表格的默认部分(`LV_TABLE_PART_BG`)设置基本样式(比如默认文本颜色、背景色等)。 步骤3:为不同的单元格部分(`LV_TABLE_PART_CELL1`、`CELL2`、`CELL3`、`CELL4`)设置样式。注意,这些样式会覆盖背景部分的样式。 步骤4:通过`lv_table_set_cell_type(table, row, col, type)`将需要特殊样式的单元格设置为某个类型(比如3或4),然后该单元格就会应用对应部分的样式。 注意:在LVGL 8.3中,默认情况下,表格的单元格会交替使用`CELL1`和`CELL2`,第一行和奇数行使用`CELL1`,偶数行使用`CELL2`。我们可以通过设置单元格类型(1到4)来覆盖默认的类型。 示例代码: 假设我们要将第1行第2列(行索引0,列索引1)的单元格设置为特殊样式(比如红色背景,白色文字)。 1. 创建表格并设置行列: ```c lv_obj_t * table = lv_table_create(lv_scr_act(), NULL); lv_table_set_col_cnt(table, 3); lv_table_set_row_cnt(table, 4); ``` 2. 设置表格的基本样式(背景部分): ```c static lv_style_t style_bg; lv_style_init(&style_bg); lv_style_set_pad_all(&style_bg, LV_STATE_DEFAULT, 10); lv_table_add_style(table, LV_TABLE_PART_BG, &style_bg); ``` 3. 设置单元格类型1和2的样式(交替行样式): ```c static lv_style_t style_cell1; lv_style_init(&style_cell1); lv_style_set_bg_color(&style_cell1, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_style_set_text_color(&style_cell1, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_table_add_style(table, LV_TABLE_PART_CELL1, &style_cell1); static lv_style_t style_cell2; lv_style_init(&style_cell2); lv_style_set_bg_color(&style_cell2, LV_STATE_DEFAULT, LV_COLOR_GRAY); lv_style_set_text_color(&style_cell2, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_table_add_style(table, LV_TABLE_PART_CELL2, &style_cell2); ``` 4. 创建一个特殊样式(比如用于类型3): ```c static lv_style_t style_cell3; lv_style_init(&style_cell3); lv_style_set_bg_color(&style_cell3, LV_STATE_DEFAULT, LV_COLOR_RED); lv_style_set_text_color(&style_cell3, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_table_add_style(table, LV_TABLE_PART_CELL3, &style_cell3); ``` 5. 将指定单元格的类型设置为3: ```c // 设置第0行第1列的单元格类型为3(注意:行和列索引从0开始) lv_table_set_cell_type(table, 0, 1, 3); ``` 这样,该单元格就会应用`CELL3`部分的样式。 注意事项: - 这种方法只能设置有限的不同样式(最多4种:CELL1, CELL2, CELL3, CELL4)。如果需要更多样式,可能需要结合使用多个表格或者自定义绘制事件。 - 在设置单元格类型后,该单元格将不再使用默认的交替行样式(即CELL1或CELL2),而是使用设置的类型对应的样式。 如果用户需要动态改变某个单元格的样式,可以通过更改该单元格的类型(比如在事件回调中调用`lv_table_set_cell_type`)来实现。 由于用户提到没有`lv_table_set_cell_style`方法,所以上述方法是在LVGL 8.3中实现类似功能的推荐方式。 完整示例代码: ```c lv_obj_t * table = lv_table_create(lv_scr_act(), NULL); lv_table_set_col_cnt(table, 3); lv_table_set_row_cnt(table, 4); // 填充表格内容 lv_table_set_cell_value(table, 0, 0, "Name"); lv_table_set_cell_value(table, 0, 1, "Age"); lv_table_set_cell_value(table, 0, 2, "Gender"); // ... 其他单元格 // 设置背景样式 static lv_style_t style_bg; lv_style_init(&style_bg); lv_style_set_pad_all(&style_bg, LV_STATE_DEFAULT, 10); lv_style_set_border_width(&style_bg, LV_STATE_DEFAULT, 1); lv_table_add_style(table, LV_TABLE_PART_BG, &style_bg); // 设置CELL1(奇数行)样式 static lv_style_t style_cell1; lv_style_init(&style_cell1); lv_style_set_bg_color(&style_cell1, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_style_set_text_color(&style_cell1, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_table_add_style(table, LV_TABLE_PART_CELL1, &style_cell1); // 设置CELL2(偶数行)样式 static lv_style_t style_cell2; lv_style_init(&style_cell2); lv_style_set_bg_color(&style_cell2, LV_STATE_DEFAULT, lv_color_hex(0xf0f0f0)); lv_style_set_text_color(&style_cell2, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_table_add_style(table, LV_TABLE_PART_CELL2, &style_cell2); // 设置CELL3样式(特殊单元格,例如高亮) static lv_style_t style_cell3; lv_style_init(&style_cell3); lv_style_set_bg_color(&style_cell3, LV_STATE_DEFAULT, LV_COLOR_RED); lv_style_set_text_color(&style_cell3, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_table_add_style(table, LV_TABLE_PART_CELL3, &style_cell3); // 设置第一行(表头)全部为特殊样式(CELL3) for (int col = 0; col < 3; col++) { lv_table_set_cell_type(table, 0, col, 3); } // 设置某个特定单元格(例如第2行第1列)为特殊样式 lv_table_set_cell_type(table, 1, 0, 3); ``` 这样,表头行(第一行)和第2行第1列的单元格就会显示为红色背景白色文字。 如果用户需要设置更多样式的单元格,可以使用类型4(`CELL4`)并设置其样式,然后设置单元格类型为4。 相关问题: 1.LVGL 8.3中如何设置表格的列宽? 2. 如何响应LVGL表格的点击事件? 3.LVGL 8.3中如何动态更新表格数据并保持样式? 注意:由于用户使用的是LVGL 8.3,建议查阅对应版本的文档:https://docs.lvgl.io/8.3/widgets/table.html。 </think>### LVGL 8.3 表格指定行列颜色设置解决方案 在 LVGL 8.3 中,确实没有直接的 `lv_table_set_cell_style` 方法,但可以通过以下替代方案实现行列定制化着色: #### 核心解决方案:使用单元格类型标识 LVGL 8.3 提供了 `lv_table_set_cell_type()` 方法,结合样式分区控制: ```c // 1. 定义不同单元格类型样式 static lv_style_t style_normal; // 普通单元格 lv_style_init(&style_normal); lv_style_set_bg_color(&style_normal, LV_STATE_DEFAULT, LV_COLOR_WHITE); static lv_style_t style_highlight; // 高亮单元格 lv_style_init(&style_highlight); lv_style_set_bg_color(&style_highlight, LV_STATE_DEFAULT, LV_COLOR_RED); lv_style_set_text_color(&style_highlight, LV_STATE_DEFAULT, LV_COLOR_WHITE); // 2. 绑定样式到表格分区 lv_table_add_style(table, LV_TABLE_PART_CELL1, &style_normal); // 类型1 lv_table_add_style(table, LV_TABLE_PART_CELL2, &style_highlight); // 类型2 // 3. 设置指定单元格类型(行列索引从0开始) lv_table_set_cell_type(table, 1, 2, 2); // 设置第2行第3列为高亮类型 ``` #### 行列批量设置方法 **整行设置**: ```c for(uint16_t col = 0; col < lv_table_get_col_cnt(table); col++) { lv_table_set_cell_type(table, 2, col, 2); // 设置第3行所有单元格 } ``` **整列设置**: ```c for(uint16_t row = 0; row < lv_table_get_row_cnt(table); row++) { lv_table_set_cell_type(table, row, 1, 2); // 设置第2列所有单元格 } ``` #### 动态更新技巧 ```c // 修改样式 lv_style_set_bg_color(&style_highlight, LV_STATE_DEFAULT, LV_COLOR_BLUE); // 刷新表格 lv_obj_invalidate(table); ``` #### 完整示例 ```c lv_obj_t *table = lv_table_create(lv_scr_act(), NULL); lv_table_set_col_cnt(table, 3); lv_table_set_row_cnt(table, 4); // 填充数据 lv_table_set_cell_value(table, 0, 0, "Name"); // [^1] lv_table_set_cell_value_fmt(table, 0, 1, "Age"); // [^2] // 定义样式类型 static lv_style_t style_header, style_highlight; lv_style_init(&style_header); lv_style_set_bg_color(&style_header, LV_STATE_DEFAULT, LV_COLOR_GRAY); lv_style_set_text_color(&style_header, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_style_init(&style_highlight); lv_style_set_bg_color(&style_highlight, LV_STATE_DEFAULT, LV_COLOR_RED); // 绑定样式分区 lv_table_add_style(table, LV_TABLE_PART_CELL1, &lv_style_plain); // 默认类型1 lv_table_add_style(table, LV_TABLE_PART_CELL2, &style_header); // 类型2 lv_table_add_style(table, LV_TABLE_PART_CELL3, &style_highlight); // 类型3 // 设置表头行 for(int col=0; col<3; col++){ lv_table_set_cell_type(table, 0, col, 2); } // 设置特定单元格(第3行第2列) lv_table_set_cell_type(table, 2, 1, 3); ``` #### 关键说明 1. **样式分区**: - `LV_TABLE_PART_CELL1` → 单元格类型1 - `LV_TABLE_PART_CELL2` → 单元格类型2 - `LV_TABLE_PART_CELL3` → 单元格类型3 - `LV_TABLE_PART_CELL4` → 单元格类型4 2. **技术限制**: - 最多支持4种单元格样式类型 - 需通过 `lv_table_set_cell_type()` 间接控制样式 - 默认交替使用类型1和类型2 > 💡 **最佳实践**:将表头设为类型2,特殊单元格设为类型3/4,普通内容使用默认类型1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值