LittleVGL

1、视频快速入门 

快速入门LVGL(基于STM32,LVGL 8.2.0)_mucherry的博客-CSDN博客_lvgl

十几分钟学会如何使用lvgl设计器gui guider和模拟器编写一个简单计算器应用_哔哩哔哩_bilibili

SquareLine Studio

STM32移植LVGL8.0.2超详细的保姆级教程附移植好的工程文件_保哥在江湖的博客-CSDN博客_stm32移植lvgl

图表 (Chart) - 5寸金牛座开发板

Tips:按住Ctrl快速一起重命名

2、普中开发板移植LVGL

移植过程按1中的视频移植,但未能成功显示数Demo,怀疑是disp_flush需要调用底层lcd操作接口不对与视频中调用的函数不一样,再度查找分析果然是,要替换成另外一个函数。

typedef union {
    struct {
        uint16_t blue  : 5;
        uint16_t green : 6;
        uint16_t red   : 5;
    } ch;
    uint16_t full;
} lv_color16_t;
typedef lv_color16_t lv_color_t;

参考文章:https://www.eefocus.com/article/484678.html

 EmbedSummary: 嵌入式大杂烩资源汇总

Data:22.12.25

LVGL学习笔记:恩智浦gui guider+Platformio+ESP32 示例 - 哔哩哔哩

LVGL学习笔记_William_Zhang_csdn的博客-CSDN博客_lvgl

3.lvgl移植正点原子视频

Codeblocks快捷键 | Ctrl

第7讲 基础篇-LVGL移植(无操作系统4)_哔哩哔哩_bilibili

LVGL 8.2 菜单-pudn.com

Free Icons, Clipart Illustrations, Photos, and Music

LVGL+SMT32的项目练习(多图) - 个人小站

4.API函数

事件回调函数的 lv_event_t * e参数 

获取触发的事件代码:lv_event_code_t code = lv_event_get_code(e);

获取触发事件的对象:lv_obj_t * target = lv_event_get_target(e);

设置背景颜色:lv_obj_set_style_bg_color( label, lv_color_hex(0xffe1d4), LV_STATE_DEFAULT );

设置字体大小:lv_obj_set_style_text_font( label, &lv_font_montserrat_30, LV_STATE_DEFAULT );
 设置文本颜色:lv_obj_set_style_text_color( label, lv_color_hex(0xf7b37b),LV_STATE_DEFAULT );

开启重新着色功能 :lv_label_set_recolor( label, true );

 单独设置颜色:lv_label_set_text( label, "hallo #ff0000 lvgl# " );

设置长文本模式:lv_label_set_long_mode(label, LV_LABEL_LONG_...);

 开启状态切换 :lv_obj_add_flag( btn, LV_OBJ_FLAG_CHECKABLE ); 

添加状态:默认打开且不可修改:lv_obj_add_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);

清除开关的状态:lv_obj_clear_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);   

获取(判断)开关状态:lv_obj_has_state(switch1, LV_STATE_CHECKED) /* 返回值:1,选中; 0,非选中 */

设置文本和勾选框的间距:lv_obj_set_style_pad_column( checkbox, 20, LV_STATE_DEFAULT );

checkbox和btn 用的是 LV_EVENT_VALUE_CHANGED

可以设置的有应用的状态、应用的部分

------------------------------------------------------label--------------------------------------------------------- 

直接设置文本:lv_label_set_text( label, "hallo \n lvgl");
文本不存储在动态内存,而是在指定的缓冲区中(慎用):lv_label_set_text_static( label,"hallo" );
格式化显示文本,类似printf :lv_label_set_text_fmt( label, “Value: %d”, 50 ) ;
背景颜色:lv_obj_set_style_bg_color( label, lv_color_hex(0xffe1d4), LV_STATE_DEFAULT );
字体大小:lv_obj_set_style_text_font( label, &lv_font_montserrat_30, LV_STATE_DEFAULT );
文本颜色:lv_obj_set_style_text_color( label, lv_color_hex(0xf7b37b), LV_STATE_DEFAULT );
开启重新着色功能 :lv_label_set_recolor( label, true ); 
单独设置颜色 :lv_label_set_text( label, "hallo #ff0000 lvgl# " );
长文本模式:lv_label_set_long_mode(label, LV_LABEL_LONG_...);


enum {
    LV_LABEL_LONG_WRAP,                     /* 默认模式, 如果部件大小已固定,超出的文本将被剪切 */
    LV_LABEL_LONG_DOT,                      /* 将 label 右下角的最后 3 个字符替换为点… */
    LV_LABEL_LONG_SCROLL,                   /* 来回滚动 */
    LV_LABEL_LONG_SCROLL_CIRCULAR,      /* 循环滚动 */
    LV_LABEL_LONG_CLIP,                     /* 直接剪切掉部件外面的文本部分 */
};

------------------------------------------------------btn---------------------------------------------------------  

 开启状态切换 :lv_obj_add_flag( btn, LV_OBJ_FLAG_CHECKABLE );

------------------------------------------------------switch--------------------------------------------------------- 

添加状态:默认打开且不可修改 :lv_obj_add_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);
清除开关的状态 :lv_obj_clear_state(switch1, LV_STATE_CHECKED | LV_STATE_DISABLED);
获取(判断)开关状态:lv_obj_has_state(switch1, LV_STATE_CHECKED)      /* 返回值:bool类型,开 :1;关: 0 */

 ------------------------------------------------------checkbox--------------------------------------------------------- 

设置文本内容 :lv_checkbox_set_text( checkbox, "remember the password" );
设置文本和勾选框的间距 :lv_obj_set_style_pad_column( checkbox, 20, LV_STATE_DEFAULT ); 添加、清除复选框状态:
lv_obj_add_state(checkbox, LV_STATE_CHECKED | LV_STATE_DISABLED);    /* 添加状态:默认选中且不可修改 */
lv_obj_clear_state(checkbox, LV_STATE_CHECKED | LV_STATE_DISABLED);    /* 清除复选框的状态 */
获取(判断)复选框状态:lv_obj_has_state(checkbox, LV_STATE_CHECKED);    /* 返回值:1,选中; 0,非选中 */

------------------------------------------------------bar---------------------------------------------------------

