前言

本文介绍LVGL,MiniGUI,Openharmony arkui_ui_lite,三种嵌入式UI引擎移植方法,开发基本框架

LVGL

  • 官网:https://lvgl.io/
  • 源码:https://github.com/lvgl/lvgl

特点

  1. C语言
  2. 社区活跃,示例丰富,应用广泛,开源代码量大管饱:通过AI即可编写复杂的界面逻辑
  3. 资源占用极少:ROM: ~64KB, RAM: ~2KB+
  4. 面向对象
  5. 事件驱动:通过事件回调响应交互

基本组件

---------------------------------------------------------------------------------------------------------	
Style			lv_style_x							风格				可以设计各种风格(颜色, 边框, 填充, 动作效果/聚焦, 阴影, 梯度, 渐变, 文本)
				lv_obj_set_style_x									lv_style_set_bg_color: 背景色
				lv_obj_add_style									lv_style_set_radius: 半径
																	lv_style_set_border_width: 边界
																	lv_style_set_text_color: 文本
																	lv_style_set_arc_color: 圆弧
																	lv_style_set_image_recolor: 图片
																	lv_style_set_shadow_width: 阴影
																	lv_style_set_outline_width: 边框
																	lv_obj_set_style_transform_rotation: 旋转角度
Event			lv_obj_add_event_cb					事件
Timer			lv_timer_create()					定时器			可以实现定时渲染(重绘)
---------------------------------------------------------------------------------------------------------
Widgets			lv_obj_create()						控件				各种组件组成
---------------------------------------------------------------------------------------------------------											
Lable			lv_label_create();					标签				显示字体/符号
Button			lv_button_create();					按钮				按钮和事件
Slider			lv_slider_create();					滑块				可以滑动
Image			lv_image_create();					图像				可以放置图片
Line			lv_line_create();					线条
Theme			lv_theme_create();					主题
Switch			lv_switch_create();					开关
Animation		lv_anim_init();						动画
Chart			lv_chart_create();					图表				展示图表
CheckBox		lv_checkbox_create()				复选框			可以勾选
List			lv_list_create()					列表				存在多列
Bar				lv_bar_create()						栏
Text			lv_textarea_create()				文本框
---------------------------------------------------------------------------------------------------------
3DTexture		lv_3dtexture_create()				3D纹理
Arc				lv_arc_create();					圆弧	
ArcLabel		lv_arclabel_create()				圆弧标签
ButtonMatrix	lv_buttonmatrix_create()			按钮矩阵
Calendar		lv_calendar_create()				日历
Canvas			lv_canvas_create()					画布				需要lv_layer_t, lv_draw_image(), lv_draw_rect(), lv_canvas_finish_layer
Scale			lv_scale_create()					度量()
DropDown		lv_dropdown_create()				下拉列表
ImageButton		lv_imagebutton_create()				图片按钮
Keyboard		lv_keyboard_create()				键盘
Led				lv_led_create()						Led灯
Lottie			lv_lottie_create()					落幕
Menu			lv_menu_create()					菜单
MessageBox		lv_msgbox_create()					消息盒子
Roller			lv_roller_create()					滚动条
Span			lv_spangroup_create()				盘组(视图组)
SpinBox			lv_spinbox_create()					微调框			
Spinner			lv_spinner_create()					微调框
Table			lv_table_create()					表格
TableView		lv_tabview_create()					表格视图
TileView		lv_tileview_create()				标题视图
Window			lv_win_create()						窗口
Barcode			lv_barcode_create()					条形码
FFMpeg			lv_ffmpeg_player_create()			视频编解码
FreeTypeFont	lv_freetype_font_create()			FreeType字体
Gif				lv_gif_create()						Gif
glTF			lv_gltf_create()				
GStreamer		lv_gstreamer_create()			
QRCoder			lv_qrcode_create()					二维码生成器
---------------------------------------------------------------------------------------------------------	
AnimTimeline 	lv_anim_timeline_create()					动画时间线		lv_anim_timeline_add
DrawTask		lv_event_get_draw_task()
FlexFlow		lv_obj_set_flex_flow()						弹性流动		
Grid			lv_obj_set_style_grid_column_dsc_array()	网格
---------------------------------------------------------------------------------------------------------	

