LVGL V8应用——通过按键切换页面

2023-11-11

一、按键切换对象

程序

全局变量

static lv_obj_t *contanier1= NULL;
static lv_obj_t *contanier2= NULL;

按钮对应回调函数,实现容器的切换

static void win_btn_event_callback1(lv_event_t* e)
{
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED)
    {
        // 给窗口1的容器添加隐藏属性,清除窗口2的隐藏属性
        lv_obj_add_flag(contanier1, LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(contanier2, LV_OBJ_FLAG_HIDDEN);
    }
}


static void win_btn_event_callback2(lv_event_t* e)
{
    lv_event_code_t code = lv_event_get_code(e);
    if (code == LV_EVENT_CLICKED)
    {
        // 给窗口2的容器添加隐藏属性,清除窗口1的隐藏属性
        lv_obj_add_flag(contanier2, LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(contanier1, LV_OBJ_FLAG_HIDDEN);
    }
}

创建容器contanier1和contanier2

void cont1(lv_obj_t *page)
{
    static lv_style_t obj_style;
    lv_style_reset(&obj_style);
    lv_style_init(&obj_style); // 初始化按钮样式
    lv_style_set_radius(&obj_style, 0); // 设置样式圆角弧度

    contanier1= lv_obj_create(page);  // 基于屏幕创建一个和屏幕大小一样的容器win1_contanier

    if (contanier1!= NULL)
    {
        lv_obj_set_style_bg_color(contanier1, lv_palette_main(LV_PALETTE_RED), 0);
        lv_obj_align(contanier1,LV_ALIGN_TOP_MID,0,0);
        lv_obj_set_size(contanier1, 280, 100);
        lv_obj_add_style(contanier1, &obj_style, 0);

        lv_obj_t * label = lv_label_create(contanier1);
        lv_label_set_text(label, "Cont1"); // 设置标签文本

        lv_obj_t * btn = lv_btn_create(contanier1);
        if (btn != NULL)
        {
            lv_obj_set_size(btn, 60, 40);
            lv_obj_align(btn,LV_ALIGN_BOTTOM_RIGHT,0,0);
            lv_obj_add_event_cb(btn, win_btn_event_callback1, LV_EVENT_ALL, page); // 给对象添加CLICK事件和事件处理回调函数

            lv_obj_t *label = lv_label_create(btn); // 给按钮添加标签
            if (label != NULL)
            {
                lv_label_set_text(label, "Button1"); // 设置标签文本
                lv_obj_center(label); // 标签居中显示
            }
        }
    }
}
void cont2(lv_obj_t *page)
{
    static lv_style_t obj_style;
    lv_style_reset(&obj_style);
    lv_style_init(&obj_style); // 初始化按钮样式
    lv_style_set_radius(&obj_style, 0); // 设置样式圆角弧度

    win2_contanier = lv_obj_create(page); // 基于屏幕创建一个和屏幕大小一样的容器win2_contanier
    if (contanier2 != NULL)
    {
        lv_obj_set_style_bg_color(contanier2 , lv_palette_main(LV_PALETTE_BLUE), 0);
        lv_obj_align(contanier2 ,LV_ALIGN_TOP_MID,0,0);
        lv_obj_set_size(contanier2 , 280, 100);
        lv_obj_add_style(contanier2 , &obj_style, 0);

        lv_obj_t * label = lv_label_create(contanier2 );
        lv_label_set_text(label, "Cont2"); // 设置标签文本

        lv_obj_t * btn = lv_btn_create(contanier2 );
        if (btn != NULL)
        {
            lv_obj_set_size(btn, 60, 40);
            lv_obj_align(btn,LV_ALIGN_BOTTOM_RIGHT,0,0);
            lv_obj_add_event_cb(btn, win_btn_event_callback2, LV_EVENT_ALL, page); // 给对象添加CLICK事件和事件处理回调函数
            lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_RED), 0);

            lv_obj_t *label = lv_label_create(btn); // 给按钮添加标签
            if (label != NULL)
            {
                lv_label_set_text(label, "Button2"); // 设置标签文本
                lv_obj_center(label); // 标签居中显示
            }
        }
    }
}

