LVGL4种输入设备详解(触摸、键盘、实体按键、编码器)

news/2025/2/9 8:20:51 标签: stm32, LVGL

lvgl有触摸、键盘、实体按键、编码器四种输入设备

先来分析一下这四种输入设备有什么区别

(1)LV_INDEV_TYPE_POINTER

主要用于触摸屏

用到哪个输入设备保留哪个其他的也是,保留触摸屏输入的任务注册,其它几种种输入任务的注册,注释掉

添加自己触摸函数

(2)LV_INDEV_TYPE_KEYPAD

要使用键盘或者编码器必须将创建个组,具体参考编码器

  • 必须创建一个对象组:并且必须使用lv_group_t * g = lv_group_create()

  • 将对象添加到组中lv_group_add_obj(g, obj)

  • 创建的组必须分配给输入设备:lv_indev_set_group(my_indev, g)

它的输入处理函数keypad_read中,就根据输入的不同按键(LV_KEY_UP,LV_KEY_DOWN,LV_KEY_LEFT,LV_KEY_RIGHT,LV_KEY_ENTER等)对Keypad所绑定的group内的组件进行操作,如焦点的切换、进度条的滑动。比如说对于一个Table来说,里面的数据很多,有一个滑动条,这个滑动条就受LV_KEY_UP和LV_KEY_DOWN键控制;而对于一个Tabview来说,Tab的切换则是受LV_KEY_LEFT和LV_KEY_RIGHT键控制。而Group中的组件之间的焦点切换则是通过LV_KEY_PREV和LV_KEY_NEXT键切换。

(3)LV_INDEV_TYPE_BUTTON

就是一个实体按键,适用于GUI中焦点永远在某一个组件上的情况。按下物理按键就代表GUI中的按键按下。

修改成按钮实际坐标

添加按键按下函数

(4)LV_INDEV_TYPE_ENCODER

使用编码器,您可以执行以下操作:

  1. 按下它的按钮

  2. 长按其按钮

  3. 左转

  4. 右转

简而言之,Encoder 输入设备的工作原理如下:

  • 通过转动编码器,您可以专注于下一个/上一个对象。

  • 当您在简单对象(如按钮)上按下编码器时,它将被单击。

  • 如果您在复杂对象(如列表、消息框等)上按下编码器,该对象将进入编辑模式,您可以通过转动编码器在对象内导航。

  • 要退出编辑模式,请长按按钮。

组的创建

从注释可以知道要使用键盘或者编码器必须将创建个组

可以使用自定义组和默认组

自定义组创建过程

  • 必须创建一个对象组:并且必须使用lv_group_t * g = lv_group_create()

  • 将对象添加到组中lv_group_add_obj(g, obj)

  • 创建的组必须分配给输入设备:lv_indev_set_group(my_indev, g)

以滑块为例

红色为聚焦时的状态,这个状态左旋右旋可以修改滑块值和检测按键按下

在lv_port.c中使用编码器

可以在用到的地方创建自定义组,那样可以不用声明组,但要声明输入设备

extern lv_indev_t * indev_encoder;
static lv_obj_t * slider1_label;
static lv_obj_t * slider2_label;
static lv_obj_t * slider3_label;
static lv_obj_t * slider4_label;

static void slider_event_cb(lv_event_t * e)
{
    lv_obj_t * slider = lv_event_get_target(e);
    int value = lv_slider_get_value(slider);
    char buf[8];
    lv_snprintf(buf, sizeof(buf), "%d%%", value);

    // 根据滑块更新对应的标签
    if (slider == lv_obj_get_child(lv_scr_act(), 0)) {
        lv_label_set_text(slider1_label, buf);
    } else if (slider == lv_obj_get_child(lv_scr_act(), 2)) {
        lv_label_set_text(slider2_label, buf);
    } else if (slider == lv_obj_get_child(lv_scr_act(), 4)) {
        lv_label_set_text(slider3_label, buf);
    } else if (slider == lv_obj_get_child(lv_scr_act(), 6)) {
        lv_label_set_text(slider4_label, buf);
    }
}

