为你的项目设计一个精美的 GUI





准备工作:
材料:
材料名称 | 数量 | 型号/说明/备注 |
LVGL | 1 | |
SquareLine Studio | 1 | |
Arduino IDE | 1 |
工具:
工具名称 | 数量 | 型号/说明/备注 |
计算机笔记本 | 1 |
为什么需要设计 UI?

用户体验在很大程度上决定了一个项目的成功程度。一个好的UI可以给人一个好的用户体验。
自从智能手机问世以来,用户熟悉了花哨的GUI。大多数最终用户现在都希望有一个好的 GUI,即使是一个小的简单项目。
LVGL 和 SquareLine Studio




相比之下,从头开始设计 GUI 非常耗时。我们需要一些工具来帮助简化工作。
LVGL 是一个很好的图形库,可以轻松制作花哨的 GUI。它有助于操作如何绘制每个小部件,如何在非常有限的资源下有效地管理绘制缓冲区,处理用户交互,动画计时等。但是如果从头开始编写代码,它仍然有一个学习曲线。
幸运的是,它有一个免费供个人使用的工具,称为 SquareLine Studio。它减少了所需的大量编码。换句话说,它可以帮助您在绘制设计后生成所有 GUI 初始代码。
软件准备

Arduino IDE集成电路
下载并安装Arduino IDE最新的1.x版本(如果尚未):
https://www.arduino.cc/en/software
Arduino-ESP32 (可选)
按照安装步骤添加 Arduino-ESP32 支持(如果尚未):
https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html
Arduino-Pico(可选)
按照安装步骤添加Arduino-Pico支持(如果尚未):
https://github.com/earlephilhower/arduino-pico
Arduino_GFX图书馆
通过选择“工具”菜单 ->“管理器库...”打开 Arduino IDE 库管理器。搜索“GFX for various displays”,然后按“安装”按钮。
你可以参考我的以前的指导有关Arduino_GFX的更多信息。
LVGL图书馆
通过选择“工具”菜单 ->“管理器库...”打开 Arduino IDE 库管理器。搜索“lvgl”,选择“lvgl”,然后按“安装”按钮。
安装LVGL库后,需要进行一些配置:
1.浏览到Arduino IDE库文件夹
2.将 libraries/lvgl/lv_conf_template.h 复制到 libraries/lv_conf.h
3.In lv_conf.h 在第 15 行左右,通过将 0 更改为 1 来启用配置文件:
#if 1
4.找到“LV_COLOR_DEPTH”并将值设置为16:
#define LV_COLOR_DEPTH 16
5.找到“LV_TICK_CUSTOM”并通过将 0 更改为 1 来启用它:
#define LV_TICK_CUSTOM 1
6.如果使用 SPI 或并行 8 显示,16 位颜色交换字节可以帮助提高性能。找到“LV_COLOR_16_SWAP”并通过将 0 更改为 1 来启用它:
#define LV_COLOR_16_SWAP 1
LVGL Hello World!

打开Arduino IDE
选择菜单项:“文件”->“示例”->“GFX for Arduino”->“LVGL”->“LvglHelloWorld”
滚动到Arduino_GFX设置部分,然后按照 Wiki 设置您的显示器
将开发设备连接到计算机,然后按Arduino IDE中的“上传”按钮
如果一切正常,您可以在中间看到“Hello Arduino”
使用项目名称保存项目,在以下步骤中添加了更多 UI
注意:
中间的文字在LVGL中称为标签,它是由3行代码动态生成的:
/* 创建简单标签 */
lv_obj_t *标签 = lv_label_create(lv_scr_act());
lv_label_set_text(标签,“你好Arduino!(V“GFX_STR(LVGL_VERSION_MAJOR)”。GFX_STR(LVGL_VERSION_MINOR)“。GFX_STR(LVGL_VERSION_PATCH) “)”);
lv_obj_align(标签, LV_ALIGN_CENTER, 0, 0);
如果您使用 SquareLine Studio 设计 UI,这些代码将由导出函数生成。
下载 SquareLine Studio

经过测试并保存了LVGL Hello World草图,是时候设计GUI了。从简单开始,我将使用一个小型面包板项目来演示设计过程。
首先,您需要在以下位置下载并安装SquareLine Studio:
https://squareline.io/downloads
安装后,您需要为第一次运行填写一些注册。
创建 SquareLine Studio 项目

打开 SquareLine Studio
- 选择“创建”
- 选择“Arduino”
- 填写您的屏幕分辨率
- 颜色深度选择“16位”或“16位交换”取决于lv_conf.h中的“LV_COLOR_16_SWAP”设置
- 为您的项目风格选择主题
- 按创建按钮
开始

中间有一个黑色方框。这是您设计的第一个屏幕。您可以在上方的栏目中调整缩放级别。
左侧上方列出了您正在使用的所有对象。一开始这里只有一个对象,即 Screen1。稍后您可以添加更多对象。下方列出了您可以添加到设计中的各种对象。
在右侧,您可以更改所选对象的参数。
插入第一个对象

让我们将第一个对象添加到屏幕上:
- 选择弧形小部件
- 弧形对象插入到屏幕并选择
- 在右侧选择调整一些参数:
- 宽度:128 像素
- 高度:128 像素
- 最大范围:50
- 值:25
- 背景起始角度:270
- Bg端角度:180
对于每个参数的变化,你都可以看到弧线发生相应的变化。
样式设置





