LVGL(轻量级 GUI)
一、为什么选 LVGL
- 极轻量(RAM < 64KB)
- 嵌入式首选:性能强、资源省
- 自带控件丰富(按钮、滑块、列表、图表、键盘)
- 支持 Framebuffer、SDL、Drm、X11
- MIT 协议、可商用
二、获取与编译
git clone https://github.com/lvgl/lvgl.git
git clone https://github.com/lvgl/lv_demos.git
git clone https://github.com/lvgl/lv_drivers.git # 驱动(fbdev、sdl)
cd lvgl
mkdir build && cd build
cmake .. -DLVGL_CHOSEN_DEMO_MUSIC=1
make
三、集成到项目
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(myapp)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(lvgl)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE lvgl)
target_include_directories(myapp PRIVATE lvgl)
四、Hello LVGL
// main.cpp
#include "lvgl.h"
int main(void)
{
lv_init();
// 1. 驱动初始化(framebuffer)
lv_display_t *disp = lv_linux_fbdev_create();
lv_linux_fbdev_set_file(disp, "/dev/fb0");
// 2. 鼠标 / 触摸
lv_indev_t *indev = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event0");
// 3. UI
lv_obj_t *label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Hello LVGL!");
lv_obj_center(label);
// 4. 主循环
while (1) {
lv_timer_handler();
usleep(5000);
}
return 0;
}
五、常用组件
// 按钮
lv_obj_t *btn = lv_button_create(lv_screen_active());
lv_obj_set_size(btn, 100, 50);
lv_obj_center(btn);
lv_obj_add_event_cb(btn, my_event_cb, LV_EVENT_CLICKED, NULL);
lv_obj_t *label = lv_label_create(btn);
lv_label_set_text(label, "Click Me");
lv_obj_center(label);
// 滑块
lv_obj_t *slider = lv_slider_create(lv_screen_active());
lv_slider_set_value(slider, 50, LV_ANIM_ON);
// 标签
lv_obj_t *label = lv_label_create(lv_screen_active());
lv_label_set_text(label, "Hello");
// 图像
LV_IMAGE_DECLARE(my_img);
lv_obj_t *img = lv_image_create(lv_screen_active());
lv_image_set_src(img, &my_img);
六、主题
lv_theme_t *th = lv_theme_default_init(lv_display_get_default(),
lv_palette_main(LV_PALETTE_BLUE),
lv_palette_main(LV_PALETTE_RED),
true, LV_FONT_DEFAULT);
lv_display_set_theme(lv_display_get_default(), th);
七、字体
// 编译时
LV_FONT_DECLARE(my_font_32)
lv_obj_set_style_text_font(label, &my_font_32, 0);
// 或启用自带
LV_FONT_MONTSERRAT_32
LV_FONT_DEJAVU_16
LV_FONT_UNSCII_8
八、动画
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, obj);
lv_anim_set_values(&a, 0, 100);
lv_anim_set_time(&a, 1000);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_x);
lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out);
lv_anim_start(&a);
九、移植到新平台
需要实现 3 个 tick:
uint32_t my_tick_get(void) {
static uint64_t start_ms = 0;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t now_ms = (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
if (start_ms == 0) start_ms = now_ms;
return (uint32_t)(now_ms - start_ms);
}
// LVGL 8.x
lv_tick_set_cb(my_tick_get);
十、显示缓冲(避免撕裂)
static lv_draw_buf_t buf;
static lv_color_t buf1[DISP_WIDTH * 10 * sizeof(lv_color16_t)];
lv_display_set_buffers(disp, buf1, NULL, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);
十一、触摸支持
static void my_input_read(lv_indev_t *indev, lv_indev_data_t *data) {
// 读触摸
if (touch_pressed()) {
data->point.x = touch_x;
data->point.y = touch_y;
data->state = LV_INDEV_STATE_PRESSED;
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
lv_indev_t *indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, my_input_read);
十二、内存监控
lv_mem_monitor_t mon;
lv_mem_monitor(&mon);
printf("used: %d%% (%d/%d)\n", mon.used_pct, mon.used_size, mon.total_size);
十三、LVGL 与 Linux
- lv_drivers 提供:
lv_linux_fbdev.clv_linux_drm.c(DRM/KMS)lv_evdev.c(输入)lv_sdl.c(SDL2 调试用)
十四、嵌入式 LVGL 项目结构
// ui/
// ├── screens.h
// ├── screens.cpp
// ├── components/
// └── events.cpp
#include "screens.h"
void create_main_screen(void) {
lv_obj_t *scr = lv_obj_create(NULL);
// ...
lv_screen_load(scr);
}
十五、推荐资源
- 官方:https://lvgl.io
- 文档:https://docs.lvgl.io
- 模拟器:https://github.com/lvgl/lv_sim_vscode_sdl
- SquareLine Studio(拖拽式 UI 设计工具)
- EEZ Studio(开源 UI 设计工具)