我在前几章移植 lvgl 到linux上时讲过注册鼠标驱动部分,那时候使用的时默认提供的驱动,支持的鼠标功能很少,只有左键点击,那时候我提过我们可以修改驱动使其支持,下面是具体的实现。

        

         

        看上面代码,我们当时是直接用的默认的模板驱动,而下面则是我专门针对鼠标写的一个驱动。这里的 evdev_fd 是输入设备的文件描述符,也就是说lvgl默认提供一种设备,所以大家如果有多个输入设备的话需要再准备几个独立的文件描述符以及驱动。这里官方提供的默认驱动是支持多种输入设备的(比如鼠标,键盘,触摸屏),所以看这代码比较多。而我们在这里专门针对鼠标进行开发驱动,使其支持我们要的效果。
首先我们打开 lv_hal_indev.h 这个文件,我们需要加上一些额外的定义,如图:

        然后我们再打开lv_api_map.h,如下图添加,遵循 lvgl 的风格

        然后我们再 evdev.c 文件中添加鼠标驱动函数,位置大家可自行添加,我这里添加到 evdev_read 的下边,代码部分如下,不是很难,重点是理解输入设备的一些参数意义,这里使用的 struct input_event 这个结构体,大部分鼠标都支持,如果你的鼠标是自定义的格式,那么需要自行看手册进行转化。

void mouse_event_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{struct input_event in;while(read(evdev_fd, &in, sizeof(struct input_event)) > 0) {/* 发生鼠标移动,记录其位置 */if(in.type == EV_REL) {if(in.code == REL_X) evdev_root_x += in.value;else if(in.code == REL_Y) evdev_root_y += in.value;else if(in.code == REL_WHEEL) data->enc_diff = in.value;    /* 将鼠标滑轮滚动转化为LVGL的编码器事件 */}/* 按键事件(包括鼠标) */else if(in.type == EV_KEY) {switch(in.code) {/* 左键 */case BTN_LEFT:if(in.value == 0)evdev_button = LV_INDEV_STATE_REL;else if(in.value == 1)evdev_button = LV_INDEV_STATE_PR;break;/* 右键 */case BTN_RIGHT:if(in.value == 0)evdev_button = LV_INDEV_STATE_RIGHT_REL;else if(in.value == 1)evdev_button = LV_INDEV_STATE_RIGHT_PR;break;/* 中键 */case BTN_MIDDLE:if(in.value == 0)evdev_button = LV_INDEV_STATE_MIDDLE_REL;else if(in.value == 1)evdev_button = LV_INDEV_STATE_MIDDLE_PR;break;default:break;}}/* 保存值 */data->point.x = evdev_root_x;data->point.y = evdev_root_y;data->state = evdev_button;/* 边界检测 */if(data->point.x < 0) data->point.x = 0;if(data->point.y < 0) data->point.y = 0;if(data->point.x > drv->disp->driver->hor_res) data->point.x = drv->disp->driver->hor_res;if(data->point.y > drv->disp->driver->ver_res) data->point.y = drv->disp->driver->ver_res;}
}

        下面我们在修改一下sdl模拟器的驱动,我们再模拟器上进行测试,下面红框是修改部分

        接下来我们看一下 lv_indev.c 输入设备核心代码,下面的这个函数是输入设备的核心函数,是 30ms 的定时函数,这个定时时间由 LV_INDEV_DEF_READ_PERIOD 这个宏决定的。而红框部分则是对输入设备的数据结构体的初始化值,最后调用我们上面写的驱动函数将读取的鼠标值转化为 lvgl 数据结构体。

        而在往下看则是对不同输入设备的具体处理,我们重点关注红框部分的鼠标处理函数

        这个就是处理鼠标的处理函数,先是对坐标进行了处理,由于我们判断过了这里就不再重复判断了,而最下面的判断是用于鼠标发生了移动重新绘制鼠标的位置的作用。

        再往下面部分就是对事件的判断从而返给对象,红框部分是新增的使其支持我们自定义的功能。这里需要强调一下,indev_proc_press 这个函数是初次按下执行一系列操作,比如LV_EVENT_PRESSED (第一下按下时调用)、 LV_EVENT_PRESSING (还在按)、LV_EVENT_PRESS_LOST (目标丢失)、LV_EVENT_LONG_PRESSED(长按)、LV_EVENT_LONG_PRESSED_REPEAT(仍长按)这些重要的中间过,对于右键来说是大部分是不需要的,但是我们要保持完整性且目标丢失我们也需要,所以右键也去调用了这个函数

        对 indev_proc_press 这个处理按下(一种过程,并非结束)的函数进行处理,重点展示修改的代码,下面“时间”打错字了,是事件

        然后就是 indev_proc_release 这个函数,主要是 LV_EVENT_RELEASED(释放)、LV_EVENT_SHORT_CLICKED(短按)、LV_EVENT_CLICKED(点击)这些事件,这里右键是不需要的,所以加个判断,同时要加上右键事件以及双击事件的发送,这里改动比较多,大家需注意:

        到这里成功实现了双击、右键、以及鼠标滑轮功能,我们创建个box简单测试一下

