LVGL 控件之矩阵按钮(lv_buttonmatrix)


一、矩阵按键

1、组成

按钮矩阵部件由两个部分组成:主体背景和按钮,示意图如下:

  • LV_PART_MAIN:对应按钮矩阵的背景
  • LV_PART_ITEMS:对应按钮矩阵的按钮
lv_obj_set_style_bg_color(btnM, lv_color_make(152, 244, 123), LV_PART_MAIN);

lv_obj_set_style_bg_color(btnM, lv_color_make(152, 244, 123), LV_PART_ITEMS);

2、创建矩阵

按钮矩阵部件中的每个按钮都可以设置文本,如果用户想设置这些按钮文本,则需要定义一个字符串数组(指针),并在该数组中传入所需的文本内容,最后通过 lv_btnmatrix_set_map 函数设置按钮文本,示例代码如下:

注意:该数组最后一个元素必须为空

lv_obj_t *btnM = lv_btnmatrix_create(lv_scr_act());
static const char* btnMap[] = {
    ",", "ABC", "DEF", "\n",
    "GHI", "JKL", "MNO", "\n",
    "PQRS", "TUV", "WXYX", ""
};
lv_btnmatrix_set_map(btnM, btnMap);
lv_obj_align(btnM, LV_ALIGN_CENTER, 0, 0);

此外,每个按钮还有个索引,索引对于按钮的属性设置非常重要。实际上索引的顺序就是我们添加按键的顺序:

3、按钮宽度

在默认情况下,按钮矩阵每一行按钮的宽度都是自动计算的,如果用户想改变按钮的宽度,可以调用 lv_btnmatrix_set_btn_width 函数来进行设置。值得注意的是,在按钮矩阵部件中,按钮只能设置相对宽度。

现在在上例的基础上添加:

lv_btnmatrix_set_btn_width(btnM, 1, 10);

4、按键属性

用户可以调用 lv_btnmatrix_set_btn_ctrl 函数,为按钮添加、清除指定的属性,这些属性的相关枚举如下:

  • LV_BTNMATRIX_CTRL_HIDDEN:将按钮隐藏;
  • LV_BTNMATRIX_CTRL_NO_REPEAT:禁用长按;
  • LV_BTNMATRIX_CTRL_DISABLED:禁用按钮;
  • LV_BTNMATRIX_CTRL_CHECKABLE:启用按钮状态切换;
  • LV_BTNMATRIX_CTRL_CHECKED:选中按钮;
  • LV_BTNMATRIX_CTRL_POPOVER:按下此按钮时在弹出窗口中显示按钮标签;
  • LV_BTNMATRIX_CTRL_RECOLOR:启用按钮文本的重新着色功能。

例:

lv_btnmatrix_set_btn_ctrl(btnM, 0, LV_BTNMATRIX_CTRL_HIDDEN);
lv_btnmatrix_set_btn_ctrl(btnM, 1, LV_BTNMATRIX_CTRL_DISABLED);
lv_btnmatrix_set_btn_ctrl(btnM, 2, LV_BTNMATRIX_CTRL_CHECKABLE);


如果用户想要清除按钮的指定属性,可以调用 lv_btnmatrix_clear_btn_ctrl 函数。

5、按钮互斥

按钮互斥是指:在某一时刻,只允许有一个按钮处于按下不弹起状态(被选中),当我们选中一个按钮之后,其他的按钮将会自动清除选中属性,示意图如下:

lv_btnmatrix_set_btn_ctrl(btnM, 0, LV_BTNMATRIX_CTRL_CHECKABLE);
lv_btnmatrix_set_btn_ctrl(btnM, 1, LV_BTNMATRIX_CTRL_CHECKABLE);
lv_btnmatrix_set_btn_ctrl(btnM, 2, LV_BTNMATRIX_CTRL_CHECKABLE);

lv_btnmatrix_set_one_checked(btnm1, true);

点击第一个键后,其处于被选中状态;


现在再点击第三个键,其处于被选中状态,不过第一个键的状态被清除了:

在这里插入图片描述

6、按钮文本重着色

在默认情况下,按钮矩阵中的按钮文本都是黑色的,如果用户需要设置文本为其他的颜色,则必须先调用 lv_btnmatrix_set_btn_ctrl 函数,为按钮添加文本重着色的属性。

设置如下:

void my_gui(void)
{
    lv_obj_t *btnM = lv_btnmatrix_create(lv_scr_act());
    static const char* btnMap[] = {
        ",", "#FF0000 ABC#", "DEF", "\n",
        "GHI", "JKL", "MNO", "\n",
        "PQRS", "TUV", "WXYX", ""
    };
    lv_btnmatrix_set_map(btnM, btnMap);
    lv_obj_align(btnM, LV_ALIGN_CENTER, 0, 0);

    lv_btnmatrix_set_btn_ctrl(btnM, 1, LV_BTNMATRIX_CTRL_RECOLOR);
}


