分享一个简单的基于C语言嵌入式GUI界面切换代码

news2025/1/18 4:32:46

目录

前言

一、数据类型

二、页面调度

三、页面显示

四、视频展示


前言

        最近在用LVGL写一个简单的UI界面,需要进行几个页面的切换,所以就自己写了一个简单页面切换代码,方便进行页面切换,同时使UI代码结构更加清晰。这个结构主要用于嵌入式MCU上使用,所以结构比较简单。

一、数据类型

typedef struct ui_show_t
{
    struct ui_show_t *last;
    uint32_t  *ui;
}ui_show_t;

这个页面切换代码会用到一个类似链表的结构,每个界面都会定义一个这样的数据数据结构,用来保存上一个页面的指针。如下图所示:

这样每切换到下一页面的时候都可以根据需要来切换到上一页面。

同时我定义了页面的函数类型:

typedef struct ui_show_t * (*ui_show_fun)(ui_show_t* ui_show,ui_opera_t ui_opera)

除了上面提到ui_show_t类型,还有一个ui_opera_t,这个类型定义了页面的操作设备,例如触摸屏、实体按键、旋转按钮等等,我的设备是旋转按钮,所以就定义了如下的类型:

typedef struct 
{
    int8_t      dir_cnt;    //旋转方向计数
    btn_sta_t   btn_sta;    //按键状态
}ui_opera_t;

这样就可以操作我的屏幕进行页面切换了。


二、页面调度

        对于页面的调用是单独创建了一个任务,在这个任务的循环里面获取旋转按钮的状态以及进行页面的显示。可以看到最终显示的是 my_show_ui->ui  这个页面,这个页面在初始化的时候被赋值了ln_lvgl_mainwindow这个函数指针,这个函数就是用来显示主页面的函数。

#include "ln_lvgl_ui.h"
lv_ui guider_ui;

static ui_show_t my_start_ui;
static ui_show_t *my_show_ui = NULL;
ui_opera_t my_ui_opera;

static OS_Thread_t g_lvgl_ui_thread;
#define LVGL_UI_TASK_STACK_SIZE   4*40*256 //Byte

void ui_show_scheduler(void *params);
ui_show_t* ln_lvgl_mainwindow(ui_show_t* ui_show,ui_opera_t ui_opera);
ui_show_t* ln_lvgl_lightwindow(ui_show_t* ui_show,ui_opera_t ui_opera);

int ln_lvgl_ui_init()
{
    ln_drv_rotate_btn_init();    //旋转按钮初始化
    lv_init();                   //LVGL初始化
    lv_port_disp_init();         //显示设备初始化
    setup_ui(&guider_ui);        //第一个页面初始化
    //创建页面显示调度任务
    if(OS_OK != OS_ThreadCreate(&g_lvgl_ui_thread, "LVGL Task", ui_show_scheduler, NULL, OS_PRIORITY_BELOW_NORMAL, LVGL_UI_TASK_STACK_SIZE)) {
        return HAL_ERROR;
    }
    return HAL_OK;
}

void ui_show_scheduler(void *params)
{
    //对第一个页面的链表进行数据初始化
    my_start_ui.last = NULL;
    my_start_ui.ui = (uint32_t*)ln_lvgl_mainwindow;
    my_show_ui = &my_start_ui;
    while(1)
    {
        //获取旋转按钮的旋转方向计数以及按键状态
        my_ui_opera.dir_cnt = ln_drv_rotate_btn_get_dir();
        my_ui_opera.btn_sta = (btn_sta_t)ln_drv_rotate_btn_get_press();
        if(my_ui_opera.dir_cnt != 0){
            LOG(LOG_LVL_ERROR, "cnt :%d \r\n", my_ui_opera.dir_cnt);
        }

        //显示对应UI
        my_show_ui = (ui_show_t*)(*((ui_show_fun)(my_show_ui->ui)))((ui_show_t*)my_show_ui,my_ui_opera);

        //LVGL函数
        lv_timer_handler();
        
        //延时1ms
        OS_MsDelay(1);
    }
}

三、页面显示

#include "ln_lvgl_mainwindow.h"