调用容器创建函数,并隐藏容器2

void main(void)
{
    lv_obj_t * page = lv_obj_create(lv_scr_act());
    lv_obj_set_size(page, LV_HOR_RES, LV_VER_RES);       //设置到屏幕大小

    label_refresh(page);

    cont1(page);
    cont2(page);
    lv_obj_add_flag(win2_contanier, LV_OBJ_FLAG_HIDDEN);
}

效果

在这里插入图片描述
在这里插入图片描述
按下按钮,只执行Cont1与Cont2之间的切换,其余部分不变

二、按键切换页面

方法1:

通过LV_OBJ_FLAG_HIDDEN隐藏属性实现页面切换,来源

//win1按钮回调函数,按下之后隐藏win1,显示win2
static void win_btn_event_callback1(lv_event_t* event)
{
    lv_event_code_t code = lv_event_get_code(event);
    if (code == LV_EVENT_CLICKED)
    {
        // 给窗口1的容器添加隐藏属性,清除窗口2的隐藏属性
        lv_obj_add_flag(win1_contanier, LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(win2_contanier, LV_OBJ_FLAG_HIDDEN);
    }
}
 //win2按钮回调函数,按下之后隐藏win2,显示win1
static void win_btn_event_callback2(lv_event_t* event)
{
    lv_event_code_t code = lv_event_get_code(event);
    if (code == LV_EVENT_CLICKED)
    {
        // 给窗口2的容器添加隐藏属性,清除窗口1的隐藏属性
        lv_obj_add_flag(win2_contanier, LV_OBJ_FLAG_HIDDEN);
        lv_obj_clear_flag(win1_contanier, LV_OBJ_FLAG_HIDDEN);
    }
}

创建两个窗口,给其中一个窗口加上隐藏属性

void lv_win_switch_main()
{
    show_button_win1();
    show_button_win2();
    // 给窗口2的容器添加隐藏属性
    lv_obj_add_flag(win2_contanier, LV_OBJ_FLAG_HIDDEN);

方法2:

在回调函数中,创建新窗口并删除旧窗口


static void win_btn_event_callback1(lv_event_t* event)
{
    lv_event_code_t code = lv_event_get_code(event);
    if (code == LV_EVENT_CLICKED)
    {
        // 删除窗口1的win1_contanier容器,这样就可以把win1_contanier上的子对象全部删除,然后显示窗口2
        lv_obj_del(win1_contanier);
        show_button_win2();
    }
}
 
 
static void win_btn_event_callback2(lv_event_t* event)
{
    lv_event_code_t code = lv_event_get_code(event);
    if (code == LV_EVENT_CLICKED)
    {
        // 删除窗口2的win2_contanier容器,这样就可以把win2_contanier上的子对象全部删除,然后显示窗口1
        lv_obj_del(win2_contanier);
        show_button_win1();
    }
}
void lv_win_switch_main()
{
    show_button_win1();
#endif

方法3:

使用下面两个函数加载屏幕

直接加载该屏幕scr
参数1:要加载的屏幕
static inline void lv_scr_load(lv_obj_t * scr)
{
    lv_disp_load_scr(scr);
}
通过动画的方式显示
参数1:要加载的屏幕
参数2:动画类别
参数3:切换动画需要的时间
参数4:为true时则会在切换界面后将旧界面删除,节约内存
void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del);

动画类别:
LV_SCR_LOAD_ANIM_NONE 在 delay 毫秒后立即切换
LV_SCR_LOAD_ANIM_OVER_LEFT/RIGHT/TOP/BOTTOM 将新屏幕按指定的方向移动
LV_SCR_LOAD_ANIM_MOVE_LEFT/RIGHT/TOP/BOTTOM 新屏幕和当前屏幕都按指定的方向移动
LV_SCR_LOAD_ANIM_FADE_ON 将新屏幕淡入旧屏幕

代码

创建页面1

    lv_obj_t * one = lv_obj_create(lv_scr_act());                  	//在默认屏上创建obj对象
    lv_obj_set_style_bg_color(one,lv_color_hex(0xeeffcc), LV_STATE_DEFAULT); // obj背景色设成黄色
    lv_obj_set_size(one, LV_HOR_RES, LV_VER_RES);       			// 设置到屏幕大小

创建页面2

	lv_obj_t * two = lv_obj_create(NULL);                          // 创建新屏幕但未加载到显示
    lv_obj_set_style_bg_color(two,lv_color_hex(0x00d8db), LV_STATE_DEFAULT);    // 背影色设成蓝色
    lv_obj_set_size(two, LV_HOR_RES, LV_VER_RES);       			//设置到屏幕大小

从one创建按钮one_btn ,two创建按钮two_btn ,分别注册回调函数,传入用户自定义数据two,one

	lv_obj_t* one_btn = lv_btn_create(one);
    lv_obj_align(one_btn, LV_ALIGN_TOP_MID, 0, 20);

    lv_obj_t* label = lv_label_create(one_btn);             // 创建label
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);         // label居屏幕中心对齐
    lv_label_set_text(label, "ONE");                    // label显示ONE
    lv_obj_add_event_cb(one_btn, one_btn_event_handler, LV_EVENT_CLICKED, two);

    lv_obj_t* two_btn = lv_btn_create(two);
    lv_obj_align(two_btn, LV_ALIGN_TOP_MID, 0, 20);

    label = lv_label_create(two_btn);                       // 创建label
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);         // 居中对齐
    lv_label_set_text(label, "TWO");                    // label上显示TWO
    lv_obj_add_event_cb(two_btn, two_btn_event_handler, LV_EVENT_CLICKED, one);