注意看,颜色设置格式为:# + 16 进制颜色 + 按钮文本 + #,在设置完文本颜色之后,我们还需要为按钮添加文本重着色的属性,其相关的枚举为 LV_BTNMATRIX_CTRL_RECOLOR

7、按钮矩阵部件的事件

  1. LV_EVENT_VALUE_CHANGED:当一个按钮被按下、释放或长按时发送。
  2. LV_EVENT_DRAW_PART_BEGIN:开始绘制按钮。

8、API 函数

函数含义
lv_btnmatrix_create()创建按钮矩阵部件
lv_btnmatrix_set_map()设置按钮
lv_btnmatrix_set_ctrl_map()设置多个按钮属性
lv_btnmatrix_set_selected_btn()设置选中的按钮
lv_btnmatrix_set_btn_ctrl()设置一个按钮的属性
lv_btnmatrix_clear_btn_ctrl()清除某个按钮的属性
lv_btnmatrix_set_btn_ctrl_all()设置所有按钮的属性
lv_btnmatrix_clear_btn_ctrl_all()清除所有按钮的属性
lv_btnmatrix_set_btn_width()设置单个按钮的相对宽度
lv_btnmatrix_set_one_checked()设置按钮互斥
lv_btnmatrix_get_map()获取按钮相关映射
lv_btnmatrix_get_selected_btn()获取用户最后点击的按钮的索引
lv_btnmatrix_get_btn_text()获取按钮的文本
lv_btnmatrix_has_btn_ctrl()获取按钮的状态
lv_btnmatrix_get_one_checked()判断按钮互斥是否开启

二、例程

// 按键矩阵的事件回调函数
static void btnmatrix_event_callback(lv_event_t * event)
{
    if (event == NULL)
    {
        printf("[%s:%d] event is NULL\n", __FUNCTION__, __LINE__);
        return ;
    }

    lv_event_code_t code = lv_event_get_code(event); // 获取当前event的code
    lv_obj_t * obj = lv_event_get_target(event);     // 获取当前事件的触发对象

    if (code == LV_EVENT_DRAW_PART_BEGIN) // 开始绘制一个区域的事件,这个事件的参数是lv_obj_draw_part_dsc_t *
    {
        lv_obj_draw_part_dsc_t * dsc = (lv_obj_draw_part_dsc_t *)lv_event_get_param(event);
        if (dsc != NULL)
        {
            switch (dsc->id)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                case 8:
                case 9:
                case 10:
                case 11:
                    {
                        if (lv_btnmatrix_get_selected_btn(obj) == dsc->id)
                        {
                            if (dsc->rect_dsc != NULL)
                            {
                                // 设置目标绘制区域的背景颜色
                                dsc->rect_dsc->bg_color = lv_color_hex(0xFF6008); // 橙色
                            }
                        }
                        else
                        {
                            if (dsc->rect_dsc != NULL)
                            {
                                dsc->rect_dsc->bg_color = lv_color_hex(0xF98E2D);
                            }
                        }

                        if (dsc->rect_dsc != NULL)
                        {
                            dsc->rect_dsc->radius = 5; // 设置目标绘制区域的圆角
                            dsc->rect_dsc->border_width = 0; // 设置目标绘制区域的边框宽度
                            dsc->rect_dsc->shadow_ofs_x = 0; // 在X方向的像素上设置阴影的偏移量
                            dsc->rect_dsc->shadow_ofs_y = 0; // 在Y方向的像素上设置阴影的偏移量
                         }

                         if (dsc->label_dsc != NULL)
                         {
                            dsc->label_dsc->color = lv_color_hex(0xFFFFFF);
                         }
                    }
                    break;

                default:
                    break;
            }
        }
    }
    else if(code == LV_EVENT_VALUE_CHANGED) // 当一个按钮被按下、释放或长按时
    {
        lv_obj_t * text_area = (lv_obj_t *)lv_event_get_user_data(event); // 获取事件的user_data
        uint16_t btn_id = lv_btnmatrix_get_selected_btn(obj);             // 获取当前选中的按键的id
        const char * txt = lv_btnmatrix_get_btn_text(obj, btn_id);        // 获取当前按键的文本

        if (txt != NULL)
        {
            if (strcmp(txt, LV_SYMBOL_BACKSPACE) == 0)
            {
                if (text_area != NULL)
                {
                    lv_textarea_del_char(text_area); // 删除文本框的字符
                }
            }
            else
            {
                if (text_area != NULL)
                {
                    lv_textarea_add_text(text_area, txt); // 文本框追加字符
                }
            }
        }
    }
}


