一款带LCD的嵌入式电子产品,如果是面向出口贸易,那么多国语言的显示功能必不可少。那么如何使用LVGL来实现多语言功能呢?先来实现一个简单的语言功能切换demo:当不断点击一个按钮,即将一个文本以不同语言进行显示。
1、下载TTF或者WOFF字体
这里我下的是思源黑体Normal版本:SourceHanSansCN-Normal-2.otf
如果想要找其它的一些字体,去Adobe开源字体 github 上下载就行了,地址:
https://github.com/adobe-fonts
2、使用 LVGL 官方的字体转换工具进行转换
使用官网网页版本的转换工具,地址如下:
https://lvgl.io/tools/fontconverter
例如我想显示:你好中国
中文:你好中国
日文:こんにちは中国
英文:Hello China
德文:Hallo China
俄文:Привет Китай
因为我只是想要显示个别国家的文本,故不需要整个字库文件,而只是从字库文件里取出我想要的那部分即可,那么这时候我们就将翻译好的文本填写到Symbols区域
即可,设置完对应的参数以后,点击Convert即可生成对应的字体数组文件并通过网页端进行下载,下载完成打开文件显示如下:(温馨提示,字库文件最好选择等宽字库文件,这样就可以兼容其它特殊的字体,例如韩语等)
3、将生成的字体文件拷贝到 lvgl 字体对应的目录下
然后添加到 lv_font.mk 中:
4、编写代码逻辑
点击按钮,将"你好中国"以中文、日文、德文、俄文分别进行显示。
#include "lvgl/lvgl.h" #include "lvgl/demos/lv_demos.h" #include "lv_drivers/display/fbdev.h" #include "lv_drivers/indev/evdev.h" #include <unistd.h> #include <pthread.h> #include <time.h> #include <sys/time.h> #define DISP_BUF_SIZE (128 * 1024) lv_obj_t *btn ; lv_obj_t *label; static void event_handler(lv_event_t * e) { static uint8_t status = 0 ; lv_event_code_t code = lv_event_get_code(e); if(code == LV_EVENT_CLICKED) { switch(status) { case 0: lv_label_set_text(label,"こんにちは"); status = 1 ; break ; case 1: lv_label_set_text(label,"Hallo China"); status = 2 ; break ; case 2: lv_label_set_text(label,"Привет Китай"); status = 3 ; break ; case 3: lv_label_set_text(label,"你好中国"); status = 0 ; break ; default: break ; } } } int main(void) { lv_init(); fbdev_init(); static lv_color_t buf[DISP_BUF_SIZE]; /*Initialize a descriptor for the buffer*/ static lv_disp_draw_buf_t disp_buf; lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE); static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.draw_buf = &disp_buf; disp_drv.flush_cb = fbdev_flush; disp_drv.hor_res = 480; disp_drv.ver_res = 800; lv_disp_drv_register(&disp_drv); evdev_init(); static lv_indev_drv_t indev_drv_1; lv_indev_drv_init(&indev_drv_1); indev_drv_1.type = LV_INDEV_TYPE_POINTER; indev_drv_1.read_cb = evdev_read; lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1); LV_IMG_DECLARE(mouse_cursor_icon) lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); lv_img_set_src(cursor_obj, &mouse_cursor_icon); lv_indev_set_cursor(mouse_indev, cursor_obj); //创建一个按钮 btn = lv_btn_create(lv_scr_act()); //设置按钮的大小 lv_obj_set_size(btn, 100, 50); //将按钮居中显示 lv_obj_center(btn); //设置按钮默认的背景颜色样式 lv_obj_set_style_bg_color(btn, lv_color_hex(0xE3EAF4), LV_STATE_DEFAULT); //当按钮按下时的背景颜色样式 lv_obj_set_style_bg_color(btn, lv_color_hex(0x3E6094), LV_STATE_PRESSED); //注册按钮事件,点击按钮时,将在event_handler回调函数里进行处理 lv_obj_add_event_cb(btn, event_handler, LV_EVENT_ALL, NULL); //从外部导入自定义字库文件 LV_FONT_DECLARE(siyuan_black); //设置自定义字体样式 static lv_style_t style_font ; lv_style_init(&style_font); //创建一个Label标签控件 label = lv_label_create(lv_scr_act()); //设置Label的大小 lv_obj_set_size(label, 200,100); //将Label显示的字体样式设置为自定义字体样式 lv_obj_set_style_text_font(label, &siyuan_black, 0); //在Label显示显示内容 lv_label_set_text(label,"你好中国"); /*Handle LitlevGL tasks (tickless mode)*/ while(1) { lv_timer_handler(); usleep(5000); } return 0; } /*基于Liunx的时基产生心跳函数,提供给LVGL用*/ uint32_t custom_tick_get(void) { static uint64_t start_ms = 0; if(start_ms == 0) { struct timeval tv_start; gettimeofday(&tv_start, NULL); start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000; } struct timeval tv_now; gettimeofday(&tv_now, NULL); uint64_t now_ms; now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000; uint32_t time_ms = now_ms - start_ms; return time_ms; }
5、运行效果
Linux开发板上的显示效果:
这个是我在SSD212开发板上跑的效果,同样的,也可以将平台无关的代码移植到任何支持LVGL v8.2的平台上:
https://gitee.com/morixinguan/lvgl_v8.2_for_mcu https://gitee.com/morixinguan/lvgl_v8.2_for_linux
就用我提供的上面这两个模板直接修改即可。我还将韦东山老师提供的开源中文键盘输入控件移植到相应的工程里,但是该控件的实现效果以及定制化离真正的产品功能还有一段距离,期待后续优化和改进:
在真正的产品开发中,一般情况下会将不同语言放在不同的文件里,然后再通过程序逻辑来实现动态切换,这样做有利于后期的维护和样式扩展,例如实现UI换肤功能。
在真正的产品开发中,一般情况下会将不同语言放在不同的文件里,然后再通过程序逻辑来实现动态切换,这样做有利于后期的维护和样式扩展,例如实现UI换肤功能。本demo例程如下:
https://gitee.com/morixinguan/lvgl_v8.2_for_linux
往期精彩
一个超棒的开源解读项目【Linux内核揭秘】,一定不要错过啦!