//在这里定义了一个这个页面的链表方便存储上一个页面的指针
static ui_show_t my_mainwindow_ui;

ui_show_t* ln_lvgl_mainwindow(ui_show_t* ui_show,ui_opera_t ui_opera)
{
    static uint8_t show_flag    = 0;
    static int8_t cur_show_item = 0;
    static int8_t last_show_item = -1;
    if(show_flag == 0){
        //显示页面,只需要显示一次就可以
        show_flag = 1;
    }
    
    //根据旋转编码器不同的值,来执行不同的操作
    cur_show_item += 0 - ui_opera.dir_cnt;
    if(cur_show_item != last_show_item){
        switch(cur_show_item){
            case 0:{
                break;
            }
            case 1:{
                break;
            }
        }
    }
    last_show_item = cur_show_item;

    //按键长按和短按也都可以执行不同的操作,例如长按返回上一个页面,短按进入下一页面
    if(ui_opera.btn_sta == SHORT_PRESS){
        //短按进入下一个页面,下一个页面自行定义,直接赋值就好
        switch(cur_show_item){
            case 0:{
                    my_mainwindow_ui.last = ui_show;
                    my_mainwindow_ui.ui = (uint32_t*)ln_lvgl_lightwindow;//例如此处显示灯光页面
                    ui_show = &my_mainwindow_ui;
                    show_flag = 0;
                    break;
                }
             case 3:{
                    my_mainwindow_ui.last = ui_show;
                    my_mainwindow_ui.ui = (uint32_t*)ln_lvgl_timewindow;//例如此处显示时间页面
                    ui_show = &my_mainwindow_ui;
                    show_flag = 0;
                    break;
                }
        }
    }
    if(ui_opera.btn_sta == LONG_PRESS){
        //长按进入上一个页面(如果有的话)
        if(ui_show->last != NULL){
            //直接赋值
            ui_show = ui_show->last;
        }
    }
    //返回赋值后的指针地址
    return ui_show;
}

四、视频展示

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Java SSM框架实现实现四六级英语报名系统项目【项目源码+论文说明】

基于java的SSM框架实现四六级英语报名系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个高校四六级报名管理系统,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作…

什么是跨站脚本攻击

跨站脚本攻击 1. 定义2. 跨站脚本攻击如何工作3. 跨站脚本攻击类型4. 如何防止跨站脚本攻击 1. 定义 跨站脚本攻击(Cross-site Scripting,通常称为XSS),是一种典型的Web程序漏洞利用攻击,在线论坛、博客、留言板等共享…

leetCode 51.皇后 + 回溯算法 + 图解 + 笔记

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。每一种解法包…

Python读取栅格遥感影像并加以辐射校正后导出为Excel的一列数据

本文介绍基于Python语言中的gdal模块,读取一景.tif格式的栅格遥感影像文件,提取其中每一个像元的像素数值,对像素值加以计算(辐射定标)后,再以一列数据的形式将计算后的各像元像素数据保存在一个.csv格式文…

【力扣206】反转链表

【力扣206】反转链表 一.题目描述 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1 : 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1]示例 2 : 输入:head [1,2] 输出&#x…

机器学习---pySpark代码开发

1、eclipse开发pySpark程序 在eclipse中开发pySpark程序,需要安装pydev插件。 1).eclipse安装python插件,安装完成后重启。 2). 在window--->preferences中找到python interpreter配置安装python的路径: 3).新建python项目: 2、pyCharm开…

Centos图形化界面封装OpenStack Centos镜像

目录 背景 环境 宿主机环境安装 创建与安装Centos7.8虚机 虚机设置 安全相关 安装ACPI服务 安装cloud-init 安装cloud-utils-growpart 停⽌虚拟机 删除个性化信息 模板化与压缩 登录与验证 背景 今天早上在Centos官网下载的CentOS-7-aarch64-GenericCloud-2003.…

3dMax拼图生成工具Puzzle2D使用教程

Puzzle2D for 3dsMax拼图生成工具使用教程 Puzzle2D简介: 2D拼图随机生成器(英文:Puzzle2D) ,是一款由#沐风课堂#用MAXScript脚本语言开发的3dsMax建模小工具,可以随机创建2D可编辑样条线拼图图形。可批量…

