
直接开始吧这篇文不废话。前段时间在Linux机器上折腾LVGL界面开发工具链用的是SquareLine Studio配合模拟器整个过程踩了不少坑。这玩意在Windows上跑得挺顺换到Linux下就各种水土不服——库路径、显示后端、编译器版本、字体内嵌每一个环节都能卡你半天。把这两周的血泪经验整理出来从安装到实战能帮一个是一个。1. SquareLine Studio在Linux下的安装没那么难但坑也不少1.1 下载和安装的基本流程SquareLine Studio官方提供了Linux版本在它的官网下载页面有个小下拉框默认是Windows记得切到Linux选项。下载下来是一个.AppImage文件这玩意在Ubuntu上算是最友好的发布形式了不用装依赖地狱给个执行权限就能跑。chmod x squareline-studio-*.AppImage ./squareline-studio-*.AppImage如果直接双击没反应大概率是缺少FUSE依赖。AppImage在Linux上依赖libfuse2才能挂载运行Ubuntu 22.04及以后的版本默认不带libfuse2坑就埋在这。sudo apt install libfuse2装完这个再启动就正常了。另外如果你用的是Wayland会话而不是X11可能还会碰到缩放模糊或者窗口打不开的问题。实测下来最简单的办法是在启动命令前加GDK_BACKENDx11GDK_BACKENDx11 ./squareline-studio-*.AppImage这算是一个比较稳定的兼容方案至少在我这边的混合显卡笔记本上用X11后端跑UI工具完全没有问题。1.2 License激活的注意点SquareLine Studio的免费版限制页面不超过5个单个工程如果你只是学习测试完全够用。激活时它会要求你填邮箱然后从邮件里拿激活码这一步在Linux下偶尔会出现网络请求超时的问题。不是说你网不行而是它默认走的激活服务器偶尔抽风。解决办法是把时间和日期开了自动同步然后重试几次。如果还不行挂代理也是个常见做法——不过这方面我就不展开说了懂得都懂。1.3 工程文件的位置SquareLine Studio的工程文件默认保存在~/Documents/SquareLineStudio/projects/下生成代码导出时默认也在~/Documents/SquareLineStudio/exports/。搞清楚这两个位置很重要后面跟LVGL模拟器对接的时候你至少知道生成的代码去了哪。习惯用find ~ -name ui*定位也行省得满系统瞎翻。2. LVGL在Linux跑起来选择一个合适的模拟器2.1 PC模拟器的选型逻辑LVGL官方在GitHub上有几个模拟器项目最常用的是lv_port_pc_eclipse但说实话它默认是为Windows和Eclipse准备的。在Linux上跑我建议直接用lv_port_linux或者基于SDL2的版本省去很多IDE配置的麻烦。无论选哪个核心依赖就两个SDL2和CMake。你可以在Linux上很轻松地装好sudo apt install libsdl2-dev cmake gcc g有一点值得说清楚为什么一定需要一个模拟器LVGL本身在嵌入式设备上是跑在裸机或RTOS上的跟显示驱动、输入驱动直接绑定。你在PC上开发不可能直接调嵌入式屏的驱动所以SDL2在这里扮演的就是“虚拟显示器和虚拟触摸屏”的角色。它把LVGL的绘制结果渲染到一个窗口里同时把鼠标事件转成LVGL的触摸事件这样你就能在没有硬件的情况下调界面逻辑。2.2 官方Linux模拟器的构建以lv_port_linux为例它的构建命令很简单git clone --recursive https://github.com/lvgl/lv_port_linux.git cd lv_port_linux mkdir build cd build cmake .. make -j$(nproc) ./lvgl_sim一个常见的坑是submodule拉不全。LVGL的仓库结构比较复杂核心库、demo、驱动分成好几个子仓库如果你clone的时候忘了--recursive编译时就会报lvgl.h找不到之类的问题。如果已经踩了这个坑补一下submodule即可git submodule update --init --recursive2.3 如果你用的是LVGL 9.xLVGL 9.x发布后API变化比较大很多老教程里的代码直接搬过来会爆编译错误。如果你在GitHub上搜到的是lv_port_pc_v9或者更新版的模拟器要注意它对CMake版本有要求3.16以上Ubuntu 20.04的默认CMake是3.16.3勉强够用更老的系统就得手动升级CMake了。LVGL 9.x的另一个变化是引入了新的初始化流程lv_init()用法没变。显示驱动注册需要用lv_display_create()而不是老的lv_disp_drv_register()。输入设备注册也是类似改动。颜色格式现在默认走LV_COLOR_FORMAT_ARGB8888如果你要省内存可以用LV_COLOR_FORMAT_RGB565但这些配置要在lv_conf.h里显式打开。如果是从8.x时代的教程迁移过来这些API差异是最容易让你怀疑人生的地方。我的建议是直接用9.x的官方demo作为参考不要看老博客。3. SquareLine Studio导出代码接入模拟器的完整流程3.1 导出设置SquareLine Studio左侧面板有Screen、Assets、Styles、Events等标签在生成代码前最需要注意的是Project Setting里的Export选项。你需要指定目标平台选择Simulator或者Generic。颜色深度跟你的模拟器保持一致通常用16 bit或32 bit。字体中文界面一定要记得添加中文字体否则导出的代码里中文全部乱码。字体这块我特别提醒一句SquareLine Studio默认带的是英文字体你要添加中文字库得自己准备.ttf或.otf文件并在Font设置里把Unicode范围勾选上中文区域。如果不设置范围生成的字体内嵌会巨大无比或者干脆漏字。导出后你会得到一个ui文件夹里面是ui.c、ui.h、ui_helpers.c、ui_events.c以及若干字体和图片文件。这些文件跟硬件没关系是纯LVGL代码直接拷到模拟器工程里就能用。3.2 接入模拟器的文件组织方式以lv_port_linux为例把生成的ui文件夹放到项目的src目录下然后在main.c里调用#include ui.h int main(void) { lv_init(); lv_port_disp_init(); lv_port_indev_init(); ui_init(); while(1) { lv_timer_handler(); usleep(5000); } }有个细节要留意ui_init()里会创建屏幕并lv_screen_load()所以它必须在显示设备和输入设备初始化完成后调用。如果你在模拟器里看到界面卡在空白页十有八九就是初始化顺序搞反了。3.3 解决中文字体内嵌问题我最初把SquareLine Studio导出的工程直接编译跑起来发现按钮上的中文全部变成方框。排查了半天问题出在两个地方一个是模拟器里没启用LV_FONT_SIMSUN_16_CJK之类的CJK字体宏另一个是ui_font_xxx.c里的字体数组太新但lv_conf.h中的LV_FONT_CUSTOM_DECLARE没有声明。建议在lv_conf.h里把字体相关的宏都打开#define LV_FONT_CUSTOM_DECLARE \ LV_FONT_DECLARE(ui_font_NotoSansCJKscRegular) \然后去ui.c里确认你的控件设置的是不是这个字体。如果这两步都做了还是方框就把lv_conf.h里的LV_USE_FONT_PLACEHOLDER设为0防止用占位符字体。4. 接入真实嵌入式目标前的几个关键检查4.1 不要跳过运行RTOS的环境模拟你最终的产品八成要跑在FreeRTOS或者其他RTOS上所以如果热词里看到了freertos移植lvgl说明很多人有这个需求。在PC模拟器里调试时while(1)循环是裸奔的但到了有RTOS的环境里你必须把LCD刷新、触摸扫描和LVGL的lv_timer_handler()放到不同优先级的任务里。一个常见的错误是把所有事情都塞进一个任务低优先级任务永远没有执行机会界面卡成PPT。我的经验是触摸任务最高优先级轮询周期10ms。LVGL的lv_timer_handler()所在任务次优先级延时5~10ms。显示刷新如果有单独的TE中断或DMA传输不要在回调里做重活。4.2 LVGL的刷新和缓冲策略虽然这是PC模拟器避坑指南但模拟器里也能模拟双缓冲。在lv_port_disp_init()里通常有这样一个缓冲区配置static lv_disp_draw_buf_t draw_buf; static lv_color_t buf1[MY_DISP_HOR_RES * 100]; static lv_color_t buf2[MY_DISP_HOR_RES * 100]; lv_disp_draw_buf_init(draw_buf, buf1, buf2, MY_DISP_HOR_RES * 100);行缓冲的100是可以用MY_DISP_VER_RES之类的全部缓冲替换的但模拟器上你完全不用省内存直接开全屏缓冲性能最好。真机上的时候再根据内部RAM大小做折中改成部分缓冲。4.3 展示层和逻辑层要分离SquareLine Studio导出的是纯UI代码你最好别把业务逻辑直接往ui_events.c里堆。事件回调里就做三件事收参数、调逻辑函数、更新界面。不然界面稍微复杂一点这个文件就会膨胀到没法看后续想换UI工具都无从下手。我自己的习惯是ui_events.c只保留事件绑定。新建一个app_logic.c放业务逻辑和状态机。通过全局结构体或指针传递界面当前状态。4.4 按键和触摸输入的兼容模拟器里鼠标模拟的是触摸但很多工控产品用的是实体按键。LVGL里既可以用lv_indev_create()注册触摸也可以用同样的方式注册按键编码器。SquareLine Studio生成的代码默认只处理触摸事件如果你需要按键导航在模拟器阶段就要把按键输入驱动也加上否则后面真机上想加按键逻辑会打乱很多状态管理。5. 常见问题速查表与避坑技巧下面这张表是我这段时间实际踩坑的总结按照问题现象、原因、解决方法三列写清楚方便直接对照。问题现象常见原因解决方法AppImage双击无反应缺少libfuse2sudo apt install libfuse2UI窗口打不开或黑屏Wayland兼容性问题GDK_BACKENDx11 ./xxx.AppImage中文显示为方框缺少CJK字体或未声明字体在lv_conf.h中声明字体检查控件字体设置导出的UI代码编译报错LVGL主仓库版本与UI导出版本不一致确认模拟器的LVGL版本和SquareLine Studio的Settings里选择一致同步后看到的是老界面缓存未清理rm -rf build mkdir build后重新cmake鼠标点击无响应输入设备初始化顺序不对确保lv_port_indev_init()在ui_init()前调用界面闪屏严重缓冲区太小或未开启双缓冲模拟器直接开全屏缓冲真机再优化CMake版本太低导致编译失败老系统自带CMake过旧使用pip install cmake或snap install cmake装新版字体导出文件巨大Unicode范围全选导致包含大量字符只勾选需要的字符集范围屏幕尺寸不对模拟器默认分辨率与SquareLine Studio画布不一致统一MY_DISP_HOR_RES和MY_DISP_VER_RES5.1 版本管理是最容易忽略的坑SquareLine Studio和LVGL核心库的版本最好严格对应。SquareLine Studio 1.3.x系列默认对应LVGL 8.3.x1.4.x支持LVGL 9.0/9.1但需要你在导出设置里明确选版本。如果你手里的模拟器是LVGL 8.3结果导出了9.x的代码编译报错能让你怀疑人生。打开模拟器里的lvgl子模块看一眼它的lv_version.h#define LVGL_VERSION_MAJOR 9 #define LVGL_VERSION_MINOR 1再看SquareLine Studio里Project Setting - LVGL Version两者保持一致再导出。5.2 生命周期与内存问题模拟器里跑的时候LVGL会自动向上申请内存。默认情况下它的堆大小是LV_MEM_SIZE默认给的是(64U * 1024U)如果你的界面里加了很多大图片或者中文字体很容易达到上限表现为画面局部不刷新或者控件创建失败。排查方法很简单在运行日志里打开内存监控lv_mem_monitor_t mon; lv_mem_monitor(mon); printf(used: %d, free: %d\n, mon.used, mon.free);在模拟器里如果发现free太少直接调大LV_MEM_SIZE即可真机上再谨慎分配用lv_mem_alloc和lv_mem_free管理。5.3 让SquareLine Studio的代码风格尽量跟你自己代码风格统一生成的ui.c动辄几百上千行但别直接在生成文件里手改。SquareLine Studio有个功能叫Merge——当你在工具里改动并重新导出时它会保留你在导出的代码里写过的部分逻辑不会覆盖。听起来很美实际上如果你在ui_events.c里写过大量自己的代码再导出时有一定概率冲突。保险做法是业务逻辑写在app_logic.cui_events.c里只做转发这样每次导出重新覆盖都无所谓。6. 再从Linux命令和开发流程角度补充几句很多做嵌入式出身的朋友对Linux命令行不熟以为装好软件点点点就行实际开发中你会发现命令行的效率完全碾压鼠标操作。这里分享几个我常用的命令跟LVGL开发直接相关查找生成的字体文件和代码位置find ~/Documents/SquareLineStudio -name *.c | head -50快速清理编译产物rm -rf build cmake -S . -B build cmake --build build -j用GDB直接定位崩溃点gdb ./lvgl_sim然后run崩溃后bt看调用栈类似linux常用命令、linux解压文件乱码这类词我在开发中也经常遇到。比如SquareLine Studio导出的工程有时是.zip包在Windows上解压没问题但Linux上解压后中文文件名可能乱码。解决办法是装unzip时指定字符集sudo apt install unzip convmv unzip -O CP936 project.zip或者解压后用convmv批量转码convmv -f GBK -t UTF-8 --notest -r .这算是Linux下中文用户一个经典老坑放到LVGL工程文件上也一样适用。有人问过我用linux跑qt还是lvgl。如果只是做轻量级HMI、硬件资源有限、需要快速启动、占用内存小的界面LVGL是更合适的选择如果目标硬件跑的是完整Linux发行版、资源充裕、要的是复杂桌面级交互Qt显然更合理。两者不冲突LVGL往资源受限方向走Qt往功能应用方向走。所以题主如果做的是跟嵌入式GUI相关选LVGL在这条路上是说得通的——尤其是配合SquareLine Studio出图工具开发效率能拉得很高。还有一点关于linux国产和国产芯片平台像全志T113-S3这类芯片官方SDK里集成了LVGL但让G2D做渲染加速的话需要确认你的LVGL绘制流程是否走drm或fb设备节点直通。模拟器上体验不到的硬件加速别等到真机才验证尽量提前看数据手册里显示控制器的blend接口。7. 实战演示做一个带开关和进度条的监控面板讲了一堆理论我拿一个实际的小界面步骤来说这样SquareLine Studio的完整工作流会更清楚。7.1 界面设计我新建了一个工程屏幕尺寸设为480x320先拖一个Panel作为背景然后把颜色改成深灰色。再往里面放一个Label作为标题字体用NotoSansCJKsc Regular 24。一个Switch控件表示设备开关。一个Slider作为进度条。两个Label显示当前数值。SquareLine Studio里这些拖拽操作非常简单注意调整好Align属性放到合适的位置。比如Title对齐TOP_MIDSwitch对齐CENTER数值Label对齐BOTTOM_MID。7.2 添加事件选中Switch控件在右侧Events面板Add Event选择VALUE_CHANGED然后Create。SquareLine Studio会自动跳转到ui_events.c生成如下代码void switch_event_handler(lv_event_t * e) { lv_event_code_t code lv_event_get_code(e); if(code LV_EVENT_VALUE_CHANGED) { // TODO: 加自己逻辑 } }我在回调里读取了开关状态并更新数值标签void switch_event_handler(lv_event_t * e) { lv_event_code_t code lv_event_get_code(e); if(code LV_EVENT_VALUE_CHANGED) { lv_obj_t * sw lv_event_get_target(e); bool is_on lv_obj_has_state(sw, LV_STATE_CHECKED); if(is_on) { lv_label_set_text(ui_StateLabel, ON); } else { lv_label_set_text(ui_StateLabel, OFF); } } }Slider那边逻辑类似监听VALUE_CHANGED然后格式化字符串写到Label里char buf[16]; snprintf(buf, sizeof(buf), %d%%, (int)lv_slider_get_value(slider)); lv_label_set_text(ui_ValueLabel, buf);7.3 导出并编译运行导出工程到~/Documents/SquareLineStudio/exports/monitor_demo把ui文件夹拷到lv_port_linux的src目录下然后在main.c里加入#include ui.h int main(void) { lv_init(); lv_port_disp_init(); lv_port_indev_init(); ui_init(); while(1) { lv_timer_handler(); usleep(5000); } return 0; }重新cmake编译运行./lvgl_sim窗口上就能看到监控面板。开关切换会改状态文字滑块拖动会改百分比整个交互是实时刷新的。到这一步你就已经具备了在PC上开发LVGL界面的完整闭环能力。8. 最后的几点经验SquareLine Studio LVGL这套组合放在Linux环境下完全可行关键是版本匹配、字体配置、显示后端这三个大坑提前避开。很多新手一上来就急着搞硬件移植其实完全可以在PC模拟器上把界面逻辑调通再去做交叉编译和真机适配效率会高很多。我个人的习惯是UI布局和样式全在SquareLine Studio里做业务逻辑全在下层C代码里做中间只通过事件回调搭桥。这样SquareLine Studio升级或者换UI工具都不会伤筋动骨。最后再分享一个小技巧如果在模拟器调试时发现界面有闪烁或者触摸不跟手别急着优化代码先看看是不是SDL2窗口没开垂直同步。在lv_port_linux的main.c里可以调用SDL_SetHint(SDL_HINT_RENDER_VSYNC, 1);很多看似性能问题的现象其实就是垂直同步没开。就到这吧有什么问题评论区聊。