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回车” ,…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...