09. 按键矩阵部件

一、按钮矩阵部件

  在 LVGL 中,按钮矩阵部件相当于一系列伪按钮的集合,它按一定的序列来排布这些按钮。这些伪按钮并不是真正的按钮部件(lv_btn),它们只是具有按钮外观的图形,但这些图形具有和按钮一样的点击效果。伪按钮所占的内存非常小,一个伪按钮大概占用 8 个字节,而一个普通按钮部件所占的内存大概为 100 ~ 150 个字节。

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

按钮矩阵组成部分

  LVGL 官方提供了一些与按钮矩阵部件相关 API。

#define lv_btnmatrix_create                  lv_buttonmatrix_create
lv_obj_t * lv_buttonmatrix_create(lv_obj_t * parent);                           // 创建按钮矩阵部件

#define lv_btnmatrix_set_map                 lv_buttonmatrix_set_map
void lv_buttonmatrix_set_map(lv_obj_t * obj, const char * map[]);               // 设置多个按钮属性

#define lv_btnmatrix_set_selected_btn        lv_buttonmatrix_set_selected_button
void lv_buttonmatrix_set_selected_button(lv_obj_t * obj, uint32_t btn_id);      // 设置选中的按钮

#define lv_btnmatrix_set_btn_ctrl            lv_buttonmatrix_set_button_ctrl
void lv_buttonmatrix_set_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl);     // 设置一个按钮的属性

#define lv_btnmatrix_clear_btn_ctrl          lv_buttonmatrix_clear_button_ctrl
void lv_buttonmatrix_clear_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl);   // 清除某个按钮的属性

#define lv_btnmatrix_set_btn_ctrl_all        lv_buttonmatrix_set_button_ctrl_all
void lv_buttonmatrix_set_button_ctrl_all(lv_obj_t * obj, lv_buttonmatrix_ctrl_t ctrl);                  // 设置所有按钮的属性

#define lv_btnmatrix_has_button_ctrl         lv_buttonmatrix_has_button_ctrl
bool lv_buttonmatrix_has_button_ctrl(lv_obj_t * obj, uint32_t btn_id, lv_buttonmatrix_ctrl_t ctrl);     // 获取按钮的状态

#define lv_btnmatrix_set_btn_width           lv_buttonmatrix_set_button_width
void lv_buttonmatrix_set_button_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width);                 // 设置单个按钮的相对宽度

#define lv_btnmatrix_set_one_checked         lv_buttonmatrix_set_one_checked
void lv_buttonmatrix_set_one_checked(lv_obj_t * obj, bool en);                  // 设置按钮互斥

#define lv_btnmatrix_get_one_checked         lv_buttonmatrix_get_one_checked
bool lv_buttonmatrix_get_one_checked(const lv_obj_t * obj);                     // 判断按钮互斥是否开启

#define lv_btnmatrix_get_map                 lv_buttonmatrix_get_map
const char ** lv_buttonmatrix_get_map(const lv_obj_t * obj);                    // 获取按钮相关映射

#define lv_btnmatrix_get_selected_btn        lv_buttonmatrix_get_selected_button
uint32_t lv_buttonmatrix_get_selected_button(const lv_obj_t * obj);             // 获取用户最后点击的按钮的索引

#define lv_btnmatrix_get_btn_text            lv_buttonmatrix_get_button_text
const char * lv_buttonmatrix_get_button_text(const lv_obj_t * obj, uint32_t btn_id);                    // 获取按钮的文本

  我们可以使用 lv_btnmatrix_create() 函数 创建按钮矩阵部件

/**
 * @brief 创建按钮矩阵部件
 * 
 * @param parent 指向父部件的指针
 * @return lv_obj_t* 指向按键矩阵部件的指针
 */
lv_obj_t * lv_btnmatrix_create(lv_obj_t * parent);

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

/**
 * @brief 设置多个按钮属性
 * 
 * @param obj 指向按钮矩阵对象的指针
 * @param map 指针一个字符串数组,最后一个元素必须为空,可以使用 "\n" 换行
 */
void lv_btnmatrix_set_map(lv_obj_t * obj, const char * map[]);

该数组最后一个元素必须为空。

如果用户需要让按钮换行,可以在字符串数组中使用换行符 "\n"。

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

/**
 * @brief 设置单个按钮的相对宽度
 * 
 * @param obj 指向按钮矩阵部件的指针
 * @param btn_id 按钮索引
 * @param width 相对宽度,可选值的范围:1~7
 */
void lv_btnmatrix_set_btn_width(lv_obj_t * obj, uint32_t btn_id, uint32_t width);

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