void lv_example_slider_1(void)
{
    /* 创建第一个滑块 */
    lv_obj_t * slider1 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider1, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider1, LV_ALIGN_TOP_MID, 0, 20);  // 将第一个滑块对齐到顶部中间
    lv_obj_add_event_cb(slider1, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第一个滑块的标签 */
    slider1_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider1_label, "0%");
    lv_obj_align_to(slider1_label, slider1, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建第二个滑块 */
    lv_obj_t * slider2 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider2, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider2, LV_ALIGN_TOP_MID, 0, 80);  // 将第二个滑块对齐到第一个滑块下方
    lv_obj_add_event_cb(slider2, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第二个滑块的标签 */
    slider2_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider2_label, "0%");
    lv_obj_align_to(slider2_label, slider2, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建第三个滑块 */
    lv_obj_t * slider3 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider3, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider3, LV_ALIGN_TOP_MID, 0, 140);  // 将第三个滑块对齐到第二个滑块下方
    lv_obj_add_event_cb(slider3, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第三个滑块的标签 */
    slider3_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider3_label, "0%");
    lv_obj_align_to(slider3_label, slider3, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建第四个滑块 */
    lv_obj_t * slider4 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider4, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider4, LV_ALIGN_TOP_MID, 0, 200);  // 将第四个滑块对齐到第三个滑块下方
    lv_obj_add_event_cb(slider4, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第四个滑块的标签 */
    slider4_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider4_label, "0%");
    lv_obj_align_to(slider4_label, slider4, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建 group */
    lv_group_t * group = lv_group_create();

    // 将滑块添加到组中
    lv_group_add_obj(group, slider1);
    lv_group_add_obj(group, slider2);
    lv_group_add_obj(group, slider3);
    lv_group_add_obj(group, slider4);

    // 将 group 绑定到输入设备(假设 indev_encoder 已初始化)
    lv_indev_set_group(indev_encoder, group);
}

使用默认组

对于一些比较复杂的组件使用默认组可以很方便

  • 在lvgl中有些部件,在创建的时候加入到默认组中,但是默认组变量lvgl并没有帮助我们初始化好,我们需要在创建部件之前初始化好才能使用默认组,这个自定义组一样不同的是对于创建时添加:

lv_group_t * g = lv_group_create(); // 创建一个组
lv_group_set_default(g);             // 设置为默认组

之后在需要的地方获取和绑定默认组

/* 获取group */
lv_group_t * group = lv_group_get_default();

// 将 group 绑定到输入设备
lv_indev_set_group(indev_encoder, group);

以tabview为例

可以在这里创建默认组

extern lv_indev_t * indev_encoder;
static lv_obj_t * slider1_label;
static lv_obj_t * slider2_label;
static lv_obj_t * slider3_label;
static lv_obj_t * slider4_label;

static void slider_event_cb(lv_event_t * e)
{
    lv_obj_t * slider = lv_event_get_target(e);
    int value = lv_slider_get_value(slider);
    char buf[8];
    lv_snprintf(buf, sizeof(buf), "%d%%", value);

    // 根据滑块更新对应的标签
    if (slider == lv_obj_get_child(lv_scr_act(), 0)) {
        lv_label_set_text(slider1_label, buf);
    } else if (slider == lv_obj_get_child(lv_scr_act(), 2)) {
        lv_label_set_text(slider2_label, buf);
    } else if (slider == lv_obj_get_child(lv_scr_act(), 4)) {
        lv_label_set_text(slider3_label, buf);
    } else if (slider == lv_obj_get_child(lv_scr_act(), 6)) {
        lv_label_set_text(slider4_label, buf);
    }
}