编译方法

  1. 下载源码
    • 核心代码
      • src/core
      • src/drivers
      • examples/porting
  2. 构建
    • 创建build, output目录
    • 进入build
    • cmake … -DCMAKE_C_COMPILER=cross_compiler_gcc -DCMAKE_INSTALL_PREFIX=源码目录绝对路径/output
  3. 编写lv_conf.h: 条件编译
    • 重命名lv_conf_template.h为lv_conf.h
    • 根据项目需求设置: 色深, 支持的控件
    • 相关配置项
      • 系统相关
        • LV_MEM_SIZE
        • LV_TICK_CUSTOM
        • LV_LOG_LEVEL
      • 图形渲染
        • LV_COLOR_DEPTH
      • 功能开关
        • LV_USE_ANIMATION
        • LV_USE_FONT_COMPRESSED
        • LV_USE_LABEL
      • 性能与优化
        • LV_REFR_DEF_PERIO: 默认刷新周期
        • LV_USE_OBJ_REBUILD: 允许对象动态重建(增加灵活性, 但是占用更多RAM)
      • 调试与开发
        • LV_USE_ASSERT
        • LV_USE_PERF_MONITOR
  4. 编译
    • 执行make
    • 执行make install
    • 编译结果
      • liblvgl.a
      • liblvgl_demos.a
      • liblvgl_examples.a
      • liblvgl_thorvg.a
  5. 实现接口: 在Demo中实现以下接口
    • 显示: 移植examples/porting/lv_port_disp_template.c: 在源码中实现这个文件中的接口
      • disp_init(): 初始化显示屏
      • disp_flush(): 向指定区域写入像素数据
    • 输入: 移植examples/porting/lv_port_indev_template.c: 在源码中实现这个文件中的接口
      • lv_port_indev_init(): 初始化输入设备
      • xxx_read(): 输入设备的读回调函数
    • lv_port_fs_template.c: 文件系统移植相关接口
  6. 编译链接
    • 编译链接liblvgl.a到Demo中

编码

初始化流程

  1. lvgl初始化: lv_Init()
  2. 设置tick回调: lv_tick_set_cb(my_get_millis), 用于定时器计时
  3. 输入输出设备初始化
    • lv_display_t
      • lv_display_create(width, hight): 创建lv_display_t对象
      • lv_display_set_buffers(display, buf, NULL, LV_DISPLAY_RENDER_MODE_PARTIAL): 设置刷新缓冲区
      • lv_display_set_flush_cb(display, my_flush_cb): 设置刷新回调. 回调中返回前要通知渲染完成
    • lv_indev_t
  4. 执行定时器任务: lv_timer_handler();

示例

void main(void)
{
    lv_init();
    lv_tick_set_cb(my_get_millis);
	
	/* 显示屏 */
    lv_display_t * display = lv_display_create(320, 240);
    static uint8_t buf[320 * 240 / 10 * 2];
    lv_display_set_buffers(display, buf, NULL, LV_DISPLAY_RENDER_MODE_PARTIAL);
    lv_display_set_flush_cb(display, my_flush_cb);
	
	/* 定时任务处理 */
    while(1) 
	{
        lv_timer_handler();
        my_sleep(5);
    }
}

uint32_t my_get_millis(void)
{
    return my_tick_ms;
}

void my_flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map)
{
    uint16_t * buf16 = (uint16_t *)px_map; /* Let's say it's a 16 bit (RGB565) display */
    int32_t x, y;
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            put_px(x, y, *buf16);
            buf16++;
        }
    }
    lv_display_flush_ready(display);
}

MiniGUI

  • 官网:https://minigui.fmsoft.cn/zh
  • 源码:https://minigui.fmsoft.cn/zh/download

特点

  1. C语言
  2. 国内开源
  3. 资源要求相对较高:ROM: ~500KB+
  4. C/S架构
  5. 传统Win32风格,基于窗口、句柄和消息循环:通过事件回调响应交互

基本组件