继续选中圆弧对象,展开每个子部分,即可在右下角看到更多样式设置。按照屏幕截图更改设置,并在屏幕上查看效果。
添加标签




选择“标签”小部件,为弧形对象添加标签。按照屏幕截图更改设置,并在屏幕上查看效果。
添加值标签




值标签也是一个普通的标签,但标签文本会在程序运行时发生变化。因此,为了便于阅读,需要一个有意义的名称。如果名称设置为“Screen1 Label Temps”,则程序中的对象指针名称将是“ui_Screen1_Label_Temps”。只需在开头添加“ui_”,并将所有空格替换为下划线即可。
按照屏幕截图更改设置并在屏幕上查看效果。
导出设计

好的,现在已经在第一个屏幕中添加了 3 个对象。让我们尝试将设计导出到 Arduino 项目:
- 选择“导出”菜单 -> “导出 UI 文件”
- 浏览到之前保存的 LVGL hello world sketch 文件夹
- 按“打开”按钮
- 所有设计对象导出到草图文件夹
初始化 SquareLine 准备的 UI





在 Arduino IDE 中打开草图。您可以看到从 SquareLine Studio 导出的 4 个源文件。
在#include <lvgl.h> 下面附加#include "ui.h":
在 Sketch 的 ino 文件中搜索“/* Create simple label */”,并注释掉标签代码。然后在下面添加“ui_init();”:
然后按上传,您就可以看到显示屏显示设计屏幕。
更新对象值

下一步是学习如何在自定义代码中更新对象。
在 loop() 函数中,首先随机一个温度值:
然后将值设置为弧对象:
将值赋给标签需要更多步骤。标签对象需要字符串值,但温度是数字。首先,我们需要将数字转换为字符串:
然后再次按上传,就可以看到弧线和标签不断变化。
參考文獻:
https://docs.lvgl.io/8.3/widgets/core/arc.html
https://cplusplus.com/reference/cstdio/sprintf/
设计

设计是一项耗时的工作,但如果每个人都喜欢你的项目,那就值得了。
本项目以 BME680 传感器读数为例。BME680 可以感知温度、湿度、气压和空气质量。因此,主屏幕显示 4 个实时传感器值及其对应的弧形数值条。温度、湿度和空气质量会随时间变化,因此另外 3 个屏幕分别显示图表,以呈现随时间变化的数值。
过渡动画

自己编写对象过渡动画是一个痛苦的加入,计算过渡、时间控制、推文位置和把所有东西放在一起......等。所有的东西都在非常有限的 MCU 资源中工作。
在 LVGL 中,所有的事情都由框架处理。您只需调用动画命令即可:
lv_scr_load_anim(ui_Screen2, LV_SCR_LOAD_ANIM_MOVE_RIGHT, SCR_LOAD_ANIM_TIME, 0, 假);
添加按钮响应

2个按钮设计,用于切换屏幕。添加了 2 个处理屏幕过渡的功能:
无效 left_btn_pressed() {
if ((millis() - last_pressed) >= SCR_LOAD_ANIM_TIME) {
开关(current_screen) {
案例1:
lv_scr_load_anim(ui_Screen4, LV_SCR_LOAD_ANIM_MOVE_RIGHT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 4;
破;
案例2:
lv_scr_load_anim(ui_Screen1, LV_SCR_LOAD_ANIM_MOVE_RIGHT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 1;
破;
案例3:
lv_scr_load_anim(ui_Screen2, LV_SCR_LOAD_ANIM_MOVE_RIGHT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 2;
破;
违约:
lv_scr_load_anim(ui_Screen3, LV_SCR_LOAD_ANIM_MOVE_RIGHT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 3;
破;
}
last_pressed = 毫();
}
}
无效 right_btn_pressed() {
if ((millis() - last_pressed) >= SCR_LOAD_ANIM_TIME) {
开关(current_screen) {
案例1:
lv_scr_load_anim(ui_Screen2, LV_SCR_LOAD_ANIM_MOVE_LEFT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 2;
破;
案例2:
lv_scr_load_anim(ui_Screen3, LV_SCR_LOAD_ANIM_MOVE_LEFT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 3;
破;
案例3:
lv_scr_load_anim(ui_Screen4, LV_SCR_LOAD_ANIM_MOVE_LEFT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 4;
破;
违约:
lv_scr_load_anim(ui_Screen1, LV_SCR_LOAD_ANIM_MOVE_LEFT, SCR_LOAD_ANIM_TIME, 0, 假);
current_screen = 1;
破;
}
last_pressed = 毫();
}
}
然后在 setup() 函数中 init 按钮 GPIO:
/* 初始化按钮 */
pinMode(LEFT_BTN_PIN, INPUT_PULLUP);
attachInterrupt(LEFT_BTN_PIN, left_btn_pressed, FALLING);
pinMode(RIGHT_BTN_PIN, INPUT_PULLUP);
attachInterrupt(RIGHT_BTN_PIN, right_btn_pressed, FALLING);
完整示例源代码

完整的示例源代码可以在 Github 中找到:
https://github.com/moononournation/Design-a-Fancy-GUI-for-Your-Project