设置当前值:lv_bar_set_value( bar, 50, LV_ANIM_ON );   /*LV_ANIM_ON : 动画开*/
设置范围值: lv_bar_set_range( bar, -100, 100 );
设置动画时间:lv_obj_set_style_anim_time( bar, 500, LV_STATE_DEFAULT ); /* 动画设置必须放在当前值设置之前 */
设置模式 :lv_bar_set_mode( bar, LV_BAR_MODE_RANGE );
设置起始值 :lv_bar_set_start_value( bar, -50, LV_ANIM_OFF );                                                设置定时器lv_timer_create(progress_bar_cb,100,NULL);


enum {
    LV_BAR_MODE_NORMAL,            /* 默认模式 */
    LV_BAR_MODE_SYMMETRICAL,        /* 从零值绘制到当前值(当前值可以小于0) */
    LV_BAR_MODE_RANGE            /* 允许设置起始值,但起始值必须小于当前值 */
};
注意:在V8.2版本的LVGL中,默认模式也允许设置起始值,但是后续的版本可能会修改。                动画时间指的是旧值刷新到新值的绘图时间,并不是现实中当前值变化所需的时间

------------------------------------------------------spinner---------------------------------------------------------

主体:LV_PART_MAIN
指示器:LV_PART_INDICATOR
手柄:LV_PART_KNOB
创建加载器部件:lv_obj_t   *spinner  = lv_spinner_create( parent, spin_time, arc_length );
设置圆弧颜色:lv_obj_set_style_arc_color( spinner, lv_color_hex(0x4a9f00), LV_PART_MAIN ); 
设置圆弧宽度:lv_obj_set_style_arc_width( spinner, 30, LV_PART_MAIN );    
------------------------------------------------------LED---------------------------------------------------------  

创建LED部件 :lv_obj_t   *led = lv_led_create( parent );
设置LED颜色 :lv_led_set_color( led, lv_color_hex(0xff0000) );
设置LED亮度,范围0~255:lv_led_set_brightness( led, 0 );    
打开LED(设置亮度为255):lv_led_on( led );
关闭LED :lv_led_off( led );
翻转LED状态 :lv_led_toggle( led );
快速居中:lv_obj_center();

------------------------------------------------------list---------------------------------------------------------  