static void event_cb(lv_event_t *e)
{lv_event_code_t code = lv_event_get_code(e);if(code == LV_EVENT_CLICKED) printf("左键点击事件\n");else if(code == LV_EVENT_RIGHT_CLICKED) printf("右键点击事件\n");else if(code == LV_EVENT_DOUBLE_CLICKED) printf("左键双击事件\n");else if(code == LV_EVENT_MOUSE_WHEEL_UP) printf("鼠标滑轮上滑事件\n");else if(code == LV_EVENT_MOUSE_WHEEL_DOWN) printf("鼠标滑轮下滑事件\n");
}void page_create(void)
{lv_obj_t* box = lv_obj_create(lv_scr_act());lv_obj_set_size(box, 60, 60);lv_obj_add_event_cb(box, event_cb, LV_EVENT_ALL, NULL);
}

        下面是输出打印

        到这里就完结了,其实 lvgl 的知识听庞大的,需要大家慢慢挖索,我不建议大家一股脑的看源代码,而是有需求用到了再去查看,探索是枯燥的,但是忍受下来你会发现其实就是那么简单,我这里只是以三种事件为例子,其实还有鼠标悬停提示这种事件,其实也不难,需要大家好好摸索,最后谢谢大家的观看。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96571.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96571.shtml
英文地址,请注明出处:http://en.pswp.cn/web/96571.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot 中单独一个类中运行main方法报错:找不到或无法加载主类

1. 报错SpringBoot项目&#xff0c;在随机某个类使用main方法&#xff0c;点击运行/调试报错错误: 找不到或无法加载主类 com.central.workorder.config.PropertyEncrypt 原因: java.lang.ClassNotFoundException: com.central.workorder.config.PropertyEncrypt2. 原因缩短命令…

React 核心 Hook 与冷门技巧:useReducer、useEffect、useRef 及 is 属性全解析

&#x1f4da; 前言React 的函数组件 Hooks 模式已经成为现代前端开发的主流。相比类组件&#xff0c;Hooks 让状态管理和副作用处理更加简洁和可复用。但在实际开发中&#xff0c;除了常用的 useState 和 useEffect&#xff0c;还有很多“进阶武器”值得我们掌握。本文将深入…

通义灵码产品演示: 数据库设计与数据分析

作者&#xff1a;了哥 演示主题&#xff1a;AI 进行数据库设计以及做数据分析 演示目的 演示通义灵码对于数据库的设计能力以及数据分析能力。 演示准备 准备数据库&#xff0c;这里为了简单实用 sqlite3 brew install sqlite3使用 vscode&#xff0c;同时安装好通义灵码的插件…

MySQL主从同步参数调优案例

#作者&#xff1a;stackofumbrella 文章目录一、前言二、故障概述2.1 基础信息2.2 故障现象描述三、故障诊断分析3.1 排查过程3.2 问题根因四、故障解决方案 &#x1f4ca;4.1 解决方案 &#x1f6e0;️五、总结附件一、前言 在磐基系统中大量使用MySQL作为后端的数据存储&…

【代码随想录算法训练营——Day10】栈与队列——232.用栈实现队列、225.用队列实现栈、20.有效的括号、1047.删除字符串中的所有相邻重复项

LeetCode题目链接 https://leetcode.cn/problems/implement-queue-using-stacks/ https://leetcode.cn/problems/implement-stack-using-queues/description/ https://leetcode.cn/problems/valid-parentheses/description/ https://leetcode.cn/problems/remove-all-adjacent-…

Asp .Net Core 系列:Asp .Net Core 集成 Hangfire+MySQL

在 .NET 或 .NET Core 应用中&#xff0c;若需在不依赖 Windows 服务、独立进程的前提下实现后台处理&#xff0c;Hangfire 是最成熟、简单的方案之一 —— 它可直接嵌入现有应用&#xff08;如 ASP.NET Core Web 应用&#xff09;&#xff0c;无需额外部署&#xff0c;同时提供…

网站漏洞扫描要怎么处理?

在网络安全领域&#xff0c;网站漏洞是黑客攻击的重要突破口&#xff0c;而网站漏洞扫描能及时发现这些隐患。但很多小白在完成漏洞扫描后&#xff0c;不清楚后续该如何处理&#xff0c;导致漏洞一直存在&#xff0c;给网站安全埋下风险。下面从准备工作、处理步骤、验证维护等…

淘宝RecGPT:通过LLM增强推荐