---------------------------------------------------------------------------------------------------------
AbstractAdapter				适配器				对外提供一致的接口, 可用于任何地方
RootWindow					根窗口				桌面窗口,所有窗口的顶层祖先,占满屏幕
MainWindow					主窗口				应用程序主界面,可包含菜单、工具栏和子窗口
DialogBox					对话框				模态或非模态的弹出窗口,用于用户交互
mComponent					组件基类				所有组件(含可见控件与不可见组件)的基类
mWidget						控件基类				派生自mComponent,是所有可见控件的基类
Renderer					渲染器				控制控件或窗口的外观绘制,支持皮肤和主题自定义
WindowClass					窗口类				定义窗口或控件的行为与外观,如按钮类模板
---------------------------------------------------------------------------------------------------------
Event						事件				原始交互信号,如鼠标点击、键盘输入
Message						消息				系统或应用发送给窗口的结构化数据
MessageQueue				消息队列			存放待处理消息的队列,保证顺序
Timer						定时器				不可见组件,按间隔产生MSG_TIMER消息
WindowProcedure				窗口过程			每个窗口的核心函数,处理所有发往该窗口的消息
---------------------------------------------------------------------------------------------------------
Static						静态框				显示文本、图片或边框,不响应用户输入
Button						按钮				可点击触发即时动作的控件
CheckButton					复选框				允许从一组选项中同时选择多个的按钮
RadioButton					单选钮				允许从一组选项中互斥选择一个的按钮
SLEdit						单行编辑框			输入和显示单行文本
MLEdit						多行编辑框			输入和显示多行文本
ComboBox					组合框				编辑框(或静态文本)与下拉列表框的组合
ListBox						列表框				以列表形式显示选项供用户选择
ListView					列表型控件			以表格形式(带表头和列)显示数据项
TreeView					树型控件			以层次化树形结构显示数据
Menu						菜单				位于主窗口顶部的下拉命令列表
Toolbar						工具栏				包含多个图标按钮,用于快速执行命令
Trackbar					滑块				拖动滑块在一个范围内选择值
ProgressBar					进度条				直观显示任务完成百分比
---------------------------------------------------------------------------------------------------------
PropertySheet				属性页/属性表		通过选项卡组织多个设置页面
MonthCalendar				月历控件			以月历形式显示日期,供选择或查看
SpinBox						旋钮控件			编辑框加一对上下箭头,用于增减数值
Grid						网格控件			以网格形式展示数据,类似电子表格
IconView					图标型控件			以图标加文字列表展示项目,类似文件管理器
ScrollView					滚动型控件			提供可滚动查看内容的视口
ScrollBar					滚动条控件			独立的滚动条
Animation					动画控件			用于播放简单动画(如GIF)
CoolBar						酷工具栏			可拖拽、可定制的增强型工具栏
mG3d						三维组件			提供简单3D绘图API,创建基本3D界面
---------------------------------------------------------------------------------------------------------
mGUtils						实用工具组件			包含颜色选择、文件打开等通用对话框
mGPlus						高级图形组件			提供路径、渐变、抗锯齿等高级2D图形接口
mGEff						动画框架组件			提供动画框架及流行UI特效
mGNCS						新控件集			用面向对象思想重新设计的控件集,含丰富控件和框架
mGi							输入法组件			提供软键盘、手写等输入法框架
mGp							打印组件			提供将图形内容输出到通用打印机的功能
---------------------------------------------------------------------------------------------------------