void lv_example_slider_1(void)
{
    /* 创建第一个滑块 */
    lv_obj_t * slider1 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider1, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider1, LV_ALIGN_TOP_MID, 0, 20);  // 将第一个滑块对齐到顶部中间
    lv_obj_add_event_cb(slider1, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第一个滑块的标签 */
    slider1_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider1_label, "0%");
    lv_obj_align_to(slider1_label, slider1, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建第二个滑块 */
    lv_obj_t * slider2 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider2, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider2, LV_ALIGN_TOP_MID, 0, 80);  // 将第二个滑块对齐到第一个滑块下方
    lv_obj_add_event_cb(slider2, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第二个滑块的标签 */
    slider2_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider2_label, "0%");
    lv_obj_align_to(slider2_label, slider2, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建第三个滑块 */
    lv_obj_t * slider3 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider3, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider3, LV_ALIGN_TOP_MID, 0, 140);  // 将第三个滑块对齐到第二个滑块下方
    lv_obj_add_event_cb(slider3, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第三个滑块的标签 */
    slider3_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider3_label, "0%");
    lv_obj_align_to(slider3_label, slider3, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建第四个滑块 */
    lv_obj_t * slider4 = lv_slider_create(lv_scr_act());
    lv_obj_set_size(slider4, 200, 10);  // 设置滑块的大小
    lv_obj_align(slider4, LV_ALIGN_TOP_MID, 0, 200);  // 将第四个滑块对齐到第三个滑块下方
    lv_obj_add_event_cb(slider4, slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL);

    /* 创建第四个滑块的标签 */
    slider4_label = lv_label_create(lv_scr_act());
    lv_label_set_text(slider4_label, "0%");
    lv_obj_align_to(slider4_label, slider4, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

    /* 创建 group */
    lv_group_t * group = lv_group_create();

    // 将滑块添加到组中
    lv_group_add_obj(group, slider1);
    lv_group_add_obj(group, slider2);
    lv_group_add_obj(group, slider3);
    lv_group_add_obj(group, slider4);

    // 将 group 绑定到输入设备(假设 indev_encoder 已初始化)
    lv_indev_set_group(indev_encoder, group);
}

实现获取编码器增量值和判断编码器是否按下

参考官方文档

实现获取编码器增量值和判断编码器是否按下 


http://www.niftyadmin.cn/n/5845824.html

相关文章

Python的秘密基地--[章节13] Python 数据分析与可视化

第13章:Python 数据分析与可视化 在大数据时代,数据分析与可视化是至关重要的技能。Python 提供了多个强大的库,如 NumPy、Pandas、Matplotlib 和 Seaborn,用于数据处理、分析和可视化。本章将介绍如何使用 Python 进行数据分析&…

FPGA高端项目:图像采集+UltraScale GTH光编码+UDP图传架构,高速接口转网络视频传输,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的 GT 高速接口解决方案我这里已有的以太网方案 3、工程详细设计方案工程设计原理框图输入Sensor之-->OV5640摄像头动态彩条视频数据组包基于UltraScale…

SpringBoot3与MyBatis-Plus

4.1 介绍 MyBatis-Plus(简称 MP)是一个基于 MyBatis 的增强工具,提供通用 CRUD 操作、代码生成器、条件构造器、分页插件等功能,简化开发流程,提升效率。 4.2 特点 无侵入:只做增强不做修改,与…

ssti学习笔记(服务器端模板注入)

目录 一,ssti是什么 二,原理 所谓模板引擎(三列,可滑动查看) 三,漏洞复现 1,如何判断其所属的模板引擎? 2,判断清楚后开始注入 (1)Jinja2&a…

MySQL第五次作业

根据图片内容完成作业 1.建表 (1)建立两个表:goods(商品表)、orders(订单表) mysql> create table goods( -> gid char(8) primary key, -> name varchar(10), -> price decimal(8,2), -> num int); mysql> create t…

Oracle Database Free版本的各项许可限制

Oracle Database Free版本的各项许可限制: 限制类型描述具体限制可能的错误信息CPU限制Oracle Database Free自动限制最多使用两个CPU核心进行处理最多2个CPU核心无特定错误信息,但性能受限安装和运行时限制每个逻辑环境中只能安装一次Oracle Database …

瑞芯微 Rockchip 系列 RK3588 主流深度学习框架模型转成 rknn 模型教程

前言 在瑞芯微 Rockchip 芯片上进行 NPU 推理,需要先将模型文件转换成 rknn 模型文件,才能执行各种推理任务。本文将介绍如何安装各种工具,并最终实现将各种深度学习框架的模型文件转换成 rknn 文件。 本教程不仅适合 RK3588 平台&#xff…

WebStorm设置Vue Component模板

下载vue.js插件 下面有模板样例 Composition API:这是 Vue 3 的一项新特性,允许通过 setup 函数来组织组件逻辑。Options API:这是 Vue 2 和 Vue 3 都支持的传统方式,通过定义组件的 data、methods、computed 等来组织逻辑。 Comp…