创建列表部件 :lv_obj_t   *list = lv_list_create( parent );
添加列表文本:lv_list_add_text( list, “Settings" );
添加列表按钮:lv_obj_t  *btn= lv_list_add_btn( list, LV_SYMBOL_WIFI, “WLAN"); 
获取列表按钮文本:lv_list_get_btn_text( list, list_btn );
手动更新物体的参数:lv_obj_update_layout(obj_1);
添加按下的选中聚焦状态:lv_obj_add_state(btn,LV_STATE_FOCUS_KEY);

------------------------------------------------------dropdown---------------------------------------------------  

设置选项:lv_dropdown_set_options( dd, "a\nb\nc\nd");
设置选项 (静态):lv_dropdown_set_options_static( dd, "a\nb\nc\nd ");
添加选项,索引从0开始 :lv_dropdown_add_option( dd, "e", 4);    /*不能使用lv_dropdown_set_options_static设置的*/
设置当前所选项:lv_dropdown_set_selected( dd, 1);
获取索引:lv_dropdown_get_selected( dd);
获取选项文本:lv_dropdown_get_selected_str( dd, buf, sizeof(buf));     char buf[10];
设置列表展开方向 :lv_dropdown_set_dir(dd, LV_DIR_RIGHT);
设置图标 :lv_dropdown_set_symbol(dd, LV_SYMBOL_RIGHT);

------------------------------------------------------roller---------------------------------------------------

设置选项间隔:lv_obj_set_style_text_line_space(roller, 30, LV_STATE_DEFAULT);    
设置选项内容、滚动模式:lv_roller_set_options(roller, “a\nb\nc\nd”, LV_ROLLER_MODE_NORMAL);         /* 正常模式 */
设置当前所选项:lv_roller_set_selected(roller, 3, LV_ANIM_ON);
设置可见行数:lv_roller_set_visible_row_count(roller, 2);
获取索引 :lv_roller_get_selected(roller);    
获取选项文本 :lv_roller_get_selected_str(roller, buf, sizeof(buf));   char buf[10];

------------------------------------------------------slider--------------------------------------------------- 

 设置当前值 :lv_slider_set_value(slider, 50, LV_ANIM_OFF);
设置范围值 :lv_slider_set_range(slider, -100, 100);  
获取当前值:lv_slider_get_value(slider);
模式设置:lv_slider_set_mode(slider, LV_SLIDER_MODE_...);   NORMAL、SYMMETRICAL、RANGE
设置左值:lv_slider_set_left_value(slider, 20, LV_ANIM_OFF);
获取左值:lv_slider_get_left_value(slider); 

------------------------------------------------------arc--------------------------------------------------- 

设置当前值(需要在范围值之内):lv_arc_set_value(arc, 80);    
设置范围值 :lv_arc_set_range(arc, 0, 200);  
设置前景弧角度 :lv_arc_set_angles(arc, 135, 270);   //在此之前应该先设置背景弧 、且不要与设置当前值混用,他并不会改变数值,这是改变样式
设置背景弧角度 :lv_arc_set_bg_angles(arc, 135, 45);  
设置旋转角度:lv_arc_set_rotation(arc, 180);
获取当前值:lv_arc_get_value(arc);
设置模式:lv_arc_set_mode(arc, LV_ARC_MODE_REVERSE);
绘制速率,90°/秒 :lv_arc_set_change_rate(arc, 90);
设置背景弧宽度:lv_obj_set_style_arc_width(arc_1,20,LV_PART_MAIN);
设置前景弧宽度:lv_obj_set_style_arc_width(arc_1,20,LV_PART_INDICATOR);
去掉旋钮:lv_obj_remove_style(arc_2,NULL,LV_PART_KNOB);
去掉可点击属性:lv_obj_clear_flag(arc_2,LV_OBJ_FLAG_CLICKABLE);

------------------------------------------------------line--------------------------------------------------- 

设置线条坐标点:static lv_point_t  line_points[] = { {15, 5}, {25, 20}, {5, 20}, {15, 5} };
lv_line_set_points(line, line_points, 4);    
设置宽度 :lv_obj_set_style_line_width(line, 8, LV_PART_MAIN); 
设置圆角 :lv_obj_set_style_line_rounded(line, true, LV_PART_MAIN);
设置y轴反转:lv_line_set_y_invert(line, true);

------------------------------------------------------img--------------------------------------------------- 

声明图片 :LV_IMG_DECLARE(img_bird);
设置图片源 :lv_img_set_src(img, &img_bird);   // 在此前要先声明图片
设置图片偏移:lv_img_set_offset_x(img, 100);
           lv_img_set_offset_y(img, 20); 
图片重新着色:lv_obj_set_style_img_recolor(img, lv_color_hex(0xffe1d2), LV_PART_MAIN); 
           lv_obj_set_style_img_recolor_opa(img, 150, LV_PART_MAIN);
设置图片缩放:lv_img_set_zoom(img, 512);    /* 放大2倍 */
设置图片旋转:lv_img_set_angle(img, 900);    /* 顺时针方向旋转90° */
设置中心点:
    lv_obj_update_layout(img);        /* 更新图片布局信息 */
    lv_img_set_pivot(img, 0, 0);        /* 设置中心点 */
设置滑块主体颜色、透明度:lv_obj_set_style_bg_color(slider,lv_color_darken(color, 100),LV_PART_MAIN);   
更新图片参数:lv_obj_update_layout(img);   

------------------------------------------------------colorwheel--------------------------------------------------- 

设置当前选中颜色:lv_colorwheel_set_rgb(cw, lv_color_hex(0xff0000));
获取当前选中颜色:lv_colorwheel_get_rgb(cw);
设置色环模式:
    色相、饱和度、明度: lv_colorwheel_set_mode(cw, LV_COLORWHEEL_MODE_HUE/SATURATION/VALUE);
    固定色环模式 :lv_colorwheel_set_mode_fixed(cw, true);
 ------------------------------------------------------btnmatrix--------------------------------------------------- 

定义按钮数组,最后一个元素必须为空 :static const char *map[] = { "btn1", "\n", "btn2", "btn3", "" };
设置按钮 :lv_btnmatrix_set_map(btnm, map);
设置按钮相对宽度:lv_btnmatrix_set_btn_width(btnm, id, width);        /* 索引 (id) 从0开始,宽度1~7 ( 默认为1 ) */
获取索引 :lv_btnmatrix_get_selected_btn(btnm);    
获取文本 :lv_btnmatrix_get_btn_text(btnm, id);
设置单个按钮属性 :lv_btnmatrix_set_btn_ctrl(btnm, id, LV_BTNMATRIX_CTRL_...);
清除单个按钮属性 :lv_btnmatrix_clear_btn_ctrl(btnm, id, LV_BTNMATRIX_CTRL_...);    
设置所有按钮属性 :lv_btnmatrix_set_btn_ctrl_all(btnm, LV_BTNMATRIX_CTRL_...);

enum {
    LV_BTNMATRIX_CTRL_HIDDEN,                     /* 隐藏 */
    LV_BTNMATRIX_CTRL_DISABLED,                    /* 失能 */
    LV_BTNMATRIX_CTRL_CHECKABLE,                     /* 允许状态切换 */
    LV_BTNMATRIX_CTRL_RECOLOR,                     /* 允许文本重新着色 */
};
设置单次选中属性:lv_btnmatrix_set_one_checked(btnm, true);         /* 注意:需要先设置允许状态切换属性 */

* 按钮矩阵(优化界面) */
    lv_obj_set_style_border_width(btnm, 0, LV_PART_MAIN);                                       /* 去除主体边框 */
    lv_obj_set_style_bg_opa(btnm, 0, LV_PART_MAIN);                                             /* 设置主体背景透明度 */
    lv_obj_set_style_bg_opa(btnm, 0, LV_PART_ITEMS);                                            /* 设置按钮背景透明度 */
    lv_obj_set_style_shadow_width(btnm, 0, LV_PART_ITEMS);                                      /* 去除按钮阴影 */
    lv_obj_add_event_cb(btnm, b

 ------------------------------------------------------textarea--------------------------------------------------- 

 添加一个字符到当前光标处 :lv_textarea_add_char(ta, 'A');
添加字符串到当前光标处 :lv_textarea_add_text(ta, "BCDEF"); 
创建键盘部件 :lv_obj_t *keyboard = lv_keyboard_create(lv_scr_act());
关联键盘和文本区域部件 :lv_keyboard_set_textarea(keyboard, ta);
设置光标位置:lv_textarea_set_cursor_pos(ta, 0);          /* 0:最左侧, LV_TEXTAREA_CURSOR_LAST:最右侧 */
删除文本:
    lv_textarea_del_char(ta);            /* 删除光标左侧的一个字符 */
    lv_textarea_del_char_forward(ta);        /* 删除光标右侧的一个字符 */
设置模式:
    lv_textarea_set_one_line(ta, true);        /* 单行模式 */
    lv_textarea_set_password_mode(ta, true);        /* 密码模式(隐藏输入的内容) */
    lv_textarea_set_password_show_time(ta, 100);    /* 密码显示时间 */
限制字符输入:
    lv_textarea_set_accepted_chars(ta,"0123456789");     /* 限制接收的字符 */
    lv_textarea_set_max_length(ta,6);        /* 限制字符长度 */
设置占位符:lv_textarea_set_placeholder_text(ta, "password");     /* 提示输入密码 */
获取文本:const char *txt = lv_textarea_get_text(ta);        /* 获取文本框文本 */ 
比对文本内容:strcmp(const char *s1,const char *s2);        /* 当s1=s2时,返回0 */
创建键盘:keyboard = lv_keyboard_create(lv_scr_act());
关联用户名文本框和键盘:lv_keyboard_set_textarea(keyboard, target);

 ------------------------------------------------------keyboard---------------------------------------------------  

创建文本区域部件 :lv_obj_t *ta = lv_textarea_create(lv_scr_act());
关联键盘和文本区域部件 :lv_keyboard_set_textarea(kb, ta);
允许按键弹窗提示 :lv_keyboard_set_popovers(kb, true);
数字键盘模式 :lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER);
获取模式:lv_keyboard_get_mode(target); 

 ------------------------------------------------------imgbtn--------------------------------------------------- 

设置某个状态的图片源 :lv_imgbtn_set_src(imgbtn, LV_IMGBTN_STATE_..., src_left, src_mid, src_right);  //可以同时设置三张
设置图片按钮大小 :lv_obj_set_size(imgbtn, 64 * 3, 64);    
设置按下状态 :lv_imgbtn_set_state(imgbtn, LV_IMGBTN_STATE_PRESSED);
如何显示带有透明度通道的图片:准备一张带有透明度通道的图片,然后重新着色并设置透明度为255。
设置图片重新着色透明度: lv_obj_set_style_img_recolor_opa(target, 255, 0); 
设置图片重新着色 :lv_obj_set_style_img_recolor(target, lv_color_hex(0x00a9ff), 0); 

 ------------------------------------------------------tabview--------------------------------------------------- 

创建选项卡部件 :lv_obj_t  *tabview =  lv_tabview_create(parent, LV_DIR_..., tab_size);
添加选项卡:lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Tab 1"); 
设置当前选中的选项卡:lv_tabview_set_act(tabview, 1, LV_ANIM_OFF);      /* 索引从0开始 */
未选中部分:LV_STATE_DEFAULT例如将一个字体应用到全部的部分
选中部分:LV_STATE_CHECKED
设置按钮边框宽度为0:lv_obj_set_style_border_width(btn, 0, LV_PART_ITEMS| LV_STATE_CHECKED);
获取按钮部分:lv_obj_t *btn = lv_tabview_get_tab_btns(tabview); 
获取主体部分:lv_obj_t *obj = lv_tabview_get_content(tabview); 
清除滑动:lv_obj_clear_flag(lv_tabview_get_content(tabview), LV_OBJ_FLAG_SCROLLABLE);
LV_PART_ITEMS:按键 

------------------------------------------------------tileview--------------------------------------------------- 

创建平铺视图部件 :lv_obj_t  *tileview = lv_tileview_create( parent );
添加页面:lv_obj_t *tile1 = lv_tileview_add_tile( tileview, 0, 0, LV_DIR_RIGHT );
更新参数 :lv_obj_update_layout( tileview );
根据页面对象设置 :lv_obj_set_tile( tileview, tile2, LV_ANIM_OFF );
根据页面行列设置 :lv_obj_set_tile_id( tileview, 1, 0, LV_ANIM_OFF );
同时设置多少文字:lv_label_set_text(label_left,LV_SYMBOL_WIFI "  80%" LV_SYMBOL_BATTERY_3); 

------------------------------------------------------win---------------------------------------------------  

创建窗口部件 :lv_obj_t *win = lv_win_create(parent, header_height);
添加标题:lv_obj_t *title = lv_win_add_title(win, "Setting");
添加按钮:lv_obj_t *btn = lv_win_add_btn(win, LV_SYMBOL_CLOSE, 20);
添加主体内容:
      获取主体 :lv_obj_t *content = lv_win_get_content(win); 
      添加内容 :lv_obj_t *label = lv_label_create(content);    
隐藏窗口:lv_obj_add_flag(win, LV_OBJ_FLAG_HIDDEN);
清除显示:lv_obj_clear_flag(win,LV_OBJ_FLAG_HIDDEN);
设置按键符号的颜色要用设置文本:lv_obj_set_style_text_color(btn_setting, lv_color_hex(0x000000), LV_STATE_DEFAULT);         /* 设置文本颜色 */ 

------------------------------------------------------msgbox---------------------------------------------------  

 

 创建消息框部件 :
    static const char *btns[] = { "Continue", "Close", "" };
    lv_obj_t *msgbox = lv_msgbox_create( lv_scr_act(), "Notice", "Do you want to continue?", btns, true );
关闭消息框:lv_msgbox_close(msgbox);
获取按钮索引、文本:
    lv_obj_t *target = lv_event_get_current_target(e);    /* 获取当前触发源  用的是current_target 用_target会错误*/
    lv_msgbox_get_active_btn(target);/* 获取按钮索引 */
    lv_msgbox_get_active_btn_text(target);    /* 获取按钮文本 */
获取两个之中最小的:LV_MIN(lv_obj_get_width(obj);
记得更新,否则加载不出:lv_obj_update_layout(msgbox_obj); 
       lv_style_set_radius(&style_bullet, LV_RADIUS_CIRCLE);        //设置半径,传入'LV_RADIUS_CIRCLE'智能判断绘制为圆形
或者回调函数传入的用户数据:lv_obj_ * obj_color = (lv_obj_t *)e->user_data;
消息部件隐藏不用的按键:
      lv_obj_set_style_bg_opa(btn,0,LV_PART_ITEMS);
      lv_obj_set_style_shadow_width(btn,0,LV_PART_ITEMS);

------------------------------------------------------spinbox---------------------------------------------------  

 

创建微调器部件 :lv_obj_t *spinbox = lv_spinbox_create(parent);
数值递增:lv_spinbox_increment(spinbox);    
数值递减:lv_spinbox_decrement(spinbox);
设置步进值:lv_spinbox_set_step(spinbox, 200);/* 设置步进值,默认为1*/
设置范围值:lv_spinbox_set_range(spinbox, -1000, 1000);/* 设置范围值,默认±99999*/
设置当前值:lv_spinbox_set_value(spinbox, 400);
设置数字格式:lv_spinbox_set_digit_format(spinbox, 4, 2); /* 设置数字位数、小数点位置 */
设置光标位置:lv_spinbox_set_pos(spinbox, 3);   //使用该函数就不要使用设置步进值函数
获取当前值:lv_spinbox_get_value(spinbox);/* 返回值为整数,而非小数 */    
在按键上添加图片:lv_obj_set_style_bg_img_src(spinbox_btn1,LV_SYMBOL_PLUS,LV_PART_MAIN);
整数化成小数形式: lv_label_set_text_fmt(parameter,"%s%d.%d",
                          spinbox_value < 0 ? "-":"+",
                          spinbox_value / 10 < 0 ? -spinbox_value /10 : spinbox_value/10,
                          spinbox_value % 10 < 0 ? -spinbox_value % 10 : spinbox_value % 10);

------------------------------------------------------table---------------------------------------------------   

创建表格部件 :lv_obj_t *table = lv_table_create(parent);
设置行数:lv_table_set_row_cnt(table,2); 
设置列数:lv_table_set_col_cnt(table,2); 
设置列的宽度 :lv_table_set_col_width(table, 1, 200); 
设置单元格的内容:lv_table_set_cell_value(table, 0, 0, "123");
格式化输入,类似printf :lv_table_set_cell_value_fmt(table, 1, 0, "%d", 100 );

#if 的用法:
#if (1 != LV_FONT_MONTSERRAT_38 || 1 != LV_FONT_MONTSERRAT_18 || 1 != LV_FONT_MONTSERRAT_20)
#error Please Make Sure Enable LV_FONT_MONTSERRAT_14 & LV_FONT_MONTSERRAT_18 & LV_FONT_MONTSERRAT_20
#endif

第一次见的算法:
 for (uint8_t i = 1; i < (10 >> 1) + 1; i++)
        lv_table_set_cell_value_fmt(table, 2 * i, 1, "Value %d", i - 1);
 for (uint8_t i = 1; i < (10 >> 1) + 2; i++)
        lv_table_set_cell_value_fmt(table, 2 * i - 1, 1, "Hide %d", i - 1);

Data:23.1.10

5、GUI-GURDER

 GUI GUIDER 应用笔记_MR_普罗米修斯的博客-CSDN博客_gui guider

LVGL-GUI Guider初始体验_云海无语的博客-CSDN博客_gui-guider

LVGL | GUI-Guider的使用分享_嵌入式大杂烩的博客-CSDN博客_gui-guider

十几分钟学会如何使用lvgl设计器gui guider和模拟器编写一个简单计算器应用_哔哩哔哩_bilibili

快速入门入LVGL第四期--Gui-Guuder使用_哔哩哔哩_bilibili

南山府嵌入式的博客_CSDN博客-玩转STM32基础篇,FreeRTOS基础知识篇,分享领域博主

TIP:使用VScode编译并运行时因为系统环境变量有mingw 的编译器导致编译失败

 

 去掉之前即可,但用VScode编译运行速度不如GUI-guider,故此后面不要VScode编译运行。

简单计算机的实现逻辑:

/**
 * @file custom.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include <stdio.h>
#include "lvgl.h"
#include "custom.h"

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/

/**********************
 *  STATIC VARIABLES
 **********************/

/**
 * Create a demo application
 */

static int get_result(int old,int oper,int value)
{
    int result = 0;
    switch (oper)
    {
    case 0:
        result = value;
        break;
    case 3:
        result = old + value;
        break;
    case 7:
        result = old - value;
        break;
    case 11:
        result = old*value;
        break;
    case 15:
        result = old/value;
        break;
    default:
        break;
    }
    return result;
}
void text_cb(lv_event_t* e)
{
    lv_ui * ui = lv_event_get_user_data(e);
    uint8_t id = lv_btnmatrix_get_selected_btn(ui->screen_btnm_1);
    const char * txt = lv_btnmatrix_get_btn_text(ui->screen_btnm_1,id);

    static int old = 0;
    static int oper = 0;
    int value = 0;
    static char num[10] = {0};


    switch (id)
    {
    case 3:
        printf("+\n");
        
    case 7:
        printf("-\n");
    case 11:
        printf("x\n");
    case 15:
        printf("/\n");
        sscanf(num,"%d",&value);                                //将现在显示的数字提取出来
        old = get_result(old,oper,value);                       //之前的内容运算出结果并保存
        lv_label_set_text_fmt(ui->screen_label_1,"%d",old);     //把之前的运算结果显示出
        oper = id ;                                             //保存当前的运算符
        memset(num,0,sizeof(num));                              //清空之前记录的显示缓存
        break;
    case 14:
        printf("=\n");
        sscanf(num,"%d",&value);                     //将现在显示的数字提取出来
        old = get_result(old,oper,value);            //之前的内容运算出结果并保存
        lv_label_set_text_fmt(ui->screen_label_1,"%d",old);   //把之前的运算结果显示出
        oper = 0 ;                                   //清空运算符
        old = 0;                                     //清空历史记录
        memset(num,0,sizeof(num));                   //清空之前记录的显示缓存
        break;
    case 12:
        printf("clean\n");
        lv_label_set_text(ui->screen_label_1,"");   //清除显示
        oper = 0 ;                                  //清空运算符
        old = 0;                                    //清空历史记录
        memset(num,0,sizeof(num));                  //清空之前记录的显示缓存
        break;
    default:
        printf("%s\n",txt);
        if (strlen(num)<sizeof(num)-1)
        {
            strcat(num,txt);
            lv_label_set_text(ui->screen_label_1,num);
        }
        
        break;
    }
}

void custom_init(lv_ui *ui)
{
    /* Add your codes here */
    lv_obj_add_event_cb(ui->screen_btnm_1,text_cb,LV_EVENT_PRESSED,ui);
}

23.1.5

6、多屏幕切换、动画【esp32&lvgl】-2.6 #lvgl-多页面(screen)设定/切换_lv_scr_load_anim_weixin_43326110的博客-CSDN博客 

6.2多屏幕切换

   /********tow_scr*************/
lv_obj_t * Scr_mainMenu;
lv_obj_t * Scr_wifi;
void Scr_1_cb(lv_event_t * e)
{
     lv_event_code_t code = lv_event_get_code(e);
     if(code == LV_EVENT_CLICKED)
     {
         /*设置页面加载动画*/
         lv_scr_load_anim(Scr_wifi, LV_SCR_LOAD_ANIM_NONE, 100, 0, false);
         lv_scr_load(Scr_wifi);
     }
}

void my_gui()
{
#if 1
    /********tow_scr*************/
    /*创建页面*/
    Scr_mainMenu = lv_obj_create(NULL);
    lv_obj_clean(Scr_mainMenu);
    lv_obj_remove_style_all(Scr_mainMenu);
    lv_obj_set_style_bg_opa(Scr_mainMenu, LV_OPA_COVER, 0);//0不透明
    lv_obj_set_style_bg_color(Scr_mainMenu, lv_color_hex(0xDaDaDa), 0);
    lv_obj_set_size(Scr_mainMenu, LV_HOR_RES, LV_VER_RES);
    lv_obj_t * Scr_1_btn = lv_btn_create(Scr_mainMenu);
    lv_obj_t * Scr_1_labl = lv_label_create(Scr_1_btn);
    lv_label_set_text(Scr_1_labl,"next page");
    lv_obj_add_event_cb(Scr_1_btn,Scr_1_cb,LV_EVENT_CLICKED,NULL);

    Scr_wifi = lv_obj_create(NULL);
    lv_obj_clean(Scr_wifi);
    lv_obj_remove_style_all(Scr_wifi);
    lv_obj_set_style_bg_opa(Scr_wifi, LV_OPA_COVER, 0);//0不透明
    lv_obj_set_style_bg_color(Scr_wifi, lv_color_hex(0x8a8a8a), 0);
    lv_obj_set_size(Scr_wifi, LV_HOR_RES, LV_VER_RES);
    lv_obj_t * Scr_2_btn = lv_btn_create(Scr_wifi);
    lv_obj_t * Scr_2_labl = lv_label_create(Scr_2_btn);
    lv_label_set_text(Scr_2_labl,"before page");
    lv_obj_add_event_cb(Scr_2_btn,Scr_2_cb,LV_EVENT_CLICKED,NULL);

    /*加载一个页面*/
    lv_scr_load(Scr_wifi);

#endif
}

6.2动画

/*******animation********/
static void anim_x_cb(void* var, int32_t v)
{
    lv_obj_set_x(var, v);
}

void my_gui()
{

#if 1
 /*******animation********/
/* 第一步:创建标签 */
 lv_obj_t* lv_obj = lv_label_create(lv_scr_act());
 lv_label_set_text(lv_obj,"ALIENTEK");
 lv_obj_set_pos(lv_obj, 400, 10);
 lv_obj_update_layout(lv_obj);
 /* 第二步:动画初始化 */
 lv_anim_t a;
 lv_anim_init(&a);
 /* 第三步:设置动画目标为标签对象 */
 lv_anim_set_var(&a, lv_obj);
 /* 第四步:设置动画起点和终点 */
 lv_anim_set_values(&a, lv_obj_get_x(lv_obj), 0);
 /* 第五步:设置动画时间 */
 lv_anim_set_time(&a, 5000);
 /* 第六步:设置动画回调函数 */
 lv_anim_set_exec_cb(&a, anim_x_cb);
 /* 第七步:设置动画轨道 */
 lv_anim_set_path_cb(&a, lv_anim_path_bounce);
 /* 第八步:设置动画轨道 */
 lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
 /* 第九步:开启动画 */
 lv_anim_start(&a);
}

LVGL库入门教程 - 动画 - 冰封残烛 - 博客园

6.3:事件冒泡

https://blog.csdn.net/qq_41650023/article/details/125260000

6.4:GUI-Guider编写事件回调

6.5:GUI-Guider生成的代码移植CodeBlocks

1. 新建lvgl_app将GUI-Guider生成的custom、generated文件复制粘贴。

2.在CodeBlocks中递归添加lvgl_app文件

3.编译并修改新添加文件头文件问题

4.添加 guider_ui的相关代码到main

参考文章:LVGL-GUI Guider生成工程移植Keil_gui guider移植_云海无语的博客-CSDN博客

codeblocks添加头文件路径包含_codeblocks头文件路径_dzdesigned的博客-CSDN博客

ESP32+LVGL笔记(2):学习B站的计算器例程_lvgl设计计算器_hwd00001的博客-CSDN博客

GUI Guider与lvgl联合仿真(结合stm32实验进行演示,含触摸屏实验计数器与计算器)_古道小七的博客-CSDN博客_lv_obj_set_scrollbar_mode

23.1.31 

codeblock编译问题找了快一周的原因,GUI_Guider生成代码移植到codeblock,时不时出现编译最后 No such file or directory 有时不会出现有时会。网上找寻答案试过各种方法都无效。最后修改文件名解决了?????我怀疑是文件名与gui_guider.h冲突导致。

 

 

 

修改后正常运行 

头文件名可以不分大小写

 

23.2.28

上述问题是编译器找不到生成的图片源文件导致,吧image文件夹放到工作文件的外外层就不报错,在eclipse下就不存在上述问题(22.3.8)

23.4.19

上述问题为头文件路径问题

正确添加头文件设置

(85条消息) codeblocks添加头文件路径包含-CSDN博客 

7.页面逻辑实现

7.1:设置页面的前端实现,页面要求,lvgl弹出对话框,只允许触摸对话框,其他地方不许触摸,例如电脑和手机弹出对话框,必须触摸关闭当前对话框,才能触摸其他地方。

方法一:

1:首先将设置页面创建并将页面隐藏: lv_obj_add_flag(win,LV_OBJ_FLAG_HIDDEN): 

2:通关点击设置按键在事件中将设置页面显示出lv_obj_clear_flag(win,LV_OBJ_FLAG_HIDDEN);

3:将设置页面置于前景:lv_obj_move_foreground(win);

4:关掉后面对象的点击事件:lv_obj_clear_flag(btn_win,LV_OBJ_FLAG_CLICKABLE);

/********win*************/
lv_obj_t * win;
lv_obj_t * btn_win;
void win_cb(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    lv_event_code_t event = lv_event_get_code(e);
    if(event == LV_EVENT_CLICKED)
    {
        lv_obj_add_flag(btn_win,LV_OBJ_FLAG_CLICKABLE);
        lv_obj_add_flag(win,LV_OBJ_FLAG_HIDDEN);
    }
}

void btn_cb(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    lv_event_code_t event = lv_event_get_code(e);
    if(event == LV_EVENT_CLICKED)
    {
        lv_obj_clear_flag(btn_win,LV_OBJ_FLAG_CLICKABLE);
        lv_obj_clear_flag(win,LV_OBJ_FLAG_HIDDEN);
        lv_obj_move_foreground(win);
    }
}

lv_obj_t * my_slider_creat(lv_obj_t * content,const char* symbol,lv_coord_t x_ofs,lv_coord_t y_ofs)
{
    lv_obj_t * slider = lv_slider_create(content);
    lv_obj_set_size(slider,scr_width/3,scr_hight/30);
    lv_slider_set_value(slider,50,LV_ANIM_OFF);
    lv_obj_align(slider, LV_ALIGN_CENTER,x_ofs,y_ofs);
    lv_obj_set_style_bg_color(slider,lv_color_hex(0x787c78), LV_PART_MAIN);
    lv_obj_set_style_bg_color(slider,lv_color_hex(0xc3c3c3), LV_PART_INDICATOR);
    lv_obj_remove_style(slider,NULL,LV_PART_KNOB);

    lv_obj_t * label = lv_label_create(content);
    lv_label_set_text(label,symbol);
    lv_obj_align_to(label,slider,LV_ALIGN_OUT_LEFT_MID,-10,0);

    return slider;

}

/********win*************/
void my_gui()
{

    win = lv_win_create(lv_scr_act(),scr_hight/12);
    lv_obj_set_size(win,scr_width*5/8,scr_hight*4/7);
    lv_obj_set_style_border_width(win,1,LV_STATE_DEFAULT);
    lv_obj_set_style_border_color(win,lv_color_hex(0x8a8a8a),LV_STATE_DEFAULT);
    lv_obj_set_style_border_opa(win,100,LV_STATE_DEFAULT);
    lv_obj_set_style_radius(win,10,LV_STATE_DEFAULT);
    lv_obj_center(win);

    lv_obj_t * btn_left = lv_win_add_btn(win,LV_SYMBOL_SETTINGS,20);
    lv_obj_set_style_bg_opa(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_left,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_t * title = lv_win_add_title(win,"Setting");
    lv_obj_set_style_text_font(title,&lv_font_montserrat_18,LV_STATE_DEFAULT);
    lv_obj_add_flag(win,LV_OBJ_FLAG_HIDDEN);

    lv_obj_t * btn_right = lv_win_add_btn(win,LV_SYMBOL_CLOSE,20);
    lv_obj_set_style_bg_opa(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0xff0000),LV_STATE_PRESSED);
    lv_obj_add_event_cb(btn_right,win_cb,LV_EVENT_CLICKED,NULL);

    lv_obj_t * content = lv_win_get_content(win);
    lv_obj_t * slider_1 = my_slider_creat(content,LV_SYMBOL_AUDIO,15, -scr_hight/14);
    lv_obj_t * slider_2 = my_slider_creat(content,LV_SYMBOL_BELL,15, scr_hight/14);

    /*SET按键*/
    lv_obj_t * btn = lv_btn_create(lv_scr_act());
    lv_obj_align(btn,LV_ALIGN_BOTTOM_MID,0,0);
    lv_obj_t* label;
    label = lv_label_create(btn);
    lv_label_set_text(label, "Set");
    lv_obj_center(label);
    lv_obj_update_layout(label);
    lv_obj_add_event_cb(btn,btn_cb,LV_EVENT_CLICKED,NULL);


    lv_obj_t * obj_win = lv_obj_create(lv_scr_act());
    lv_obj_set_size(obj_win,400,300);
    btn_win = lv_btn_create(obj_win);
    lv_obj_align(btn_win,LV_ALIGN_OUT_LEFT_MID,0,0);

}

方法二:

使用模态对话框,他设置按键回调事件中在layer_top层创建设置界面,并启用了click属性,layer_top将吸收所有用户点击并充当模态 。设置页面关闭后删除设置界面。

/**********模态对话框***********/
void close_btn_cb(lv_event_t * e)
{
    lv_obj_t * target = lv_event_get_target(e);
    lv_event_code_t event = lv_event_get_code(e);
    if(event == LV_EVENT_CLICKED)
    {
        lv_obj_del(win);           // 删除对象及其所有子对象
        win = NULL;
        lv_obj_clear_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);   // 清除标志
        lv_obj_set_style_bg_opa(lv_layer_top(), LV_OPA_TRANSP, 0);  // 设置透明度
    }
}

static void ste_btn_cb(lv_event_t * e)
{
    lv_event_code_t code = lv_event_get_code(e);
    lv_obj_t * ta = lv_event_get_target(e);

    if(code == LV_EVENT_CLICKED) {
            if(win == NULL) {
    //设置弹窗
    lv_obj_add_flag(lv_layer_top(), LV_OBJ_FLAG_CLICKABLE);                         // 使能 lv_layer_top 点击
    win = lv_win_create(lv_layer_top(),scr_hight/12);                               // 在 lv_layer_top 层上创建日历对象
    lv_obj_set_style_bg_opa(lv_layer_top(), LV_OPA_50, 0);                          // 设置对象透明度
    lv_obj_set_style_bg_color(lv_layer_top(), lv_palette_main(LV_PALETTE_GREY), 0); // 设置对象颜色
    lv_obj_set_size(win,scr_width*5/8,scr_hight*4/7);
    lv_obj_set_style_border_width(win,1,LV_STATE_DEFAULT);
    lv_obj_set_style_border_color(win,lv_color_hex(0x8a8a8a),LV_STATE_DEFAULT);
    lv_obj_set_style_border_opa(win,100,LV_STATE_DEFAULT);
    lv_obj_set_style_radius(win,10,LV_STATE_DEFAULT);
    lv_obj_center(win);

    //顶部左边设置logo
    lv_obj_t * btn_left = lv_win_add_btn(win,LV_SYMBOL_SETTINGS,20);
    lv_obj_set_style_bg_opa(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_left,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_left,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_t * title = lv_win_add_title(win,"Setting");
    lv_obj_set_style_text_font(title,&lv_font_montserrat_18,LV_STATE_DEFAULT);

    //顶部右边关闭logo
    lv_obj_t * btn_right = lv_win_add_btn(win,LV_SYMBOL_CLOSE,20);
    lv_obj_set_style_bg_opa(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_shadow_width(btn_right,0,LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0x000000),LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(btn_right,lv_color_hex(0xff0000),LV_STATE_PRESSED);
    lv_obj_add_event_cb(btn_right,close_btn_cb,LV_EVENT_CLICKED,NULL);

    //滑块
    lv_obj_t * content = lv_win_get_content(win);
    lv_obj_t * slider_1 = my_slider_creat(content,LV_SYMBOL_AUDIO,15, -scr_hight/14);
    lv_obj_t * slider_2 = my_slider_creat(content,LV_SYMBOL_BELL,15, scr_hight/14);

        }
    }
}
/**********模态对话框***********/
void my_gui()
{

    lv_obj_t * btn = lv_btn_create(lv_scr_act());
    lv_obj_align(btn,LV_ALIGN_BOTTOM_MID,0,0);
    lv_obj_t* label;
    label = lv_label_create(btn);
    lv_label_set_text(label, "Set");
    lv_obj_center(label);
    lv_obj_update_layout(label);
    lv_obj_add_event_cb(btn,ste_btn_cb,LV_EVENT_CLICKED,NULL);

    lv_obj_t * bg_obj_win = lv_obj_create(lv_scr_act());
    lv_obj_set_size(bg_obj_win,400,300);
    btn_win = lv_btn_create(bg_obj_win);
    lv_obj_align(btn_win,LV_ALIGN_OUT_LEFT_MID,0,0);
}

 23.2.2

参考文章:icore4tlvgl_9 []

LVGL|lvgl教程之巧用图层(layer)编写模态对话框_挨踢民工biubiu的博客-CSDN博客_lv_layer_sys

8.mune菜单控件

这个控件各个视频教程都没有提及到,偶然控看见有这个控件,在V8.2版本中,才发现正点原子的CodeBlock是8.0的版本,并无munu控件,改用百问网的8.2工程

LVGL 8.2 菜单_lvgl 菜单_仙剑情缘的博客-CSDN博客

LVGL库入门教程 - 动画 - 自由资讯

8.1 content容器铺满问题

默认情况下在content下添加组件是不铺满有边距的

解决办法:lv_style_set_pad_all 

    static lv_style_t cont_style;   // 容器的样式
	lv_style_init(&cont_style);
	lv_style_set_pad_all(&cont_style, 0);  // 铺满(新添加的一行代码)
	lv_obj_add_style(ui->screen_select_prescription_win_content, &cont_style, 0);
	lv_obj_set_size(ui->screen_select_prescription_list_1, 200,400*4/7);

参考文章:LVGL|lvgl教程之flex布局铺满整个容器(弹性布局铺满整个容器)_挨踢民工biubiu的博客-CSDN博客_flex布局高度铺满

23.2.9 

lvgl 增加自定义SYMBOL_徐满华的博客-CSDN博客_lvgl自定义图标仙剑情缘的博客_CSDN博客-C/C++,little VGL,NRF52832个人学习笔记领域博主

8.2 menu相关

8 编码器

LVGL如何使用编码器 - 知乎 (zhihu.com)

(71条消息) lvgl使用旋转编码器做为外部输入设备_lvgl 编码器_我来过了.的博客-CSDN博客

(71条消息) STM32移植LVGL+旋转编码器接口对接_lvgl 编码器_IMSHYANNE的博客-CSDN博客

【开源】ESP32 Arduino LVGL8 编码器EC11输入 演示demo_哔哩哔哩_bilibili

(86条消息) LVGL V8应用——通过按键切换页面_lvgl 页面切换_临界msp的博客-CSDN博客

(86条消息) 【LVGL】学习笔记--(3)界面切换以及显示优化_lvgl界面切换_公子无缘的博客-CSDN博客

9 主题模式

 0:为明亮

 1:为暗色

设置主题:粉色

static const lv_font_t * font_normal;
lv_theme_default_init(NULL, lv_palette_main(LV_PALETTE_PINK), lv_palette_main(LV_PALETTE_BLUE), LV_THEME_DEFAULT_DARK, font_normal);

默认为蓝色:

 

 (85条消息) LVGL学习笔记4 - 主题Themes_lvgl主题-CSDN博客

static lv_style_t gThemeRectStyle;
static void new_theme_apply_cb(lv_theme_t* th, lv_obj_t* obj)
{
    if (lv_obj_check_type(obj, &lv_obj_class))
    {
        lv_obj_add_style(obj, &gThemeRectStyle, LV_STATE_DEFAULT);
    }
}
void set(){

    lv_obj_t* rect = lv_obj_create(lv_scr_act());
    lv_obj_set_size(rect, LV_PCT(20), LV_PCT(20));
    lv_obj_align(rect, LV_ALIGN_TOP_LEFT, 20, 20);

    /*Set a background color and a radius*/
    lv_style_init(&gThemeRectStyle);
    lv_style_set_radius(&gThemeRectStyle, 10);
    lv_style_set_bg_opa(&gThemeRectStyle, LV_OPA_COVER);
    lv_style_set_bg_color(&gThemeRectStyle, lv_palette_lighten(LV_PALETTE_RED, 1));

    /*Add a shadow*/
    lv_style_set_shadow_width(&gThemeRectStyle, 55);
    lv_style_set_shadow_color(&gThemeRectStyle, lv_palette_main(LV_PALETTE_BLUE));

    lv_obj_add_style(rect, &gThemeRectStyle, LV_PART_MAIN|LV_STATE_DEFAULT);

    /*通过当前主题初始化新主题*/
    lv_theme_t* th_active = lv_theme_get_from_obj(NULL);
    static lv_theme_t th_new;
    th_new = *th_active;

    /*设置父主题和新主题的样式适播放回调函数*/
    lv_theme_set_parent(&th_new, th_active);
    lv_theme_set_apply_cb(&th_new, new_theme_apply_cb);

    /*设置新主题*/
    lv_disp_set_theme(NULL, &th_new);

    lv_obj_t* rect2 = lv_obj_create(lv_scr_act());
    lv_obj_set_size(rect2, LV_PCT(20), LV_PCT(20));
    lv_obj_align(rect2, LV_ALIGN_TOP_LEFT, 220, 20);

    lv_obj_t* rect3 = lv_obj_create(lv_scr_act());
    lv_obj_set_size(rect3, LV_PCT(20), LV_PCT(20));
    lv_obj_align(rect3, LV_ALIGN_TOP_LEFT, 420, 20);
}

猜你喜欢

转载自blog.csdn.net/qq_45803449/article/details/128419441