当按钮按下时调用回调函数,获取用户自定义数据two,one,并切换到相应界面lv_scr_load_anim();

void one_btn_event_handler(lv_event_t *e)
{
    lv_obj_t * two = lv_event_get_user_data(e);
    
	// 加载屏幕TWO,动画效果为LV_SCR_LOAD_ANIM_FADE_ON,切换时间为100ms,延迟0ms后从第一屏开始切换,切换完成后隐藏屏幕二
    lv_scr_load_anim(two, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, false); 
}
void two_btn_event_handler(lv_event_t *e)
{
    lv_obj_t * one = lv_event_get_user_data(e);
    
	// 加载屏幕one,动画效果为LV_SCR_LOAD_ANIM_FADE_ON,切换时间为100ms,延迟0ms后从第二屏开始切换,切换完成后隐藏屏幕一
    lv_scr_load_anim(one, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, false); 
}

效果

按下按钮one切换到屏幕two
在这里插入图片描述
在这里插入图片描述

方法4:

在唯一画布上建立多个界面,每个界面大小都等于屏幕大小

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LVGL V8应用——通过按键切换页面 的相关文章

  • 类型错误:无法读取未定义的属性“存在”

    我正在尝试为 jsx 文件编写一个测试用例 在此我能够传递 proptypes 但不是我正确传递 proptypes 的地方 当我运行测试用例时出现错误 下面提供我的错误 测试用例和代码 类型错误 无法读取未定义的属性 存在 不知道如何让它
  • 为什么虽然输入的值确实发生了变化,但jquery更改事件没有触发? [复制]

    这个问题在这里已经有答案了 JSFIDDLE http jsfiddle net meXm3 2 网页代码
  • 创建地图后向 Google 地图 v3 添加标记

    我对使用 Google Maps API 比较陌生 现在我正在开发一个项目 用户可以选择各种搜索过滤器并查看结果自动显示在地图上 而无需重新加载页面 到目前为止 我的方法是创建一个控制地图的 Javascript 对象 以便我可以按照我的意
  • 通过 JavaScript 获取页面/iframe 的编码

    我想通过 JavaScript 或浏览器中的其他一些 API 以编程方式确定页面的编码 我想要这些信息的原因是因为我试图对主要浏览器支持的字符编码进行模糊测试 显然仅仅因为我发送了适当的 内容类型 并不意味着浏览器会使用编码做正确的事情 欢
  • 从 json 创建下拉列表

    我有一个这种形式的 json COLUMNS ID Name DATA 1 Joe 2 Sam 3 Doug 我正在寻找一个如何在 javascript 中从该数据创建下拉列表的示例 但 json dropdown 列表的所有示例 json
  • 如何告诉杰克逊在反序列化期间忽略空对象?

    在反序列化过程中 据我理解是将JSON数据转换为Java对象的过程 我如何告诉Jackson 当它读取不包含数据的对象时 应该忽略它 我正在使用 Jackson 2 6 6 和 Spring 4 2 6 我的控制器收到的JSON数据如下 i
  • 如何将捕获的图像写入/粘贴到文档文件?

    我有一个场景 我需要捕获图像并将它们一个接一个地写入到一个word文件中 我已经编写了下面的代码 但似乎不起作用 请帮忙 Robot robot try robot new Robot BufferedImage screenShot ro
  • 定时器启动/停止参数

    自从加入这个社区以来 我在技能和进步方面取得了突飞猛进的进步 你们都是一个巨大的帮助 我无法提供一个计时器 该计时器已在启动和停止时实现了某些参数 我要么收到错误消息 局部变量计时器可能尚未初始化 要么没有收到错误消息 但什么也没有发生 也
  • 在 init 之外在 java 中创建对象

    因此 对于我正在创建的游戏 我有一些扩展 GameDriver 的类 到目前为止 在所有其他类上我都能够扩展 GameDriver 然后在 GameDriver 中我可以执行以下操作 ArrayList
  • 如何将 JAVAX-WS 端点绑定更改为 SOAP 1.2?

    我正在使用发布测试 WS 实现Endpoint publish 用于在 Visual Studio 中使用 根据文档 http metro java net nonav 1 2 docs endpoint html默认的 SOAP 绑定是1
  • Firefox:按下鼠标按钮时鼠标悬停不起作用

    这是我想做的 https gfycat com ValidEmbarrassedHochstettersfrog https gfycat com ValidEmbarrassedHochstettersfrog 我想强调一些 td 对象在
  • java:验证 GUI 中的所有文本字段是否已完成

    我正在尝试创建一个允许某人设置帐户的 GUI 我想验证按下创建帐户按钮时所有文本字段是否完整 做这个的最好方式是什么 我正在附加我的代码 但我对文本字段是否完整的验证不起作用 参见下面的代码 public class GUIaccounts
  • 计算网站上多个文件的下载次数的最佳方法[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 问题是 计算网站上多个文件的下载次数的最佳方法 我正在尝试做的事情 跟踪并统计多个文件的下载数量 对于具有不同扩展名的文件 foo z
  • 检查 IE8 是否使用纯 Javascript [重复]

    这个问题在这里已经有答案了 我以前是这样检查的 browser msie browser version 8 但似乎 browser已从 jQuery 的更高版本中删除 So 我怎样才能用纯javascript检查这一点 I tried i
  • 在 d3v4 堆积条形图中使用 JSON

    我找到了一个d3v3堆积条形图示例 http bl ocks org mstanaland 6100713我想使用它 因为它使用 json 数据 还有一个d3v4规范条形图示例 https bl ocks org mbostock 3886
  • datatables.search 函数修改后的奇怪行为

    这个问题是后续问题这个问题 https stackoverflow com questions 54671211 overriding datatables js search behavior 我已经创建了这个 JSFiddle http
  • Firefox 扩展中的 localStorage

    我正在尝试从 Firefox 扩展访问页面的 localStorage 我的理解是content给出了参考window当前页面的 当我尝试访问页面的 localStorage 时content localStorage 我想我正在得到它的参
  • ASP.NET 中的 JavaScript 事件处理程序

    我有以下 iframe 控件 旨在成为类似 facebook 的按钮 iframe gt 我在上面定义了 javascript 函数 如下所示
  • 用圆形雷达数学方法表示点

    我正在编写一个简单的应用程序 它可以向您显示您周围的朋友 但不是在法线地图中 而是在像 UI 这样的真正圆形雷达上 https i stack imgur com Au3IP png https i stack imgur com Au3I
  • Sencha-touch :保存登录名/密码(保存会话,多任务)

    我有一个 Java Web 应用程序 其中移动部分是用 Sencha touch 开发的 当我启动 sencha touch 应用程序时 她询问我的登录名 密码 因为该应用程序的访问受到限制 但是我想保存用户的登录名 密码 sencha t

随机推荐

  • AlexNet imagenet classification with deep convolutional neural networks 阅读笔记

    NIPS 2012 imagenet classification with deep convolutional neural networks Paper 该网络有60 000 000个参数 650 000个神经元 包含5个卷积层 有一
  • 几分钟带你快速了解MyBatis框架理论知识!

    1 Mybatis框架是什么 mybatis是一款非常优秀的持久化框架 也是一个半ORM 对象关系映射 框架 mybatis框架它支持sql语句的定制化 存储过程和高级映射 mybatis避免了JDBC代码和手动设置参数和获取结果集 myb
  • 7个步骤让PC网站自动适配手机网页

    传统的网站如何完成向移动设备的快速转型 通过移动适配技术可以实现 切图网是国内首家基于web技术服务的公司 而移动适配主要通过底层的web技术开发手段来完成 下面切图网将从技术角度来告诉你通过7个步骤来完成一个PC网站向移动设备的跳跃 1允
  • Stereo Matching (双目)立体匹配 & 视差图 & 双目图片进行立体匹配获取深度图进行三维重建的步骤​​​​​​​

    立体匹配技术就是通过匹配两幅或者多幅图像来获得视差 disparity 图 通过立体匹配可以获得深度 进行深度估计 立体匹配算法通常由四个部分组成 包括 匹配代价计算 代价聚合 视差计算和视差优化 双目立体匹配一直是双目视觉的研究热点 双目
  • GDAL-3.3.2编译

    前言 我的环境是win10 vs2019 gdal3 3 2 编译步骤 1 GDAL下载 1 GDAL下载地址 2 GEOS Geometry Engine Open Source 下载地址 3 PROJ8下载地址 注意 1 geos官网主
  • 【Xilinx AX7103 MicroBalze学习笔记4】MicroBlaze 按键中断实验

    目录 实验任务 实验框图 硬件设计 Vivado部分 Block Design 搭建 软件设计 SDK部分 代码部分 上板验证 往期系列博客 实验任务 通过 AXI GPIO 检测按键状态产生中断信号 中断控制器检测到中断后 给处理器发送中
  • 【C语言】—— 实现简易四则运算

    实现简易四则运算表达式 前言 在我们使用计算器进行简单的加减乘除运算的时候 需要注意很多问题 最重要的是乘除法的算数优先级和加减法是不同的 如果在一连串连续输入的时候 我们要如何做到正确解答问题呢 解题思路 在面对这个问题的时候 我首先想到
  • 埋点SDK原理与实现

    文章目录 埋点分析 一 埋点是什么 二 为什么要埋点 三 怎么做埋点 举例Google Analytics服务提供的主要功能 四 埋点的实现原理 1 用户使用方式 1 全局注册 2 手动埋点 3 无埋点 2 实现原理 1 如
  • esp8266 at接收数据中断时间_C51编程18中断篇(串行通讯2)

    MCS 51单片机内部有两个独立的接收与发送SBUF 接收SBUF不能发送 发送SBUF不能接收 它们共用一个地址 99H 内部逻辑结构下图所示 在串行内部逻辑结构中可以看到 串行通信除了与SBUF有关外 还与串行口控制寄存器SCON 地址
  • PCL点云处理之读取与保存PLY文件(点云\网格)(一百五十四)

    PCL点云处理之读取与保存PLY文件 一百五十四 一 PLY文件介绍 二 读取内容 1 点云 2 网格 一 PLY文件介绍 在平常的工作学习 会接触到后缀名为 ply的文件 这是一种常用的存储点云或者网格数据的文件格式 我们可以通过一些方法
  • 两台(或多台)电脑怎么实现文件共享

    关于文件共享 总结了几种实现方式 大家可以根据自己的需求选择合适的共享方式 一 在同一个局域网内 无论是连接的WiFi还是网线 工作的需要 需要共享一些文件 1 找到需要共享的文件夹 或者文件 位置 如下图 比如需要共享 我的电脑的C盘 2
  • 【源码可分享】教你用Python制作自动答题脚本,实现自动答题,100%正确率!

    文章目录 前言 一 自动答题的原理 二 自动答题的步骤 三 Python实现自动答题的方法 总结 前言 当今社会 人们的生活越来越依赖于计算机技术 而Python作为一种高级编程语言 已经成为了众多程序员的首选语言 Python具有简单易学
  • 字符串解析

    知识点 1 split 方法用于把一个字符串分割成字符串数组 2 JSON stringify serilizeUrl sUrl 利用原生JSON对象 将对象转为字符串
  • 遇到DDos攻击勒索保护费,这该怎么办?

    经常会有遇到一些客户过来咨询自己遭到了网络攻击 对方勒索钱财 要是不给就会一直持续攻击下去 许多客户遇到这种情况 找到了德迅云安全询问这种情况有什么办法处理 首先遇到这种事情 这个是不能妥协的 不能助长违法行为 根据以往的经验 只要妥协一次
  • Linux下设置白名单sudo

    Linux下设置白名单sudo 普通账户权限不够 频繁切换root账户比较麻烦 我们可以把自己的普通账户添加到sudoers file中 这样我们可以使用sudo命令在普通用户下提升我们的权限 在root账户下 输入 vim etc sud
  • (论文加源码)基于deap的四分类脑电情绪识别(一维CNN+LSTM和一维CNN+GRU

    论文和源码见个人主页 https download csdn net download qq 45874683 85002721 论文加源码 基于DEAP数据集的1D CNN和RNN情感分类 GRU和LSTM 摘要 在这里 我们研究了脑电情
  • 远程桌面的端口号是多少?

    远程桌面 Remote Desktop 是一种用于远程访问和控制计算机的技术 它允许用户通过网络连接到远程计算机并以图形化界面进行操作 远程桌面使用的端口号通常是3389 在Windows操作系统中 远程桌面协议 Remote Deskto
  • 云服务器内存使用率多少合适,什么时候应当考虑升级主机内存

    根据mysql官方说法 服务器内存占用比例达80 时 属于高负载运行状态了 内存占用比例长时间超过80 时 属于很不稳定状态 长时间超过90 就进入风险区了 这时容易产生数据丢失 数据库崩塌等不安全现象 当然 内存使用率过低又有点资源浪费
  • Wolfram Mathematica 12.3免费安装教程

    注意 本文介绍的Wolfram Mathematica仅为学习用途 如果有条件请支持正版 本文参考自贴吧激活教程 有Github账号的可以点赞支持原作者 https github com TieBaMma InstallTutorial b
  • LVGL V8应用——通过按键切换页面

    一 按键切换对象 程序 全局变量 static lv obj t contanier1 NULL static lv obj t contanier2 NULL 按钮对应回调函数 实现容器的切换 static void win btn ev