#define LV_BTNMATRIX_CTRL_HIDDEN       LV_BUTTONMATRIX_CTRL_HIDDEN              // 按钮隐藏
#define LV_BTNMATRIX_CTRL_NO_REPEAT    LV_BUTTONMATRIX_CTRL_NO_REPEAT           // 禁用长按
#define LV_BTNMATRIX_CTRL_DISABLED     LV_BUTTONMATRIX_CTRL_DISABLED            // 禁用按钮
#define LV_BTNMATRIX_CTRL_CHECKABLE    LV_BUTTONMATRIX_CTRL_CHECKABLE           // 启用按钮状态切换
#define LV_BTNMATRIX_CTRL_CHECKED      LV_BUTTONMATRIX_CTRL_CHECKED             // 选中按钮
#define LV_BTNMATRIX_CTRL_CLICK_TRIG   LV_BUTTONMATRIX_CTRL_CLICK_TRIG          // 启用:在点击时发送 LV_EVENT_VALUE_CHANGE;禁用:在按下时发送 LV_EVENT_VALUE_CHANGE
#define LV_BTNMATRIX_CTRL_POPOVER      LV_BUTTONMATRIX_CTRL_POPOVER             // 此按钮时在弹出窗口中显示按钮标签
#define LV_BTNMATRIX_CTRL_CUSTOM_1     LV_BUTTONMATRIX_CTRL_CUSTOM_1            // 可自定义使用的标志
#define LV_BTNMATRIX_CTRL_CUSTOM_2     LV_BUTTONMATRIX_CTRL_CUSTOM_2            // 可自定义使用的标志

  按钮互斥 是指在某一时刻,只允许有一个按钮处于按下不弹起状态(被选中),当我们选中一个按钮之后,其他的按钮将会自动清除选中属性。用户可以调用 lv_btnmatrix_set_one_checked() 函数,开启按钮互斥功能。

/**
 * @brief 设置按钮互斥
 * 
 * @param obj 指向按钮矩阵部件的指针
 * @param en 是否启用按钮互斥功能
 */
void lv_btnmatrix_set_one_checked(lv_obj_t * obj, bool en);

二、实验例程

#include "lvgl.h"
#include "lv_port_disp_template.h"
#include "lv_port_indev_template.h"

lv_obj_t *label;

int main(void)
{
    const char *map[] = {"Sakura", "\n", "Akame", "Kurome", ""};

    HAL_Init();
    System_Clock_Init(8, 336, 2, 7);
    Delay_Init(168);

    SPI_Simulate_Init();
    // SRAM_Init();
    TIM_Base_Init(&g_tim6_handle, TIM6, 83, 999);
    __HAL_TIM_CLEAR_IT(&g_tim6_handle, TIM_IT_UPDATE);                          // 清除更新中断标志位
    HAL_TIM_Base_Start_IT(&g_tim6_handle);                                      // 使能更新中断,并启动计数器

    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();

    // 测试代码
    label = lv_label_create(lv_scr_act());                                      // 创建标签部件
    lv_obj_set_align(label, LV_ALIGN_TOP_MID);                                  // 设置标签部件考上居中对齐
    lv_obj_set_style_text_font(label, &lv_font_montserrat_30, LV_PART_MAIN);    // 设置标签部件的字体样式
    lv_label_set_text(label, "buttonMatrix test");                              // 设置标签部件的文本

    lv_obj_t *buttonMatrix = lv_btnmatrix_create(lv_scr_act());                 // 创建按钮矩阵部件

    lv_obj_center(buttonMatrix);                                                // 将按钮矩阵部件居中

    lv_btnmatrix_set_map(buttonMatrix, map);                                    // 设置按钮矩阵部件的映射表
    lv_btnmatrix_set_btn_width(buttonMatrix, 1, 2);                             // 设置按钮的相对宽度
    lv_btnmatrix_set_btn_ctrl_all(buttonMatrix, LV_BTNMATRIX_CTRL_CHECKABLE);   // 启用按钮状态切换
    lv_btnmatrix_set_one_checked(buttonMatrix, true);                           // 设置按钮单次选中

    lv_obj_add_event_cb(buttonMatrix, buttonMatrix_event_cb, LV_EVENT_CLICKED, NULL);

    while (1)
    {
        lv_timer_handler();
        Delay_ms(5);
    }
  
    return 0;
}
void buttonMatrix_event_cb(lv_event_t *e)
{
    lv_event_code_t code = lv_event_get_code(e);                                // 获取事件的事发类型
    lv_obj_t *target = lv_event_get_target(e);                                  // 获取事件的触发源
    uint8_t id = 0;
    const char *text;

    if (code == LV_EVENT_CLICKED)
    {
        id = lv_btnmatrix_get_selected_btn(target);                             // 获取按键的索引
        text = lv_btnmatrix_get_btn_text(target, id);                           // 获取按键的文本
        lv_label_set_text(label, text);
    }
}
posted @ 2024-06-03 20:51  星光映梦  阅读(57)  评论(0编辑  收藏  举报