导论背景 (Background)​​推荐系统的核心挑战​​&#xff1a;怎么 准确推断 用户行为背后快速变化的真实意图&#xff0c;以实现用户、商户和平台的三赢。​​现有方法的局限性​​&#xff1a;传统的基于历史日志共现模式&#xff08;“从点击学习点击”&#xff09;的模型&…

【Go系统编程】07 网络化IPC:Go的王牌——Socket编程

大家好&#xff0c;我是Tony Bai。欢迎来到我们《Go 系统编程》专栏的最后一讲。在过去的旅程中&#xff0c;我们探索了管道、消息队列、共享内存等一系列强大的 IPC 机制。它们各有所长&#xff0c;但都有一个共同的、致命的局限性&#xff1a;它们都只能在同一台物理机上工作…

claude code使用小窍门

视频地址 B站 1 /init 在项目最开始的时候&#xff0c;使用/init可以将项目通读一遍。cc会将学习到的关于项目的知识都保存到CLAUD.MD文件中 2、 /compact 用来压缩对话的上下文&#xff0c;claude会将之前的一些乱七八糟或者重复的对话删除压缩&#xff0c;有利于提高AI的…

The learning process of Decision Tree Model|决策树模型学习过程

----------------------------------------------------------------------------------------------- 这是我在我的网站中截取的文章&#xff0c;有更多的文章欢迎来访问我自己的博客网站rn.berlinlian.cn&#xff0c;这里还有很多有关计算机的知识&#xff0c;欢迎进行留言或…

期货盘后空开是认购期权行权?

本文主要介绍期货盘后空开是认购期权行权&#xff1f;期货盘后空开与认购期权行权是两个独立的概念&#xff0c;无直接关联&#xff0c;需从交易机制、操作逻辑及市场规则三方面区分。期货盘后空开是认购期权行权&#xff1f;1. 定义与交易属性期货盘后空开&#xff1a;属于期货…

ESP32 I2S音频总线学习笔记(七):制作一个录音播放器

简介 上一篇我们利用I2S输出DIY了一个蓝牙音箱简单玩了一下&#xff0c;本篇我们继续来看代码。前面几篇文章我们分别介绍了I2S输入&#xff0c;I2S输出&#xff0c;以及WAV文件格式的相关内容&#xff0c;那我们就可以根据所学到的&#xff0c;制作一个录音机&#xff0c;具体…

PyTorch 动态图的灵活性与实用技巧

PyTorch 以其动态计算图&#xff08;Dynamic Computation Graph&#xff09;而闻名&#xff0c;这赋予了它极高的灵活性和易用性&#xff0c;使其在研究和实际应用中都备受青睐。与TensorFlow 1.x的静态图&#xff08;需要先定义图结构&#xff0c;再运行&#xff09;不同&…

#C语言——刷题攻略:牛客编程入门训练(十一):攻克 循环控制(三),轻松拿捏!

&#x1f31f;菜鸟主页&#xff1a;晨非辰的主页 &#x1f440;学习专栏&#xff1a;《C语言刷题合集》 &#x1f4aa;学习阶段&#xff1a;C语言方向初学者 ⏳名言欣赏&#xff1a;"代码行数决定你的下限&#xff0c;算法思维决定你的上限。" 前言&#xff1a;在学习…

复杂PDF文档结构化提取全攻略——从OCR到大模型知识库构建

在学术研究、金融分析、法律合同、工程设计等众多领域&#xff0c;PDF文档已成为信息存储与传递的重要载体。然而&#xff0c;面对包含复杂表格、公式、图表、手写批注、多栏排版等元素的PDF&#xff0c;传统工具往往难以准确、完整地提取内容。这不仅影响信息利用效率&#xf…

HttpClient、OkHttp 和 WebClient

HttpClient、OkHttp 和 WebClient 是 Java 生态中常见的 HTTP 客户端&#xff0c;它们在设计理念、异步能力、性能等方面有所不同。以下是它们的详细对比&#xff1a;1. 概述客户端介绍Apache HttpClient传统同步 HTTP 客户端&#xff0c;功能丰富&#xff0c;历史悠久&#xf…

书籍成长书籍文字#创业付费杂志《财新周刊》2025最新合集 更33期

免费访问地址 https://isharehubs.com/article/2025-33-26c27ee5bb9180cdafc5efbec9545ac5 资源信息 付费杂志《财新周刊》2025最新合集 更33期 《财新周刊》2025 最新合集&#xff08;更至 33 期&#xff09;重磅上线&#xff0c;聚焦年度热点与结构性变化&#xff0c;从监…

用python的socket写一个局域网传输文件的程序

局域网传输文件是最最常用的功能&#xff0c;我参考https://www.jb51.net/python/345837qrz.htm这篇文章&#xff0c;复制粘贴&#xff0c;开发了一个。但发现进度条没有用&#xff0c;也没有显示传输用时和传输速度的功能&#xff0c;于是我改写了代码&#xff0c;使它实现这个…