编译方法

  1. 下载源码: https://minigui.fmsoft.cn/download
  2. 构建
    • 执行autogen.sh
    • 执行./configure --prefix= --host=cross_compiler_gcc --enable-videoxx=yes --enable-xxxial=yes --with-runmode=proc/ths/sa
      • video: GAL选择. --enable-videocustom, 用户自定义显示驱动
      • ial: IAL选择. --enable-customial, 用户自定义输入驱动
      • runmode: 运行模式. 进程(多应用共享一个屏幕), 线程(应用独占一个屏幕)
  3. 编译
    • 执行make
    • 执行make install
    • 生成结果
      • libminigui_ths.a
  4. MiniGUI.cfg
    • MiniGUI执行初始化时(InitGUI)加载进内存的配置文件
    • 核心参数
      • `[system]
        • gal_engine=commlcd
        • defaultmode=1968✖1024
        • ial_engine=custom
      • `[systemfont]
      • `[resinfo]
      • `[memory]
        • heap_size=
      • `[window]
  5. 实现接口
    • 根据使用GAL, IAL不同, 需要实现MiniGUI中的外部声明接口
      • –enable-customial=yes
        • 初始化: `BOOL InitCustomInput (INPUT* input, const char* mdev, const char* mtype)
        • 回收: `void TermCustomInput()
      • –enable-videocommlcd=yes
        • 定义: struct commlcd_ops __mg_commlcd_ops;
  6. 编译链接
    • 编译链接libminigui_ths.a到Demo中
    • export MG_CFG_PATH=MiniGUI.cfg
    • 执行Demo

编码流程

初始化流程

  1. 创建主窗口:CreateMainWindow()
  2. 编写消息处理函数:static int MyWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
  3. 显示窗口:ShowWindow()
  4. 消息循环: while (GetMessage(&Msg, hMainWnd)){TranslateMessage(&Msg); DispatchMessage(&Msg);}

示例

#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>

/* 窗口过程函数(类似LVGL的事件回调)*/
static int MyWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    switch (message) {
        case MSG_PAINT:
            hdc = BeginPaint(hWnd);
            /* 在窗口上绘制文本 */
            TextOut(hdc, 60, 60, "Hello MiniGUI!");
            EndPaint(hWnd, hdc);
            return 0;
        case MSG_CLOSE:
            DestroyMainWindow(hWnd);        /* 销毁主窗口 */
            PostQuitMessage(hWnd);          /* 发送退出消息 */
            return 0;
    }
    return DefaultMainWinProc(hWnd, message, wParam, lParam);
}

/* MiniGUI 应用程序入口(不是传统 main 函数)*/
int MiniGUIMain(int argc, const char* argv[])
{
    MSG Msg;
    HWND hMainWnd;
    MAINWINCREATE CreateInfo;

    #ifdef _MGRM_PROCESSES
    /* MiniGUI-Processes 模式下需要加入图层 */
    JoinLayer(NAME_DEF_LAYER, "helloworld", 0, 0);
    #endif

    /* 设置主窗口创建参数 */
    CreateInfo.dwStyle     = WS_VISIBLE | WS_BORDER | WS_CAPTION;
    CreateInfo.dwExStyle   = WS_EX_NONE;
    CreateInfo.spCaption   = "MyApp";
    CreateInfo.hMenu       = 0;
    CreateInfo.hCursor     = GetSystemCursor(0);
    CreateInfo.hIcon       = 0;
    CreateInfo.MainWindowProc = MyWinProc;          /* 绑定窗口过程函数 */
    CreateInfo.lx          = 0;
    CreateInfo.ty          = 0;
    CreateInfo.rx          = 320;                   /* 窗口宽度 */
    CreateInfo.by          = 240;                   /* 窗口高度 */
    CreateInfo.iBkColor    = COLOR_lightwhite;
    CreateInfo.dwAddData   = 0;
    CreateInfo.hHosting    = HWND_DESKTOP;          /* 托管窗口为桌面 */

    /* 创建主窗口 */
    hMainWnd = CreateMainWindow(&CreateInfo);
    if (hMainWnd == HWND_INVALID)
        return -1;

    /* 显示窗口 */
    ShowWindow(hMainWnd, SW_SHOWNORMAL);

    /* 消息循环 —— 类似 LVGL 的 while(1) { lv_timer_handler(); } */
    while (GetMessage(&Msg, hMainWnd)) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    /* 清理资源 */
    MainWindowThreadCleanup(hMainWnd);
    return 0;
}

ArkUI_ui_lite

  • 源码: https://gitee.com/openharmony/arkui_ui_lite

特点

  1. C++
  2. OpenHarmony国内开源
  3. 资源占用少
  4. 面向对象
  5. 事件驱动:通过事件回调响应交互

基本组件

---------------------------------------------------------------------------------------------------------
AbstractAdapter				适配器				对外提供一致的接口, 可用于任何地方
RootView					根视图				通过GetInstance()可返回单例RootView, 适用于单窗口应用
												多窗口, 可以创建新
---------------------------------------------------------------------------------------------------------											
Listener					监听者				UIView::OnClickListener, UIView::OnTouchListener
												UIView::OnLongPressListener, UIView::OnRotateListener
												UIView::OnDragListener, UIView::OnFocusListener
												UIPicker::SelectedListener
												UITimePicker::SelectedListener
												UISwipeView::OnSwipeListener
												UIImageAnimatorView::AnimatorStopListener
												UISlider::UISliderEventListener
												UIScrollView::OnScrollListener
												UICheckBox::OnChangeListener
												UIEditText::OnChangeListener
												UIList::ListScrollListener
												UITextureMapper::AnimatorStopListener
												UIVideo::PlayerListener
---------------------------------------------------------------------------------------------------------
Event						事件					拖动事件; 取消; 点击; 按键事件; 长按事件; 按下事件; 释放事件; 旋转事件; 虚拟设备事件
UIFont						字体
Layout						布局					FlexLayout灵活布局; GridLayout网格布局; Layout布局; ListLayout列表布局
Window						窗口			
---------------------------------------------------------------------------------------------------------
UILabel						标签
UIArcLabel					圆弧形标签
TextAdapter					文本适配器			使用`List<const char*> dynamicText_, 作为成员. 适用于初始化列表项文本
UIEditText					文本框
UIButton					按钮
UILabelButton				带标签按钮
UIToggleButton				切换按钮
UIRadioButton				单选按钮
UIRepeatButton				重复按钮				用户长按会连续触发点击事件
UIImageView					图片
UICheckBox					复选框
UIBoxProgress				进度盒子
UISlider					滑动条
UICircleProgress			圆形进度
UIScrollView				滚动视图
UIList						列表
UIPicker					列表选择器			
UITimePicker 				时间选择器			会有时//秒的选择列表			
UISwipeView					滑动视图						
UIAxis						坐标轴
UICanvas					画布					提供低级绘图接口, 允许直接绘制基本图形. 像素级别的控制!!!
UIChart						图表					高级数据可视化组件,用于展示各种类型的图表: 折线图, 柱状图, 饼图, 散点图
UIImageAnimatorView			图片动画视图			帧动画播放; 动画控制(播放, 暂停, 停止)
UITextureMapper				纹理映射器			高级图形组件,用于实现2D/3D变换效果和纹理映射
UIDialog					对话框视图			模态或非模态的弹出窗口: 布局和大小是固定的, 建议自己封装一个
UIScreenshot				屏幕截图
UIQrcode					二维码				生成和显示二维码的组件
UIDigitalClock				数字时钟
UIAnalogClock				模拟时钟				SetHandLine: 设置三条时钟线, 秒针, 分针, 时针; 设置动画回调, 驱动指针转动
UIVideo						视频播放				选中播放的视频, 进行播放
UISurfaceView				图形绘制窗口			允许你绕过标准的UI组件树渲染流程,直接在这块内存上绘制像素(预览, 2D/3D, 动态数据)
---------------------------------------------------------------------------------------------------------
UIAbstractClock				时钟
UIAbstractProgress			进度条
UIAbstractScroll			滚动		
---------------------------------------------------------------------------------------------------------
EventInjector				事件注入
UIDumpDomTree				帮助开发者可视化和分析UI组件的层次结构
UIViewBounds				控件边框显示/隐藏控制
---------------------------------------------------------------------------------------------------------

