LVGL的List控件的触摸按键和实体按键的处理
在LVGL的List控件使用过程中,虽然通过触摸按键选择item,但是有些场景需要实体按键选取item,但是LVGL 的V8.3中没有像Emwin那样有函数选择list item的函数。LVGL中List引入了Group的概念,把列表项都添加到同一个group中。然后通过更改group的焦点达到选择list item的作用。
#include "LVGL/GUI_APP/lv_mainstart.h"
#include "lvgl.h"
#include <stdio.h>
#include "./BSP/KEY/key.h"
#define scr_act_width() lv_obj_get_width(lv_scr_act())
#define scr_act_height() lv_obj_get_height(lv_scr_act())
static lv_obj_t *list; /* 定义列表 */
static lv_obj_t *list_label; /* 定义标签 */
static const lv_font_t *font; /* 定义字体 */
extern lv_indev_t * indev_keypad;
lv_obj_t* BtnUp,*BtnDn, *label;
lv_group_t * group;
static void list_btn_event_cb(lv_event_t *e)
{
lv_obj_t *list_btn = lv_event_get_target(e);
lv_label_set_text(list_label, lv_list_get_btn_text(list, list_btn));
lv_obj_add_state(list_btn, LV_STATE_FOCUS_KEY);
}
下面是另外的触摸按键的UP/Down实现选择list item
由于没有找到重新聚焦group的函数,所以另辟蹊径,在up/down的事件回调函数中下发实体按键事件中。
static void event_btn_handler(lv_event_t *e)
{
lv_obj_t* targetObj = lv_event_get_target(e);
if (targetObj == BtnUp)
{
set_virl_key(KEY1_PRES);
}
if (targetObj == BtnDn)
{
set_virl_key(KEY0_PRES);
}
}
static void lv_example_list(void)
{
/* 根据屏幕大小设置字体 */
if (scr_act_width() <= 320)
{
font = &lv_font_montserrat_14;
}
else if (scr_act_width() <= 480)
{
font = &lv_font_montserrat_16;
}
else
{
font = &lv_font_montserrat_18;
}
/* 创建左侧矩形背景 */
lv_obj_t* obj_left = lv_obj_create(lv_scr_act()); /* 创建一个基础对象 */
lv_obj_set_width(obj_left, scr_act_width() * 0.7); /* 设置宽度 */
lv_obj_set_height(obj_left, scr_act_height() * 0.9); /* 设置高度 */
lv_obj_align(obj_left, LV_ALIGN_LEFT_MID, 5, 0); /* 设置位置 */
lv_obj_update_layout(obj_left); /* 手动更新物体的参数 */
/* 创建右侧矩形背景 */
lv_obj_t* obj_right = lv_obj_create(lv_scr_act()); /* 创建一个基础对象 */
lv_obj_set_width(obj_right, scr_act_width() - lv_obj_get_width(obj_left) - 15); /* 设置宽度 */
lv_obj_set_height(obj_right, lv_obj_get_height(obj_left)); /* 设置高度 */
lv_obj_align_to(obj_right, obj_left, LV_ALIGN_OUT_RIGHT_MID, 5, 0); /* 设置位置 */
lv_obj_update_layout(obj_right); /* 手动更新物体的参数 */
/* 显示当前选项的文本内容 */
list_label = lv_label_create(obj_right); /* 创建标签 */
lv_obj_set_width(list_label, lv_obj_get_width(obj_right) - 13); /* 设置标签的宽度 */
lv_obj_align(list_label, LV_ALIGN_TOP_MID, 0, 5); /* 设置标签位置 */
lv_obj_update_layout(list_label); /* 手动更新标签的参数 */
lv_obj_set_style_text_align(list_label, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); /* 设置标签文本对齐方式 */
lv_label_set_text(list_label, "New"); /* 设置标签文本 */
lv_obj_set_style_text_font(list_label, font, LV_PART_MAIN); /* 设置标签文本字体 */
//
BtnUp = lv_btn_create(obj_right);
lv_obj_set_size(BtnUp, 100, 50);
lv_obj_align(BtnUp, LV_ALIGN_TOP_RIGHT, -20, 100);
// lv_obj_add_flag( BtnUp, LV_OBJ_FLAG_CHECKABLE );
lv_obj_add_event_cb(BtnUp, event_btn_handler,LV_EVENT_CLICKED,NULL);
label = lv_label_create(BtnUp); //创建label
lv_label_set_text(label, "Up"); //设置label的字内容
lv_obj_center(label); //居中对象
BtnDn = lv_btn_create(obj_right);
lv_obj_set_size(BtnDn, 100, 50);
lv_obj_align(BtnDn, LV_ALIGN_BOTTOM_RIGHT, -20, -100);
// lv_obj_add_flag( BtnDn, LV_OBJ_FLAG_CHECKABLE );
lv_obj_add_event_cb(BtnDn, event_btn_handler, LV_EVENT_CLICKED, NULL);
label = lv_label_create(BtnDn); //创建label
lv_label_set_text(label, "Down"); //设置label的字内容
lv_obj_center(label);
///
/* 创建列表 */
list = lv_list_create(obj_left); /* 创建列表 */
lv_obj_set_width(list, lv_obj_get_width(obj_left) * 0.8); /* 设置列表宽度 */
lv_obj_set_height(list, lv_obj_get_height(obj_left) * 0.9); /* 设置列表高度 */
lv_obj_center(list); /* 设置列表的位置 */
lv_obj_set_style_text_font(list, font, LV_PART_MAIN); /* 设置字体 */
/* 为列表添加按钮 */
lv_obj_t* btn;
group = lv_group_create();
lv_indev_set_group(indev_keypad, group);
lv_list_add_text(list, "File"); /* 添加列表文本 */
btn = lv_list_add_btn(list, LV_SYMBOL_FILE, "New"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
label = lv_label_create(btn); //创建label
lv_label_set_text(label, "Down"); //设置label的字内容
lv_obj_center(label);
btn = lv_list_add_btn(list, LV_SYMBOL_DIRECTORY, "Open"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
btn = lv_list_add_btn(list, LV_SYMBOL_SAVE, "Save"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
btn = lv_list_add_btn(list, LV_SYMBOL_CLOSE, "Delete"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
btn = lv_list_add_btn(list, LV_SYMBOL_EDIT, "Edit"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
lv_list_add_text(list, "Connectivity"); /* 添加列表文本 */
btn = lv_list_add_btn(list, LV_SYMBOL_BLUETOOTH, "Bluetooth"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
btn = lv_list_add_btn(list, LV_SYMBOL_GPS, "Navigation"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
btn = lv_list_add_btn(list, LV_SYMBOL_USB, "USB"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
btn = lv_list_add_btn(list, LV_SYMBOL_BATTERY_FULL, "Battery"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
lv_list_add_text(list, "Exit"); /* 添加列表文本 */
btn = lv_list_add_btn(list, LV_SYMBOL_OK, "Apply"); /* 添加按钮 */
lv_group_add_obj(group, btn);
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
btn = lv_list_add_btn(list, LV_SYMBOL_CLOSE, "Close"); /* 添加按钮 */
lv_obj_add_event_cb(btn, list_btn_event_cb, LV_EVENT_CLICKED, NULL); /* 添加按钮回调 */
lv_group_add_obj(group, btn);
}
注意在添加实体按键group时需要注意变量的声明的先后顺序。在lv_port_indev_template.C中初始化实体按键后,不能立即添加组,除非需要被添加的obj已经声明赋值,否则就会错误死机。在例程中的
/* 接着你需要用 `lv_group_t * group = lv_group_create()` 来创建组
* 用 `lv_group_add_obj(group, obj)` 往组中添加物体
* 并将这个输入设备分配到组中,以导航到它:
* `lv_indev_set_group(indev_keypad, group);` */
当把注释取消后就是死机,无法找到原因,后来才发现,obj还没有声明赋值
void lv_mainstart(void)
{
lv_example_list();
}
在key.c中添加按键和虚拟触摸按键的处理。
void set_virl_key(uint8_t key)
{
vir_key = key;
}
uint8_t key_scan(uint8_t mode)
{
static uint8_t key_up = 1; /* 按键按松开标志 */
uint8_t keyval = 0;
if (mode) key_up = 1; /* 支持连按 */
if (key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1)) /* 按键松开标志为1, 且有任意一个按键按下了 */
{
delay_ms(10); /* 去抖动 */
key_up = 0;
if (KEY0 == 0) keyval = KEY0_PRES;
if (KEY1 == 0) keyval = KEY1_PRES;
if (KEY2 == 0) keyval = KEY2_PRES;
if (WK_UP == 1) keyval = WKUP_PRES;
}
else if(vir_key!=0)
{
keyval = vir_key;
vir_key = 0;
}
else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0) /* 没有任何按键按下, 标记按键松开 */
{
key_up = 1;
}
return keyval; /* 返回键值 */
}
相关文章:

LVGL的List控件的触摸按键和实体按键的处理
在LVGL的List控件使用过程中,虽然通过触摸按键选择item,但是有些场景需要实体按键选取item,但是LVGL 的V8.3中没有像Emwin那样有函数选择list item的函数。LVGL中List引入了Group的概念,把列表项都添加到同一个group中。然后通过更…...

数据结构 模拟实现二叉树(孩子表示法)
目录 一、二叉树的简单概念 (1)关于树的一些概念 (2)二叉树的一些概念及性质 定义二叉树的代码: 二、二叉树的方法实现 (1)createTree (2)preOrder (…...

Android14之解决刷机报错:Can not load Android system. Your data may be corrupt(一百七十七)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…...

二阶贝塞尔曲线生成弧线
概述 本文分享一个二阶贝塞尔曲线曲线生成弧线的算法。 效果 实现 1. 封装方法 class ArcLine {constructor(from, to, num 100) {this.from from;this.to to;this.num num;return this.getPointList();}getPointList() {const { from, to } thisconst ctrlPoint thi…...

FilterQuery过滤查询
ES中的查询操作分为两种:查询和过滤。查询即是之前提到的query查询,它默认会计算每个返回文档的得分,然后根据得分排序。而过滤只会筛选出符合条件的文档,并不计算得分,并且可以缓冲记录。所以我们在大范围筛选数据时&…...

java多线程(并发)夯实之路-线程池深入浅出
线程池 Thread Pool:线程池,存放可以重复使用的线程(消费者) Blocking Queue:阻塞队列,存放等待执行的任务(生产者) poll方法(有时限地获取任务)相对take注…...
数据库-列的类型-字符串char类型
char 和 varchar 类型 char 类型懂得都懂就是固定的字符串类型 char (maxLen) 例如 char(5) 这个长度为5 但插入数据‘a’时 是5 插入abc 也是5 即使插满固定 就像C/C语言里 char 字符数组一样 char str[64]; maxLen255 哈哈最多有255个字符多了我认为你是错误 varchar…...

大话 JavaScript(Speaking JavaScript):第二十一章到第二十五章
第二十一章:数学 原文:21. Math 译者:飞龙 协议:CC BY-NC-SA 4.0 Math对象用作多个数学函数的命名空间。本章提供了一个概述。 数学属性 Math的属性如下: Math.E 欧拉常数(e) Math.LN2 2 …...

ICMP协议
ICMP协议是网络层协议, 利用ICMP协议可以实现网络中监听服务和拒绝服务,如 ICMP重定向的攻击。 一、ICMP基本概念 1、ICMP协议 ICMP是Internet控制报文协议,用于在IP主机、路由器之间传递控制消息,控制消息指网络通不通、主机是…...

环信服务端下载消息文件---菜鸟教程
前言 在服务端,下载消息文件是一个重要的功能。它允许您从服务器端获取并保存聊天消息、文件等数据,以便在本地进行进一步的处理和分析。本指南将指导您完成环信服务端下载消息文件的步骤。 环信服务端下载消息文件是指在环信服务端上,通过调…...

创建型模式 | 建造者模式
一、建造者模式 1、原理 建造者模式又叫生成器模式,是一种对象的构建模式。它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。创建者模式是一步一步创建一个复杂的对象…...
MVC设计模式
在当今的软件开发领域,MVC(Model-View-Controller)设计模式已经成为了一种广泛使用的架构模式。它为应用程序提供了一种结构化的方法,将数据、用户界面和业务逻辑分开,从而使得应用程序更易于维护、扩展和重用。 一、…...
WSL (2103) ERROR: CreateProcessEntryCommon:493: chdir 错误解决
[TOC](WSL (2103) ERROR: CreateProcessEntryCommon:493: chdir 错误解决) 1. 错误信息 <3>WSL (2103) ERROR: CreateProcessEntryCommon:493: chdir(/mnt/d/Program Files/PowerShell/7) failed 52. 解决方法 wsl --shutdownwslrefer: https://github.com/microsoft/…...

【二、自动化测试】为什么要做自动化测试?哪种项目适合做自动化?
自动化测试是一种软件测试方法,通过编写和使用自动化脚本和工具,以自动执行测试用例并生成结果。 自动化旨在替代手动测试过程,提高测试效率和准确性。 自动化测试可以覆盖多种测试类型,包括功能测试、性能测试、安全测试等&…...
用ChatGPT来造一个ChatGPT:计算机领域智能问答系统实践(2)
在PHP语言中,你可以使用MySQL数据库来存储知识库,并使用PHP来实现系统的逻辑。以下是一个简单的示例: 创建数据库表: 首先,创建一个名为 computer_knowledge 的表来存储计算机知识。可以使用以下SQL语句:…...

Ubuntu开机自动挂载硬盘
前言: 因为我的电脑是WIN10 Ubuntu18.04双系统,且两个系统都装在C盘上,而D盘作为数据和代码存储盘,经常会开机就被访问,例如上一次关机前用VS Code访问D盘代码,然后下一次开机的时候打开VSCode发现打不开…...
vue3基础:单文件组件介绍
介绍 Vue 的单文件组件 (即 *.vue 文件,简称 SFC,全称是single file component) 是一种特殊的文件格式,使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中。下面是一个单文件组件的示例: <script> export def…...

OCR字符识别:开始批量识别身份证信息
身份证信息批量识别OCR是一项解决方案,它能够将身份证照片打包成zip格式或通过URL地址进行提交,并能够识别照片中的文本信息。最终,用户可以将识别结果生成为excel文件进行下载。 API接口功能: 1. 批量识别:支持将多…...

php多小区智慧物业管理系统源码带文字安装教程
多小区智慧物业管理系统源码带文字安装教程 运行环境 服务器宝塔面板 PHP 7.0 Mysql 5.5及以上版本 Linux Centos7以上 统计分析以小区为单位,统计如下数据:小区总栋数、小区总户数、小区总人数、 小区租户数量、小区每月收费金额统计、小区车位统计、小…...

解决虚拟机的网络图标不见之问题
在WIN11中,启动虚拟机后,发现网络图标不见了,见下图: 1、打开虚拟机终端 输入“sudo server network-manager stop”,停止网络管理器 输入“cd /回车” , 切换到根目录 输入“cd var回车” ,…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...