解决vscode中html部分无法嵌套注释

不管是React项目还是Vue项目,相信你一定遇到过同样的问题,如果想要注释的结构内部也存在注释,那么编译器会报以下问题 使用 HTML-Comment 这个插件即可解决问题 选中需要注释的区域并根据系统输入快捷键,可以发现就算嵌套了注释…

使用Redis构建任务队列

文章目录 第1关:先进先出任务队列第2关:优先级任务队列第3关:定时任务队列 第1关:先进先出任务队列 编程要求 在Begin-End区域编写 add_task(task_name) 函数,实现将任务加入队列的功能,具体参数与要求如下…

C++基础 -35- string类

string类的格式 string a;如下图,使用string类比常规的字符串处理方便很多 而且需要进行的字符串处理,在类中都能完成 #include "iostream"using namespace std;extern "C" {#include "string.h" }int main() {//c的写…

Java基本数据类型详解

✨个人主页:全栈程序猿的CSDN博客 💨系列专栏:Java从入门到精通 ✌座右铭:编码如诗,Bug似流星,持续追求优雅的代码,解决问题如同星辰般自如 Java是一种强类型语言,数据类型在程序中起…

Prefix-Tuning 论文概述

Prefix-Tuning 论文概述 前缀调优:优化生成的连续提示前言摘要论文十问实验数据集模型实验结论摘要任务泛化性能 前缀调优:优化生成的连续提示 前言 大规模预训练语言模型(PLM)在下游自然语言生成任务中广泛采用fine-tuning的方法进行adaptation。但是f…

Java中各种数据类型之间的转换

低类型向高类型自动进行转换,高类型向低类型的准换会丢失数据,整数到字符类型的转换将获取对应编码的字符。 进行高精度向低精度的强制类型准换时,需要将想要转换成的数据类型加一个括号()。 如何完成自动转换呢? 转换前的数据类…

正是阶段高等数学复习--函数极限的计算

之前在预备阶段中函数极限的解决方式分三步,第一步观察形式并确定用什么方式来解决,第二步化简,化简方式一共有7种,分别是最重要的三种(等价替换、拆分极限存在的项、计算非零因子)以及次重要的4种&#xf…

Maven的安装与配置本地仓库,镜像源,环境变量详细步骤

参考视频: 黑马程序员2023新版JavaWeb开发教程,实现javaweb企业开发全流程 【小飞非系列】最新Maven实战教程-项目实战构建利器 文章目录 一.下载Maven安装包二.配置Maven的本地仓库(本机仓库)三.配置镜像源(加速jar包的下载)四.配置Maven的环…

【计算机视觉】基于OpenCV计算机视觉的摄像头测距技术设计与实现

基于计算机视觉的摄像头测距技术 文章目录 基于计算机视觉的摄像头测距技术导读引入技术实现原理技术实现细节Python-opencv实现方案获取目标轮廓步骤 1:图像处理步骤 2:找到轮廓步骤完整代码 计算图像距离前置技术背景与原理步骤 1:定义距离…

llama.cpp部署通义千问Qwen-14B

llama.cpp是当前最火热的大模型开源推理框架之一,支持了非常多的LLM的量化推理,生态比较完善,是个人学习和使用的首选。最近阿里开源了通义千问大语言模型,在众多榜单上刷榜了,是当前最炙手可热的开源中文大语言模型。…

JavaWeb 添加页面和用户图像展示

add.jsp(需要登录之后才可以访问 ) -> 不是和login.jsp同级了那就 在images目录下加上默认图像 js目录下加入common.js javaWeb项目中,页面的路径 img的src form的action link的href script的src a的href推荐使用绝对路径 这个绝对路径…

图像批量设计软件Retrobatch Pro mac中文版功能特色

Retrobatch Mac是一款灵活的批量图像处理工具。用户可以自由创建Workflow来实现相应的功能,这些Workflow能取代大量的重复劳动,提高生产力。Retrobatch Mac的一般操作是从左边栏拖动相应动作到工作区形成节点(Nodes),节…