编译方法

编码流程

初始化流程

  1. 图形引擎初始化: OHOS::GraphicStartup::Init()
  2. 字体引擎: OHOS::InitFontEngine()
  3. 创建窗口, 显示窗口: Window::CreateWindow(WindowConfig())
    • WindowConfig config:
      • Rect rect: 矩形. 框定了窗口的范围
      • WindowPixelFormat pixelFormat: 像素的格式. 16/24/32
      • COPY: 全屏应用; BLEND: 半透明对话框, 悬浮窗口
    • Window::CreateWindow(config)
    • window->BindRootView(): 绑定根视图
    • RootView: 根视图类. 可以设置视图的位置SetPosition和大小Resize
    • window->Show(): 显示窗口
  4. 任务处理: OHOS::TaskManager::GetInstance()->TaskHandler()
    • 循环处理任务

示例

int main()
{
	OHOS::GraphicStartup::Init();
	OHOS::InitFontEngine();
	WindowConfig config;
	config.rect.SetRect(0, 0, Screen::GetInstance().GetWidth() - 1, Screen::GetInstance().GetHight() - 1);
	Window *window = Window::CreateWindow(config);
	window->BindRootView(RootView::GetInstance());
	window->Show();
	
	while(1)
	{
		OHOS::TaskManager::GetInstance()->TaskHandler();
		sleep_ms(1);
	}
	return 0;
}
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