void my_gui()
{
    static const char * btnm_map[] = {"1", "2", "3", "\n",
                                       "4", "5", "6", "\n",
                                       "7", "8", "9", "\n",
                                       ".", "0", LV_SYMBOL_BACKSPACE, ""};

    lv_obj_t * obj_text_area = lv_textarea_create(lv_scr_act()); // 创建文本框控件
    if (obj_text_area == NULL)
    {
        printf("[%s:%d] obj_text_area is NULL\n", __FUNCTION__, __LINE__);
        return ;
    }

    lv_textarea_set_one_line(obj_text_area, true);        // 将文本区域配置为一行
    lv_textarea_set_password_mode(obj_text_area, true);   // 将文本区域配置为密码模式
    lv_textarea_set_max_length(obj_text_area, 15);        // 设置文本区域可输入的字符长度最大值
    lv_obj_add_state(obj_text_area, LV_STATE_FOCUSED);    // 显示光标
    lv_obj_set_style_radius(obj_text_area, 5, 0);         // 设置样式的圆角弧度
    lv_obj_set_style_border_width(obj_text_area, 1, 0);   //设置边框宽度
    lv_obj_set_size(obj_text_area, 255, 40);              // 设置对象大小
    lv_obj_align(obj_text_area, LV_ALIGN_TOP_MID, 0, 50);

    lv_obj_t * obj_btnm = lv_btnmatrix_create(lv_scr_act()); // 创建一个按钮矩阵对象
    if (obj_btnm == NULL)
    {
        printf("[%s:%d] obj_btnm is NULL\n", __FUNCTION__, __LINE__);
        return ;
    }

    lv_btnmatrix_set_one_checked(obj_btnm, true);  // 启用“一次检查”功能,允许一次只检查一个按钮。
    lv_obj_set_size(obj_btnm, 260, 245);           // 设置控件大小
    lv_obj_align(obj_btnm, LV_ALIGN_CENTER, 0, 0);
    lv_obj_clear_flag(obj_btnm, LV_OBJ_FLAG_CLICK_FOCUSABLE); // 按钮按下的是时候焦点才聚集到该控件,确保按钮按下后焦点聚集到文本框
    lv_btnmatrix_set_map(obj_btnm, btnm_map);                 // 给按钮矩阵添加键盘映射

    int i = 0;
    for (i = 0; i < 12; i++)
    {
        lv_btnmatrix_set_btn_ctrl(obj_btnm, i, LV_BTNMATRIX_CTRL_NO_REPEAT); // 长按按钮时禁用重复
    }

    lv_obj_set_style_radius(obj_btnm, 0, 0);                                                       // 设置样式的圆角弧度
    lv_obj_set_style_border_width(obj_btnm, 0, 0);                                                 //设置边框宽度
    lv_obj_set_style_bg_color(obj_btnm, lv_color_hex(0xFFFFFF), 0);                                // 设置背景颜色
    lv_obj_set_style_bg_opa(obj_btnm, LV_OPA_0, 0);                                                // 设置样式背景的不透明度
    lv_obj_set_style_text_font(obj_btnm, &lv_font_montserrat_20, 0);                               //设置字体
    lv_obj_add_event_cb(obj_btnm, btnmatrix_event_callback, LV_EVENT_ALL, (void *)obj_text_area);  // 按钮矩阵添加事件回调函数
}
<think>好的,我现在需要解决用户在使用LVGL时遇到的lv_buttonmatrix_ctrl_t未定义的问题。用户之前提供的代码中使用了这个类型,但编译时出现错误,说明可能版本不兼容或者配置有误。 首先,我应该回忆LVGL的版本更新历史。因为用户提到lv_buttonmatrix_ctrl_t,而根据我的知识,LVGL在v8版本之后进行了一些重大的API更改。例如,按钮矩阵相关的控件可能从lv_btnm改为lv_buttonmatrix,同时相关类型和函数名称也有所变化。 接下来,用户提供的代码中有lv_buttonmatrix_ctrl_t,这可能是在较新的版本(如v8或更高)中引入的。如果用户使用的是旧版本(比如v7),那么这个类型确实不存在,导致未定义错误。因此,我需要确认用户当前的LVGL版本,并建议他们检查版本兼容性。 另外,用户可能在包含头文件时出现了问题。需要确认是否正确包含了lvgl/lvgl.h或者其他必要的头文件。有时候,如果头文件路径没有正确设置,也会导致类型未定义的问题。 然后,查看用户提供的引用内容,引用[1]中提到了lv_buttonmatrix的使用示例,而引用[2]和[3]涉及样式和标签设置,可能与当前问题关联不大。但用户可能在尝试设置按钮矩阵的样式时遇到了问题,需要确保样式设置符合当前版本的要求。 用户的问题还可能出在如何正确初始化和配置按钮矩阵。例如,在旧版本中,按钮矩阵控件类型可能是通过不同的方式定义的,比如使用位掩码或不同的枚举类型。如果用户从旧版本迁移到新版本,可能需要更新相关的代码结构。 此外,用户可能在编译时没有启用必要的模块。在LVGL中,某些功能需要通过配置文件lv_conf.h启用,比如LV_USE_BUTTONMATRIX。如果该宏未被定义,相关函数和类型将不可用,导致编译错误。 需要建议用户检查以下几点: 1. 确认LVGL版本,如果是v7或更早,需要升级到v8及以上,或者调整代码以适应旧版本。 2. 检查头文件是否包含正确,确保所有必要的头文件都被引入。 3. 验证lv_conf.h中的配置,确保启用了按钮矩阵相关的模块。 4. 根据版本调整代码,例如在v8及以上使用lv_buttonmatrix,而在旧版本中使用lv_btnm及相关类型。 最后,需要提供具体的代码示例,展示如何在不同版本中正确使用按钮矩阵,并处理控件类型和样式设置,帮助用户解决编译错误并成功实现英文输入文本框的功能。</think>### 问题分析:`lv_buttonmatrix_ctrl_t`未定义问题的解决方案 `lv_buttonmatrix_ctrl_t` 未定义通常由以下原因导致: --- #### 1. **LVGL版本不兼容** `lv_buttonmatrix_ctrl_t` 是 LVGL v8.0 及以上版本引入的类型[^1]。若您使用的是旧版本(如 v7.x),需调整代码: ```c // LVGL v7.x 中使用 lv_btnm_ctrl_t static lv_btnm_ctrl_t kb_9key_ctrl[] = { /* ... */ }; ``` --- #### 2. **头文件缺失** 确保正确包含核心头文件: ```c #include "lvgl/lvgl.h" // 必须包含核心库 ``` --- #### 3. **配置未启用按钮矩阵** 在 `lv_conf.h` 中检查以下配置项: ```c #define LV_USE_BUTTONMATRIX 1 // 启用按钮矩阵支持 ``` --- ### 分版本解决方案 #### **针对 LVGL v8.x+** 直接使用 `lv_buttonmatrix_ctrl_t` 并设置控制映射: ```c static lv_buttonmatrix_ctrl_t kb_9key_ctrl[] = { LV_BUTTONMATRIX_CTRL_CHECKED | 2, // 按钮占2列宽度 LV_BUTTONMATRIX_CTRL_HIDDEN, // 隐藏按钮 // ...其他按钮控制参数 }; // 设置控制映射 lv_buttonmatrix_set_ctrl_map(kb, LV_BUTTONMATRIX_CTRL_NONE, kb_9key_ctrl); ``` --- #### **针对 LVGL v7.x** 需改用旧版API: ```c // 使用 lv_btnm_ctrl_t 类型 static lv_btnm_ctrl_t kb_9key_ctrl[] = { LV_BTNM_CTRL_NONE, LV_BTNM_CTRL_HIDDEN, // ...其他参数 }; // 设置按钮控制参数 lv_btnm_set_ctrl_map(kb, kb_9key_ctrl); ``` --- ### 完整修复示例(v8.x) ```c // 1. 定义控制映射 static lv_buttonmatrix_ctrl_t ctrl_map[] = { LV_BUTTONMATRIX_CTRL_CHECKED | 2, // 按钮占2列 LV_BUTTONMATRIX_CTRL_HIDDEN, // 隐藏按钮 LV_BUTTONMATRIX_CTRL_CHECKED | 3, // 按钮占3列 // ...其他按钮配置 }; // 2. 创建按钮矩阵 lv_obj_t* kb = lv_buttonmatrix_create(parent); lv_buttonmatrix_set_map(kb, kb_9key_map); // 设置按钮文本 lv_buttonmatrix_set_ctrl_map(kb, ctrl_map); // 应用控制参数 // 3. 设置样式(参考用户提供的引用[1]) lv_obj_set_style_bg_color(kb, lv_color_hex(0xf0f0f0), LV_PART_MAIN); // 浅灰色背景 lv_obj_set_style_pad_row(kb, 10, LV_PART_MAIN); // 行间距10像素 ``` --- ### 关键点总结 1. **版本匹配**:确认 LVGL 版本(通过 `lv_version.h` 检查) 2. **API更新**:v8 起 `lv_btnm_*` 更名为 `lv_buttonmatrix_*`[^1] 3. **功能启用**:在 `lv_conf.h` 中确保按钮矩阵模块已启用 ![LVGL版本兼容性对比图](https://example.com/lvgl-version-compat.png)[^2] ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值