diff --git a/docs/Application_guide/zh/media/multi-media/lvgl/lvgl_font20.jpg b/docs/Application_guide/zh/media/multi-media/lvgl/lvgl_font20.jpg new file mode 100644 index 0000000000000000000000000000000000000000..150b91f8e129378a7f026ea15286708aa996a57a Binary files /dev/null and b/docs/Application_guide/zh/media/multi-media/lvgl/lvgl_font20.jpg differ diff --git a/docs/Application_guide/zh/media/multi-media/lvgl/lvgl_font21.jpg b/docs/Application_guide/zh/media/multi-media/lvgl/lvgl_font21.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bae98c06b3710a165f13ecafe6342679509597fe Binary files /dev/null and b/docs/Application_guide/zh/media/multi-media/lvgl/lvgl_font21.jpg differ diff --git a/docs/Application_guide/zh/media/multi-media/lvgl/startlogo1.png b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo1.png new file mode 100644 index 0000000000000000000000000000000000000000..b457dc7d61d5d53a43c719e9fe6522e695995859 Binary files /dev/null and b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo1.png differ diff --git a/docs/Application_guide/zh/media/multi-media/lvgl/startlogo2.png b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo2.png new file mode 100644 index 0000000000000000000000000000000000000000..a86fb220dd85403e6bb80a6a249d9e66c0b6895c Binary files /dev/null and b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo2.png differ diff --git a/docs/Application_guide/zh/media/multi-media/lvgl/startlogo3.png b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo3.png new file mode 100644 index 0000000000000000000000000000000000000000..5e05c77ddca973b266f62b22dce4b11d0deb9ca9 Binary files /dev/null and b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo3.png differ diff --git a/docs/Application_guide/zh/media/multi-media/lvgl/startlogo4.png b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo4.png new file mode 100644 index 0000000000000000000000000000000000000000..edab6e9e457d46e818a63f249b8b7e064a74f8e8 Binary files /dev/null and b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo4.png differ diff --git a/docs/Application_guide/zh/media/multi-media/lvgl/startlogo5.png b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo5.png new file mode 100644 index 0000000000000000000000000000000000000000..2de325a62837c6c27b98a8af324df0e8fb059e56 Binary files /dev/null and b/docs/Application_guide/zh/media/multi-media/lvgl/startlogo5.png differ diff --git a/docs/Application_guide/zh/multi-media/lvgl/README.md b/docs/Application_guide/zh/multi-media/lvgl/README.md index 0d09c6664dbd1de62587ae1b15d393eb8985c3cf..55b41f08fdaefa778208b30c42eaef4a30629291 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/README.md +++ b/docs/Application_guide/zh/multi-media/lvgl/README.md @@ -1,5 +1,5 @@ -Quecpython LVGL具备具有界面精美,资源消耗小,响应式布局等特点,更有 GUI guider 工具可实现可视化组件拖曳式开发,能够让开发者轻松搞定精美的用户界面,并在资源有限的环境下获得卓越的性能和用户体验,大大提升产品的竞争力。 - -- [LVGL](./lvgl.md) - -- [开机logo](./startup_logo.md) +Quecpython LVGL具备具有界面精美,资源消耗小,响应式布局等特点,更有 GUI guider 工具可实现可视化组件拖曳式开发,能够让开发者轻松搞定精美的用户界面,并在资源有限的环境下获得卓越的性能和用户体验,大大提升产品的竞争力。 + +- [LVGL](./lvgl.md) + +- [开机logo](./startup_logo.md) diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl.md index c1725dab9980391e258e01f75101b066c78a179b..62988f945684658dc18e5d333a9169a3496fe3fb 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl.md @@ -1,25 +1,25 @@ -# LVGL - -## 概述 - -`LVGL`全称 Light and Versatile Graphics Library。是一个轻量级的、自由的、开源的 GUI库,界面精美,资源消耗小,响应式布局,很适合嵌入式界面开发。 - -Quecpython LVGL主要特性如下: - -- 基于Quecpython开发,上手简单。 -- 具有非常丰富的内置控件,像 label(文本),button(按钮), img(图片),list(列表)等。 -- 高级图形效果:动画,反锯齿,透明度,平滑滚动。 -- 支持多种输入设备,像 touchpad, keyboard等。 -- GUI guider工具可实现可视化组件拖曳式开发,方便快捷。 -- 提供了丰富的在线和离线文档。 - -## 章节目录 - -- [LVGL-流程](./lvgl_flow.md):介绍LVGL与LCD等硬件设备的关联以及LVGL完整的工作流程。 -- [LVGL-常用组件](./lvgl_control.md):介绍LVGL对象的一些基本概念,包括对象间的关系(父级子级),样式,事件等;介绍项目中常用的组件的用法及API。 -- [LVGL-示例](./lvgl_demo.md):教您如何快速上手使用Quecpython LVGL开发一个GUI应用程序。 -- [LVGL-字体库](./lvgl_fontlib.md):如果LVGL默认字体库不能满足您的项目需求,请翻阅本章。 -- [LVGL-UI工具](./lvgl_ui_tool.md):介绍GUI guider工具的使用,即使不熟悉LVGL接口也能使用它轻松开发,帮您的UI开发节约90%的时间。 -- [LVGL-应用场景](./lvgl_application_scenarios.md):介绍Quecpython LVGL目前的几个主要应用场景,并给出开发指导。 -- [LVGL-注意事项](./lvgl_notes.md):避坑必看,总结了项目开发过程中经常遇到的问题,让您的GUI开发更顺利。 - +# LVGL + +## 概述 + +`LVGL`全称 Light and Versatile Graphics Library。是一个轻量级的、自由的、开源的 GUI库,界面精美,资源消耗小,响应式布局,很适合嵌入式界面开发。 + +Quecpython LVGL主要特性如下: + +- 基于Quecpython开发,上手简单。 +- 具有非常丰富的内置控件,像 label(文本),button(按钮), img(图片),list(列表)等。 +- 高级图形效果:动画,反锯齿,透明度,平滑滚动。 +- 支持多种输入设备,像 touchpad, keyboard等。 +- GUI guider工具可实现可视化组件拖曳式开发,方便快捷。 +- 提供了丰富的在线和离线文档。 + +## 章节目录 + +- [LVGL-流程](./lvgl_flow.md):介绍LVGL与LCD等硬件设备的关联以及LVGL完整的工作流程。 +- [LVGL-常用组件](./lvgl_control.md):介绍LVGL对象的一些基本概念,包括对象间的关系(父级子级),样式,事件等;介绍项目中常用的组件的用法及API。 +- [LVGL-示例](./lvgl_demo.md):教您如何快速上手使用Quecpython LVGL开发一个GUI应用程序。 +- [LVGL-字体库](./lvgl_fontlib.md):如果LVGL默认字体库不能满足您的项目需求,请翻阅本章。 +- [LVGL-UI工具](./lvgl_ui_tool.md):介绍GUI guider工具的使用,即使不熟悉LVGL接口也能使用它轻松开发,帮您的UI开发节约90%的时间。 +- [LVGL-应用场景](./lvgl_application_scenarios.md):介绍Quecpython LVGL目前的几个主要应用场景,并给出开发指导。 +- [LVGL-注意事项](./lvgl_notes.md):避坑必看,总结了项目开发过程中经常遇到的问题,让您的GUI开发更顺利。 + diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl_application_scenarios.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl_application_scenarios.md index 3b6e0aa35d5701e58bc7881a52259c4feb07eb02..7fa2bdc875ae9edf5bd1b19324f3fb0c13ce0269 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl_application_scenarios.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl_application_scenarios.md @@ -1,18 +1,18 @@ -# LVGL-应用场景 - -## 概述 - -目前,Quecpython LVGL已经在以下应用场景锋芒初露: - -- 智能手表 -- 电子学生卡 -- 两轮车仪表盘 -- 对讲机 -- 充电桩 - -凭借LVGL和Quecpython二者的优势,未来将有更多的应用场景加入进来。 - -### 典型场景的开发建议 - --todo - +# LVGL-应用场景 + +## 概述 + +目前,Quecpython LVGL已经在以下应用场景锋芒初露: + +- 智能手表 +- 电子学生卡 +- 两轮车仪表盘 +- 对讲机 +- 充电桩 + +凭借LVGL和Quecpython二者的优势,未来将有更多的应用场景加入进来。 + +### 典型场景的开发建议 + +-todo + diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl_control.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl_control.md index 9f7bfec3a1a3c3582287a7c0ad59d5ddeea69443..1e2c835d4603d1796c1281c25a5c26a5286e928f 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl_control.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl_control.md @@ -1,518 +1,518 @@ -# LVGL-常用组件 - -LVGL库提供了一系列组件,用于构建用户界面的基本元素。这些组件包括但不限于按钮、标签、文本框、列表、滑块、图表等。每个组件都具有独特的功能和样式,开发者可以通过设置属性和样式来定制它们的外观和行为,以满足特定应用场景的需求。 - -以下介绍LVGL常用组件,使用以下组件可以实现绝大部分界面需求。若需了解所有的组件及其API说明,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 - -## LVGL基础对象 - -### 概述 - -`基础对象`实现了屏幕上组件的基本属性,例如: - -- 坐标 - -- 父对象 - -- 基于父对象的后代 - -- 包含样式 - -- 诸如可点击(Clickable)、可滚动(Scrollable) 等属性。 - -`基础对象`是 LVGL 中所有组件的基类,其他组件对象均继承自基础对象。 - -`基础对象`可以直接用作一个简单的组件:它就是一个矩形。在没有指定父类对象的时候,一个基础对象就独自构成一个LVGL界面。在指定父类对象的时候,它是一个容器。 - -#### 坐标(Coordinates) - -##### 大小(Size) - -您可以使用`set_width(new_width)`和`set_height(new_height)`设置或修改单个轴上的对象大小,或者可以使用`set_size(new_width, new_height)`同时修改两个轴 。 - -##### 位置(Position) - -您可以使用`set_x(new_x)`和`set_y(new_y)`设置相对于父级的位置,或者使用`set_pos(new_x, new_y)`来同时设置两个轴的位置。 - -##### 对齐(Alignment) - -可以使用设置align(对齐)设置一个控件相对于父容器的对齐方式,Quecpython接口有下面两个: - -- `obj.align(lvgl.ALIGN.type,x,y)` -- `obj.set_align(lvgl.ALIGN.type)` - -> 如果设置居中,有快捷接口`obj.center()` - -LVGL支持的对齐方式见下图: - -![image-20230726163115149](../../media/multi-media/lvgl/lvgl_align_type.png) - -例如,以下代码会将对象从其父对象的中心移动 10(x),20(y) 像素: - -```python -import lvgl as lv - -obj = lv.obj(lv.scr_act()) - -obj.set_align(lv.ALIGN.CENTER); -obj.set_pos(10, 20); - -//Or in one function -obj.align(lv.ALIGN.CENTER, 10, 20); -``` - -#### 父对象和子对象(Parents and children) - -除了界面对象,所有LVGL组件对象都有父对象。 - -父对象和子对象具有以下特点: - -- 一起移动 -- 子对象仅在父对象范围可见 - -组件对象在创建的时候,就需要指定父级对象。您可以使用 `obj.set_parent(new_parent)`为对象设置新的父级。要获取当前父级,请使用 `obj.get_parent()`。 - -要获取父对象的特定子对象,请使用`obj.get_child(idx)`。 idx 的一些示例: - -- `0` 获取创建的第一个子对象 - -- `1` 获取创建的第二个子对象 - -- `-1` 获取最后创建的子对象 - -父级的子对象们可以这样迭代: - -```python -for i in range(obj.get_child_cnt()): - child_obj = obj.get_child(i) -``` - -`obj.get_index()`返回对象在其父对象中的索引。 - -您可以使用`obj.move_foreground()`和`obj.move_background()`将对象移到前台或将其移到后台。 - -#### 显示和屏幕(Display and Screens) - -在 LVGL 中,对象层次结构的最高级别是 `display`,它代表显示设备(物理显示器或模拟器)的驱动程序,[LVGL与显示设备的关联](./LVGL流程.MD)在前面的章节已有描述,不做赘述。 一个显示器可以有一个或多个与其相关联的界面。 每个界面都包含图形组件的对象层次结构。 - -当你创建了一个像`screen = lv.obj()`这样的界面对象时,你可以用`lv.scr_load(screen)`激活它。 - -`lv.scr_act()` 函数为当前活动的界面对象。 - -#### 事件(Events) - -要为对象设置事件回调,请使用 `obj.add_event_cb(event_cb, lv.EVENT.type, user_data)`, - -要手动向对象发送事件,请使用 `lv.event_send(obj, lv.EVENT.type, param)` - -请阅读 [事件概述](https://docs.lvgl.io/8.3/overview/event.html) 章节,以了解有关事件的更多信息。 - -#### 样式(Styles) - -可以使用`obj.add_style(new_style, selector)`函数向对象添加新样式。 - -selector可以组合使用。 例如:`lv.PART.SCROLLBAR | lv.STATE.PRESSED`。 - -基础对象的selector使用`lv.PART.MAIN`和`lv.PART.SCROLLBAR`。 - -请阅读 [样式概述](https://docs.lvgl.io/8.3/overview/style.html) 章节详细了解。 - -#### 宏开关(Flags) - -有一些属性可以通过`obj.add/clear_flag(lv.obj.FLAG.type)`启用/禁用。`lv.obj.FLAG.type`见API常量。 - -### API - -> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 -> -> 以下描述均默认`import lvgl as lv`。 - -#### 构造函数 - -##### `lv.obj(parent)` - -创建一个基础对象(矩形)。 - -**参数描述:** - -- `parent` - 父对象,object类型,不指定则创建的是界面对象。 - -#### 方法 - -##### `obj.add_style(style_obj,selector)` - -给对象添加样式。 - -**参数描述:** - -- `style_obj` - 样式对象,style_obj类型,要添加的样式。 -- `selector` - 选择器,常量,要添加样式的部分及状态,可以组合使用。 例如:`lv.PART.SCROLLBAR | lv.STATE.PRESSED`。 - -##### `obj.add_flag(type)` - -给对象添加宏开关。 - -**参数描述:** - -- `type` - flag类型,常量,要添加的宏开关类型,可以一个或多个类型。 - -##### `obj.clear_flag(type)` - -清除对象的宏开关。 - -**参数描述:** - -- `type` - flag类型,常量,要清除的宏开关类型,可以多个类型。 - -##### `obj.add_state(state)` - -向对象添加一个或多个状态。其他状态位将保持不变。如果在样式中指定,则过渡动画将从以前的状态开始到当前状态。 - -**参数描述:** - -- `state` - state类型,常量,要添加的状态类型,可以一个或多个状态 。 - -##### `obj.clear_state(state)` - -删除对象的一个或多个状态。其他状态位将保持不变。如果在样式中指定,则过渡动画将从以前的状态开始到当前状态。 - -**参数描述:** - -- `state` - state类型,常量,要清除的状态类型,可以一个或多个状态 。 - -##### `obj.get_state()` - -获取对象的状态。 - -#### 常量 - -##### `flag` - -宏开关 - -- `lv.obj.FLAG.HIDDEN` 隐藏对象 -- `lv.obj.FLAG.CLICKABLE` 使输入设备可点击对象 -- `lv.obj.FLAG.CLICK_FOCUSABLE` 单击时将焦点状态添加到对象 -- `lv.obj.FLAG.CHECKABLE` 对象被点击时切换选中状态 -- `lv.obj.FLAG.SCROLLABLE` 使对象可滚动 -- `lv.obj.FLAG.SCROLL_ELASTIC` 允许在内部滚动但速度较慢 -- `lv.obj.FLAG.SCROLL_MOMENTUM` 在“抛出”时使对象滚动得更远 -- `lv.obj.FLAG.SCROLL_ONE` 只允许滚动一个可捕捉的子对象 -- `lv.obj.FLAG.SCROLL_CHAIN` 允许将滚动传播到父级 -- `lv.obj.FLAG.SCROLL_ON_FOCUS` 自动滚动对象以使其在聚焦时可见 -- `lv.obj.FLAG.SNAPPABLE` 如果在父对象上启用了滚动捕捉,它可以捕捉到这个对象 -- `lv.obj.FLAG.PRESS_LOCK` 保持对象被按下,即使按下从对象上滑动 -- `lv.obj.FLAG.EVENT_BUBBLE` 也将事件传播给父级 -- `lv.obj.FLAG.GESTURE_BUBBLE` 将手势传播给父级 -- `lv.obj.FLAG.ADV_HITTEST` 允许执行更准确的命中(点击)测试。例如。考虑圆角。 -- `lv.obj.FLAG.IGNORE_LAYOUT` 使对象可以通过布局定位 -- `lv.obj.FLAG.FLOATING` 父滚动时不滚动对象,忽略布局 - -##### `PART` - -- `lv.PART.MAIN` 类似矩形的背景 -- `lv.PART.SCROLLBAR` 滚动条部分 -- `lv.PART.INDICATOR` 指示部分,例如用于圆弧、条、开关或复选框的勾选框 -- `lv.PART.KNOB` 向圆弧的帽子部分 -- `lv.PART.SELECTED` 表示当前选择的选项或部分 -- `lv.PART.ITEMS` 如果小部件有多个相似的元素(例如表格单元格) -- `lv.PART.TICKS` 刻度上的刻度,例如对于图表或仪表 -- `lv.PART.CURSOR` 标记一个特定的地方,例如文本区域或图表的光标 -- `lv.PART.CUSTOM_FIRST` 可以从这里添加自定义部件。 - -##### `state` - -- `lv.STATE.DEFAULT` 正常, 释放状态默认状态 -- `lv.STATE.CHECKED` 切换或者选中状态 -- `lv.STATE.FOCUSED` 被按键或者编码器聚焦/被触摸屏或鼠标点击 -- `lv.STATE.FOCUS_KEY` 被按键或者编码器聚焦但不是被触摸屏或鼠标点击 -- `lv.STATE.EDITED` 被编码器编辑 -- `lv.STATE.HOVERED` 鼠标悬停(暂不支持) -- `lv.STATE.PRESSED` 被按住 -- `lv.STATE.SCROLLED` 正在滚动 -- `lv.STATE.DISABLED` 失效状态 - -##### `flex-flow` - -- `lv.FLEX_FLOW.ROW` 将子对象排成一行而换行 -- `lv.FLEX_FLOW.COLUMN` 将子对象放在一列中而不换行 -- `lv.FLEX_FLOW.ROW_WRAP` 将子对象排成一排,不超过父容器的宽,否则换行 -- `lv.FLEX_FLOW.COLUMN_WRAP` 将子对象放成一列,不超过父容器的高,否则换行 -- `lv.FLEX_FLOW.ROW_REVERSE` 将子对象排成一行而不换行,但顺序相反 -- `lv.FLEX_FLOW.COLUMN_REVERSE` 将子对象放在一列中,不换行,但顺序相反 -- `lv.FLEX_FLOW.ROW_WRAP_REVERSE` 将子对象排成一行而不换行,但顺序相反 -- `lv.FLEX_FLOW.COLUMN_WRAP_REVERSE` 将子对象放在一列中,不换行,但顺序相反 - -## 标签(label) - -### 概述 - -标签是用来显示文本的对象类型。 - -### 部分和风格(Parts and Styles) - -- `lv.PART.MAIN`表示整个背景和文本部分。 填充值可用于在文本和背景之间添加间隙。 -- `lv.PART.SCROLLBAR` 当文本大于组件的大小时显示的滚动条。 -- `lv.PART.SELECTED` 表示所选文本的部分。 只能使用 `text_color` 和 `bg_color` 样式属性。 - -### 用法(Usage) - -#### 设置文本(Set text) - -您可以在LVGL运行时使用 `label.set_text("New text")` 设置标签上的文本。 - -换行符由标签对象自动处理。 您可以使用 `\n` 来换行。 例如:`"line1\nline2\n\nline4"` - -#### 长模式(long mode) - -默认情况下,标签的大小会自动扩展到文本大小。 如果显式设置宽度或高度(使用例如`label.set_size` 或布局),则可以根据几种长模式策略来操作比标签宽度更宽的行。 类似地,如果文本的高度大于标签的高度,则可以应用策略。 - -- `lv.label.LONG.WRAP` 文本太长,将被剪裁。 (默认) -- `lv.label.LONG.DOT` 将标签右下角的最后 3 个字符替换为点 (`.`) -- `lv.label.LONG.SCROLL` 如果文本比标签宽,则水平来回滚动它。如果它更高,垂直滚动。只滚动一个方向,水平滚动的优先级更高。 -- `lv.label.LONG.SCROLL_CIRCULAR` 如果文本比标签宽,则水平滚动它。如果它更高,请垂直滚动。只滚动一个方向,水平滚动的优先级更高。 -- `lv.label.LONG.CLIP` 只需剪掉标签外的文本部分。 - -您可以使用 `label.set_long_mode(type)` 指定长模式。 - -#### 事件(Events) - -标签组件不发送特殊事件。 - -可以使用`lv.obj.FLAG.CLICKABLE` 使标签变成可点击对象,这样它近似于一个透明的按钮,可以添加点击事件。 - -### API - -> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 - -#### 构造函数 - -##### `lv.label(parent)` - -创建一个标签。 - -**参数描述:** - -- `parent` - 父对象,object类型,必填。 - -#### 方法 - -##### `label.set_text(text)` - -给标签设置显示文本。 - -**参数描述:** - -- `text` - 文本内容,string类型,要显示的文本。 - -##### `label.set_long_mode(type)` - -给标签设置长文本模式。 - -**参数描述:** - -- `type` - 模式,常量,长文本模式。 - -##### `label.get_text()` - -获取标签的显示文本。 - -**返回值描述:** - -- `text` - 文本内容,string类型,显示的文本。 - -#### 常量 - -##### `LONG` - -长文本模式 - -- `lv.label.LONG.WRAP` 文本太长,将被剪裁。 (默认) -- `lv.label.LONG.DOT` 将标签右下角的最后 3 个字符替换为点 (`.`) -- `lv.label.LONG.SCROLL` 如果显示文本比标签宽,则水平来回滚动它。如果它更高,垂直滚动。只滚动一个方向,水平滚动的优先级更高。 -- `lv.label.LONG.SCROLL_CIRCULAR` 如果文本比标签宽,则水平滚动它。如果它更高,垂直滚动。只滚动一个方向,水平滚动的优先级更高。 -- `lv.label.LONG.CLIP` 只需剪掉标签外的文本部分。 - -## 图像(image) - -### 概述 - -图像是显示来自闪存(作为数组)或来自文件的图像的基本对象。 图像也可以显示符号(`lv.SYMBOL....`)。 - -### 部分和风格(Parts and Styles) - -- `lv.PART.MAIN`表示整个背景和图像部分。 - -### 用法(Usage) - -#### 图片来源(Image source) - -为了提供最大的灵活性,图像的来源可以是: - -- 文件系统的文件。 -- Symbols图标。 - -要设置图像的来源,请使用`img.set_src(src)`。 - -要使用文件系统的文件,请将图片文件下载至文件系统,使用`img.set_src("U:/my_img.jpg")`。 - -您还可以设置类似于标签的符号。 在这种情况下,图像将根据样式中指定的 font 呈现为文本。 它其实是一个轻量级单色“字母”而不是真实图像。 你可以设置像`img.set_src(lv.SYMBOL.OK)`这样的符号。 - -#### 转换(Transformations) - -使用 `img.set_zoom(factor)` 图像将被缩放。 将 `factor` 设置为 `256` 为原图大小。 较大的值会放大图像(例如“512”双倍尺寸),较小的值会缩小图像(例如“128”半尺寸)。 分数尺度也有效。 例如。 `281` 放大 10%。 - -要旋转图像,请使用 `img.set_angle(angle)`。 角度的精度为 0.1 度,因此对于 45.8° 设置 458。 - -默认情况下,旋转的轴心点是图像的中心。 它可以通过 `img.set_pivot(pivot_x, pivot_y)` 改变。 `0;0` 是左上角。 - -转换的质量可以通过 `img.set_antialias(True/False)` 来调整。 启用抗锯齿后,转换质量更高但速度更慢。 - -请注意,图像对象的真实坐标在转换过程中不会改变。 即`obj.get_width/height/x/y()` 将返回原始的、未缩放的坐标。 - -#### 事件(Events) - -图像组件不发送特殊事件。 - -可以使用`lv.obj.FLAG.CLICKABLE` 使标签变成可点击对象,这样它近似于一个图像按钮,可以添加点击事件。 - -> **注意**:图像组件能使用图片缓存机制,所以相较于图像按钮组件,更推荐使用图像组件。 - -### API - -> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 - -#### 构造函数 - -##### `lv.img(parent)` - -创建一个图像。 - -**参数描述:** - -- `parent` - 父对象,object类型,必填。 - -#### 方法 - -##### `img.set_src(src)` - -给图像设置图像源。 - -**参数描述:** - -- `src` - 1)图像文件的路径,string类型,要显示的图像的路径。2)`SYMBOL`,例如`lv.SYMBOL.OK` - -##### `img.set_offset_x(x)` - -为图像的源设置x轴偏移,以便从新原点显示图像。 - -**参数描述:** - -- `x` - x轴偏移,int类型。 - -##### `img.set_offset_y(y)` - -为图像的源设置y轴偏移,以便从新原点显示图像。 - -**参数描述:** - -- `y` - y轴偏移,int类型。 - -##### `img.set_angle(angle)` - -图像设置旋转角度。 - -**参数描述:** - -- `angle` - 角度,int类型,精度为0.1度。 - -##### `img.set_zoom(factor)` - -图像设置缩放大小。 - -**参数描述:** - -- `factor` - 缩放程度,int类型,256为原图大小,512双倍尺寸。 - -##### `img.set_pivot(x,y)` - -设置图像的旋转中心,图像将围绕此点旋转。 - -**参数描述:** - -- `x` - 旋转中心x轴坐标,int类型。 -- `y` - 旋转中心y轴坐标,int类型。 - -##### `img.set_antialias(antialias)` - -是否启用/禁用变换的抗锯齿(旋转、缩放)。抗锯齿效果更好,但速度较慢。 - -**参数描述:** - -- `antialias` - 抗锯齿,bool类型,True为使能,False为禁止。 - -## 按钮(Button) - -### 概述 - -与基础对象相比,按钮没有新功能。 它们可用于语义目的,并且默认设置略有不同。 - -默认情况下,按钮在以下方面与基础对象不同: - -- 不可滚动 -- 添加到默认组 -- 默认高度和宽度设置为 `LV_SIZE_CONTENT` - -### 部分和风格(Parts and Styles) - -- `lv.PART.MAIN`表示按钮的背景部分。 - -### 用法(Usage) - -与基础对象相比,按钮没有新功能 - -#### 事件(Events) - -当对象被点击时有选中切换(Toggle)状态的效果,并且可以在 `lv.EVENT.VALUE_CHANGED` 事件类型中处理事件。 - -#### 事件(Events) - -请注意,`lv.KEY.ENTER` 的状态被转换为 `lv.EVENT.PRESSED/PRESSING/RELEASED` 等。 - -参见基础对象的事件。 - -### API - -> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 - -#### 构造函数 - -##### `lv.btn(parent)` - -创建一个按钮。 - -**参数描述:** - -- `parent` - 父对象,object类型,必填。 - -## LVGL其他组件 - -除了上述介绍的组件,LVGL还提供以下组件,项目中选择使用哪种组件请视需求而定。 - -| **组件** | 构造函数 | 说明 | LVGL官网链接 | -| -------- | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -| 列表 | `lv.list()` | 一个垂直布局的矩形,可以向其中添加按钮和文本 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/list.html) | -| 窗口 | `lv.win()` | 由一个带有标题、按钮和内容区域的标题构建而成的容器 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/win.html) | -| 弧 | `lv.acr()` | 圆弧由背景和前景弧组成。前景(指示器)可以进行触摸调整 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/core/arc.html) | -| 进度条 | `lv.bar()` | 显示进度 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/core/bar.html) | -| 开关 | `lv.sw()` | 看起来像一个小滑块,开关的功能类似于按钮,也可以用来打开和关闭某些东西 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/core/switch.html) | -| 滑动页 | `lv.tileview()` | 菜单页可用,比较界面切换的动画,多出了手指跟随的效果 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/tileview.html) | -| 仪表盘 | `lv.meter()` | 以非常灵活的方式可视化数据。在中可以显示圆弧、指针、刻度线和标签 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/meter.html) | -| 图表 | `lv.chart()` | 折线图,直方图,散点图 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/chart.html) | -| 键盘 | `lv.keyboard()` | 特殊的按钮矩阵,自身实现了按键映射 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/keyboard.html) | -| 菜单 | `lv.menu()` | 多级菜单,它自动处理页面之间的遍历 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/menu.html) | - - - - - +# LVGL-常用组件 + +LVGL库提供了一系列组件,用于构建用户界面的基本元素。这些组件包括但不限于按钮、标签、文本框、列表、滑块、图表等。每个组件都具有独特的功能和样式,开发者可以通过设置属性和样式来定制它们的外观和行为,以满足特定应用场景的需求。 + +以下介绍LVGL常用组件,使用以下组件可以实现绝大部分界面需求。若需了解所有的组件及其API说明,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 + +## LVGL基础对象 + +### 概述 + +`基础对象`实现了屏幕上组件的基本属性,例如: + +- 坐标 + +- 父对象 + +- 基于父对象的后代 + +- 包含样式 + +- 诸如可点击(Clickable)、可滚动(Scrollable) 等属性。 + +`基础对象`是 LVGL 中所有组件的基类,其他组件对象均继承自基础对象。 + +`基础对象`可以直接用作一个简单的组件:它就是一个矩形。在没有指定父类对象的时候,一个基础对象就独自构成一个LVGL界面。在指定父类对象的时候,它是一个容器。 + +#### 坐标(Coordinates) + +##### 大小(Size) + +您可以使用`set_width(new_width)`和`set_height(new_height)`设置或修改单个轴上的对象大小,或者可以使用`set_size(new_width, new_height)`同时修改两个轴 。 + +##### 位置(Position) + +您可以使用`set_x(new_x)`和`set_y(new_y)`设置相对于父级的位置,或者使用`set_pos(new_x, new_y)`来同时设置两个轴的位置。 + +##### 对齐(Alignment) + +可以使用设置align(对齐)设置一个控件相对于父容器的对齐方式,Quecpython接口有下面两个: + +- `obj.align(lvgl.ALIGN.type,x,y)` +- `obj.set_align(lvgl.ALIGN.type)` + +> 如果设置居中,有快捷接口`obj.center()` + +LVGL支持的对齐方式见下图: + +![image-20230726163115149](../../media/multi-media/lvgl/lvgl_align_type.png) + +例如,以下代码会将对象从其父对象的中心移动 10(x),20(y) 像素: + +```python +import lvgl as lv + +obj = lv.obj(lv.scr_act()) + +obj.set_align(lv.ALIGN.CENTER); +obj.set_pos(10, 20); + +//Or in one function +obj.align(lv.ALIGN.CENTER, 10, 20); +``` + +#### 父对象和子对象(Parents and children) + +除了界面对象,所有LVGL组件对象都有父对象。 + +父对象和子对象具有以下特点: + +- 一起移动 +- 子对象仅在父对象范围可见 + +组件对象在创建的时候,就需要指定父级对象。您可以使用 `obj.set_parent(new_parent)`为对象设置新的父级。要获取当前父级,请使用 `obj.get_parent()`。 + +要获取父对象的特定子对象,请使用`obj.get_child(idx)`。 idx 的一些示例: + +- `0` 获取创建的第一个子对象 + +- `1` 获取创建的第二个子对象 + +- `-1` 获取最后创建的子对象 + +父级的子对象们可以这样迭代: + +```python +for i in range(obj.get_child_cnt()): + child_obj = obj.get_child(i) +``` + +`obj.get_index()`返回对象在其父对象中的索引。 + +您可以使用`obj.move_foreground()`和`obj.move_background()`将对象移到前台或将其移到后台。 + +#### 显示和屏幕(Display and Screens) + +在 LVGL 中,对象层次结构的最高级别是 `display`,它代表显示设备(物理显示器或模拟器)的驱动程序,[LVGL与显示设备的关联](./LVGL流程.MD)在前面的章节已有描述,不做赘述。 一个显示器可以有一个或多个与其相关联的界面。 每个界面都包含图形组件的对象层次结构。 + +当你创建了一个像`screen = lv.obj()`这样的界面对象时,你可以用`lv.scr_load(screen)`激活它。 + +`lv.scr_act()` 函数为当前活动的界面对象。 + +#### 事件(Events) + +要为对象设置事件回调,请使用 `obj.add_event_cb(event_cb, lv.EVENT.type, user_data)`, + +要手动向对象发送事件,请使用 `lv.event_send(obj, lv.EVENT.type, param)` + +请阅读 [事件概述](https://docs.lvgl.io/8.3/overview/event.html) 章节,以了解有关事件的更多信息。 + +#### 样式(Styles) + +可以使用`obj.add_style(new_style, selector)`函数向对象添加新样式。 + +selector可以组合使用。 例如:`lv.PART.SCROLLBAR | lv.STATE.PRESSED`。 + +基础对象的selector使用`lv.PART.MAIN`和`lv.PART.SCROLLBAR`。 + +请阅读 [样式概述](https://docs.lvgl.io/8.3/overview/style.html) 章节详细了解。 + +#### 宏开关(Flags) + +有一些属性可以通过`obj.add/clear_flag(lv.obj.FLAG.type)`启用/禁用。`lv.obj.FLAG.type`见API常量。 + +### API + +> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 +> +> 以下描述均默认`import lvgl as lv`。 + +#### 构造函数 + +##### `lv.obj(parent)` + +创建一个基础对象(矩形)。 + +**参数描述:** + +- `parent` - 父对象,object类型,不指定则创建的是界面对象。 + +#### 方法 + +##### `obj.add_style(style_obj,selector)` + +给对象添加样式。 + +**参数描述:** + +- `style_obj` - 样式对象,style_obj类型,要添加的样式。 +- `selector` - 选择器,常量,要添加样式的部分及状态,可以组合使用。 例如:`lv.PART.SCROLLBAR | lv.STATE.PRESSED`。 + +##### `obj.add_flag(type)` + +给对象添加宏开关。 + +**参数描述:** + +- `type` - flag类型,常量,要添加的宏开关类型,可以一个或多个类型。 + +##### `obj.clear_flag(type)` + +清除对象的宏开关。 + +**参数描述:** + +- `type` - flag类型,常量,要清除的宏开关类型,可以多个类型。 + +##### `obj.add_state(state)` + +向对象添加一个或多个状态。其他状态位将保持不变。如果在样式中指定,则过渡动画将从以前的状态开始到当前状态。 + +**参数描述:** + +- `state` - state类型,常量,要添加的状态类型,可以一个或多个状态 。 + +##### `obj.clear_state(state)` + +删除对象的一个或多个状态。其他状态位将保持不变。如果在样式中指定,则过渡动画将从以前的状态开始到当前状态。 + +**参数描述:** + +- `state` - state类型,常量,要清除的状态类型,可以一个或多个状态 。 + +##### `obj.get_state()` + +获取对象的状态。 + +#### 常量 + +##### `flag` + +宏开关 + +- `lv.obj.FLAG.HIDDEN` 隐藏对象 +- `lv.obj.FLAG.CLICKABLE` 使输入设备可点击对象 +- `lv.obj.FLAG.CLICK_FOCUSABLE` 单击时将焦点状态添加到对象 +- `lv.obj.FLAG.CHECKABLE` 对象被点击时切换选中状态 +- `lv.obj.FLAG.SCROLLABLE` 使对象可滚动 +- `lv.obj.FLAG.SCROLL_ELASTIC` 允许在内部滚动但速度较慢 +- `lv.obj.FLAG.SCROLL_MOMENTUM` 在“抛出”时使对象滚动得更远 +- `lv.obj.FLAG.SCROLL_ONE` 只允许滚动一个可捕捉的子对象 +- `lv.obj.FLAG.SCROLL_CHAIN` 允许将滚动传播到父级 +- `lv.obj.FLAG.SCROLL_ON_FOCUS` 自动滚动对象以使其在聚焦时可见 +- `lv.obj.FLAG.SNAPPABLE` 如果在父对象上启用了滚动捕捉,它可以捕捉到这个对象 +- `lv.obj.FLAG.PRESS_LOCK` 保持对象被按下,即使按下从对象上滑动 +- `lv.obj.FLAG.EVENT_BUBBLE` 也将事件传播给父级 +- `lv.obj.FLAG.GESTURE_BUBBLE` 将手势传播给父级 +- `lv.obj.FLAG.ADV_HITTEST` 允许执行更准确的命中(点击)测试。例如。考虑圆角。 +- `lv.obj.FLAG.IGNORE_LAYOUT` 使对象可以通过布局定位 +- `lv.obj.FLAG.FLOATING` 父滚动时不滚动对象,忽略布局 + +##### `PART` + +- `lv.PART.MAIN` 类似矩形的背景 +- `lv.PART.SCROLLBAR` 滚动条部分 +- `lv.PART.INDICATOR` 指示部分,例如用于圆弧、条、开关或复选框的勾选框 +- `lv.PART.KNOB` 向圆弧的帽子部分 +- `lv.PART.SELECTED` 表示当前选择的选项或部分 +- `lv.PART.ITEMS` 如果小部件有多个相似的元素(例如表格单元格) +- `lv.PART.TICKS` 刻度上的刻度,例如对于图表或仪表 +- `lv.PART.CURSOR` 标记一个特定的地方,例如文本区域或图表的光标 +- `lv.PART.CUSTOM_FIRST` 可以从这里添加自定义部件。 + +##### `state` + +- `lv.STATE.DEFAULT` 正常, 释放状态默认状态 +- `lv.STATE.CHECKED` 切换或者选中状态 +- `lv.STATE.FOCUSED` 被按键或者编码器聚焦/被触摸屏或鼠标点击 +- `lv.STATE.FOCUS_KEY` 被按键或者编码器聚焦但不是被触摸屏或鼠标点击 +- `lv.STATE.EDITED` 被编码器编辑 +- `lv.STATE.HOVERED` 鼠标悬停(暂不支持) +- `lv.STATE.PRESSED` 被按住 +- `lv.STATE.SCROLLED` 正在滚动 +- `lv.STATE.DISABLED` 失效状态 + +##### `flex-flow` + +- `lv.FLEX_FLOW.ROW` 将子对象排成一行而换行 +- `lv.FLEX_FLOW.COLUMN` 将子对象放在一列中而不换行 +- `lv.FLEX_FLOW.ROW_WRAP` 将子对象排成一排,不超过父容器的宽,否则换行 +- `lv.FLEX_FLOW.COLUMN_WRAP` 将子对象放成一列,不超过父容器的高,否则换行 +- `lv.FLEX_FLOW.ROW_REVERSE` 将子对象排成一行而不换行,但顺序相反 +- `lv.FLEX_FLOW.COLUMN_REVERSE` 将子对象放在一列中,不换行,但顺序相反 +- `lv.FLEX_FLOW.ROW_WRAP_REVERSE` 将子对象排成一行而不换行,但顺序相反 +- `lv.FLEX_FLOW.COLUMN_WRAP_REVERSE` 将子对象放在一列中,不换行,但顺序相反 + +## 标签(label) + +### 概述 + +标签是用来显示文本的对象类型。 + +### 部分和风格(Parts and Styles) + +- `lv.PART.MAIN`表示整个背景和文本部分。 填充值可用于在文本和背景之间添加间隙。 +- `lv.PART.SCROLLBAR` 当文本大于组件的大小时显示的滚动条。 +- `lv.PART.SELECTED` 表示所选文本的部分。 只能使用 `text_color` 和 `bg_color` 样式属性。 + +### 用法(Usage) + +#### 设置文本(Set text) + +您可以在LVGL运行时使用 `label.set_text("New text")` 设置标签上的文本。 + +换行符由标签对象自动处理。 您可以使用 `\n` 来换行。 例如:`"line1\nline2\n\nline4"` + +#### 长模式(long mode) + +默认情况下,标签的大小会自动扩展到文本大小。 如果显式设置宽度或高度(使用例如`label.set_size` 或布局),则可以根据几种长模式策略来操作比标签宽度更宽的行。 类似地,如果文本的高度大于标签的高度,则可以应用策略。 + +- `lv.label.LONG.WRAP` 文本太长,将被剪裁。 (默认) +- `lv.label.LONG.DOT` 将标签右下角的最后 3 个字符替换为点 (`.`) +- `lv.label.LONG.SCROLL` 如果文本比标签宽,则水平来回滚动它。如果它更高,垂直滚动。只滚动一个方向,水平滚动的优先级更高。 +- `lv.label.LONG.SCROLL_CIRCULAR` 如果文本比标签宽,则水平滚动它。如果它更高,请垂直滚动。只滚动一个方向,水平滚动的优先级更高。 +- `lv.label.LONG.CLIP` 只需剪掉标签外的文本部分。 + +您可以使用 `label.set_long_mode(type)` 指定长模式。 + +#### 事件(Events) + +标签组件不发送特殊事件。 + +可以使用`lv.obj.FLAG.CLICKABLE` 使标签变成可点击对象,这样它近似于一个透明的按钮,可以添加点击事件。 + +### API + +> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 + +#### 构造函数 + +##### `lv.label(parent)` + +创建一个标签。 + +**参数描述:** + +- `parent` - 父对象,object类型,必填。 + +#### 方法 + +##### `label.set_text(text)` + +给标签设置显示文本。 + +**参数描述:** + +- `text` - 文本内容,string类型,要显示的文本。 + +##### `label.set_long_mode(type)` + +给标签设置长文本模式。 + +**参数描述:** + +- `type` - 模式,常量,长文本模式。 + +##### `label.get_text()` + +获取标签的显示文本。 + +**返回值描述:** + +- `text` - 文本内容,string类型,显示的文本。 + +#### 常量 + +##### `LONG` + +长文本模式 + +- `lv.label.LONG.WRAP` 文本太长,将被剪裁。 (默认) +- `lv.label.LONG.DOT` 将标签右下角的最后 3 个字符替换为点 (`.`) +- `lv.label.LONG.SCROLL` 如果显示文本比标签宽,则水平来回滚动它。如果它更高,垂直滚动。只滚动一个方向,水平滚动的优先级更高。 +- `lv.label.LONG.SCROLL_CIRCULAR` 如果文本比标签宽,则水平滚动它。如果它更高,垂直滚动。只滚动一个方向,水平滚动的优先级更高。 +- `lv.label.LONG.CLIP` 只需剪掉标签外的文本部分。 + +## 图像(image) + +### 概述 + +图像是显示来自闪存(作为数组)或来自文件的图像的基本对象。 图像也可以显示符号(`lv.SYMBOL....`)。 + +### 部分和风格(Parts and Styles) + +- `lv.PART.MAIN`表示整个背景和图像部分。 + +### 用法(Usage) + +#### 图片来源(Image source) + +为了提供最大的灵活性,图像的来源可以是: + +- 文件系统的文件。 +- Symbols图标。 + +要设置图像的来源,请使用`img.set_src(src)`。 + +要使用文件系统的文件,请将图片文件下载至文件系统,使用`img.set_src("U:/my_img.jpg")`。 + +您还可以设置类似于标签的符号。 在这种情况下,图像将根据样式中指定的 font 呈现为文本。 它其实是一个轻量级单色“字母”而不是真实图像。 你可以设置像`img.set_src(lv.SYMBOL.OK)`这样的符号。 + +#### 转换(Transformations) + +使用 `img.set_zoom(factor)` 图像将被缩放。 将 `factor` 设置为 `256` 为原图大小。 较大的值会放大图像(例如“512”双倍尺寸),较小的值会缩小图像(例如“128”半尺寸)。 分数尺度也有效。 例如。 `281` 放大 10%。 + +要旋转图像,请使用 `img.set_angle(angle)`。 角度的精度为 0.1 度,因此对于 45.8° 设置 458。 + +默认情况下,旋转的轴心点是图像的中心。 它可以通过 `img.set_pivot(pivot_x, pivot_y)` 改变。 `0;0` 是左上角。 + +转换的质量可以通过 `img.set_antialias(True/False)` 来调整。 启用抗锯齿后,转换质量更高但速度更慢。 + +请注意,图像对象的真实坐标在转换过程中不会改变。 即`obj.get_width/height/x/y()` 将返回原始的、未缩放的坐标。 + +#### 事件(Events) + +图像组件不发送特殊事件。 + +可以使用`lv.obj.FLAG.CLICKABLE` 使标签变成可点击对象,这样它近似于一个图像按钮,可以添加点击事件。 + +> **注意**:图像组件能使用图片缓存机制,所以相较于图像按钮组件,更推荐使用图像组件。 + +### API + +> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 + +#### 构造函数 + +##### `lv.img(parent)` + +创建一个图像。 + +**参数描述:** + +- `parent` - 父对象,object类型,必填。 + +#### 方法 + +##### `img.set_src(src)` + +给图像设置图像源。 + +**参数描述:** + +- `src` - 1)图像文件的路径,string类型,要显示的图像的路径。2)`SYMBOL`,例如`lv.SYMBOL.OK` + +##### `img.set_offset_x(x)` + +为图像的源设置x轴偏移,以便从新原点显示图像。 + +**参数描述:** + +- `x` - x轴偏移,int类型。 + +##### `img.set_offset_y(y)` + +为图像的源设置y轴偏移,以便从新原点显示图像。 + +**参数描述:** + +- `y` - y轴偏移,int类型。 + +##### `img.set_angle(angle)` + +图像设置旋转角度。 + +**参数描述:** + +- `angle` - 角度,int类型,精度为0.1度。 + +##### `img.set_zoom(factor)` + +图像设置缩放大小。 + +**参数描述:** + +- `factor` - 缩放程度,int类型,256为原图大小,512双倍尺寸。 + +##### `img.set_pivot(x,y)` + +设置图像的旋转中心,图像将围绕此点旋转。 + +**参数描述:** + +- `x` - 旋转中心x轴坐标,int类型。 +- `y` - 旋转中心y轴坐标,int类型。 + +##### `img.set_antialias(antialias)` + +是否启用/禁用变换的抗锯齿(旋转、缩放)。抗锯齿效果更好,但速度较慢。 + +**参数描述:** + +- `antialias` - 抗锯齿,bool类型,True为使能,False为禁止。 + +## 按钮(Button) + +### 概述 + +与基础对象相比,按钮没有新功能。 它们可用于语义目的,并且默认设置略有不同。 + +默认情况下,按钮在以下方面与基础对象不同: + +- 不可滚动 +- 添加到默认组 +- 默认高度和宽度设置为 `LV_SIZE_CONTENT` + +### 部分和风格(Parts and Styles) + +- `lv.PART.MAIN`表示按钮的背景部分。 + +### 用法(Usage) + +与基础对象相比,按钮没有新功能 + +#### 事件(Events) + +当对象被点击时有选中切换(Toggle)状态的效果,并且可以在 `lv.EVENT.VALUE_CHANGED` 事件类型中处理事件。 + +#### 事件(Events) + +请注意,`lv.KEY.ENTER` 的状态被转换为 `lv.EVENT.PRESSED/PRESSING/RELEASED` 等。 + +参见基础对象的事件。 + +### API + +> **注意:**本章节只介绍了一些常见API,如需查看所有API,可以访问[LVGL官网](https://docs.lvgl.io/8.3/examples.html#widgets)查看。 + +#### 构造函数 + +##### `lv.btn(parent)` + +创建一个按钮。 + +**参数描述:** + +- `parent` - 父对象,object类型,必填。 + +## LVGL其他组件 + +除了上述介绍的组件,LVGL还提供以下组件,项目中选择使用哪种组件请视需求而定。 + +| **组件** | 构造函数 | 说明 | LVGL官网链接 | +| -------- | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| 列表 | `lv.list()` | 一个垂直布局的矩形,可以向其中添加按钮和文本 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/list.html) | +| 窗口 | `lv.win()` | 由一个带有标题、按钮和内容区域的标题构建而成的容器 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/win.html) | +| 弧 | `lv.acr()` | 圆弧由背景和前景弧组成。前景(指示器)可以进行触摸调整 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/core/arc.html) | +| 进度条 | `lv.bar()` | 显示进度 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/core/bar.html) | +| 开关 | `lv.sw()` | 看起来像一个小滑块,开关的功能类似于按钮,也可以用来打开和关闭某些东西 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/core/switch.html) | +| 滑动页 | `lv.tileview()` | 菜单页可用,比较界面切换的动画,多出了手指跟随的效果 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/tileview.html) | +| 仪表盘 | `lv.meter()` | 以非常灵活的方式可视化数据。在中可以显示圆弧、指针、刻度线和标签 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/meter.html) | +| 图表 | `lv.chart()` | 折线图,直方图,散点图 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/chart.html) | +| 键盘 | `lv.keyboard()` | 特殊的按钮矩阵,自身实现了按键映射 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/keyboard.html) | +| 菜单 | `lv.menu()` | 多级菜单,它自动处理页面之间的遍历 | [点击此处查看组件详细信息](https://docs.lvgl.io/8.2/widgets/extra/menu.html) | + + + + + diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl_demo.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl_demo.md index 0561c282844256e17c04293290979df7d1b184fe..7bb01aed7b5ba6fb7c8042aedd471502fdeac665 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl_demo.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl_demo.md @@ -1,232 +1,232 @@ -# LVGL-示例 - -## 概述 - -前面章节介绍了LVGL在嵌入式GUI开发上的优势,以及介绍了LVGL的工作流程和常用组件。 - -本章节将教您如何零基础快速上手使用Quecpython LVGL开发一个GUI应用程序。 - - - -## 实验环境搭建 - -### 硬件准备 - -**开发板**:LTE OPEN-EVB_V1.1和EC600U-EU_AB TE-A - -**LCD屏**:ST7789 240*320 - -### 固件下载 - -请前往[Quecpython官网下载中心](https://python.quectel.com/resource-download?cid=15)下载EC600U-EU_AB的公版固件。 - -![LVGL_demo1](../../media/multi-media/lvgl/LVGL_demo1.png) - -### 硬件连接 - -将LCD屏接好开发板的LCD接口,连接开发板的USB口,长按PWRKEY开机,如下图所示。 - -![lvgl_demo2](../../media/multi-media/lvgl/lvgl_demo2.jpg) - -### 固件烧录 - -使用QPYcom工具([下载地址](https://python.quectel.com/resource-download?cid=8)),进行固件烧录, - -![lvgl_demo3](../../media/multi-media/lvgl/lvgl_demo3.jpg) - -## 脚本编写 - -应用代码[下载链接]()。 - -### LCD初始化 - -LCD的初始化部分参见wiki:[machine LCD](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html) - -本示例使用的是分辨率240*320的ST7789屏。以下为LCD初始化部分代码: - -```python -from machine import LCD - -init_param=( -0, 0, 0x11, -2, 0, 120, -0, 0, 0x00, -0, 1, 0x36, -1, 1, 0x00, -0, 1, 0x3A, -1, 1, 0x05, -0, 1, 0x35, -1, 1, 0x00, -0, 1, 0xC7, -1, 1, 0x00, -0, 1, 0xCC, -1, 1, 0x09, -0, 5, 0xB2, -1, 1, 0x0C, -1, 1, 0x0C, -1, 1, 0x00, -1, 1, 0x33, -1, 1, 0x33, -0, 1, 0xB7, -1, 1, 0x35, -0, 1, 0xBB, -1, 1, 0x36, -0, 1, 0xC0, -1, 1, 0x2C, -0, 1, 0xC2, -1, 1, 0x01, -0, 1, 0xC3, -1, 1, 0x0D, -0, 1, 0xC4, -1, 1, 0x20, -0, 1, 0xC6, -1, 1, 0x0F, -0, 2, 0xD0, -1, 1, 0xA4, -1, 1, 0xA1, -0, 14, 0xE0, -1, 1, 0xD0, -1, 1, 0x17, -1, 1, 0x19, -1, 1, 0x04, -1, 1, 0x03, -1, 1, 0x04, -1, 1, 0x32, -1, 1, 0x41, -1, 1, 0x43, -1, 1, 0x09, -1, 1, 0x14, -1, 1, 0x12, -1, 1, 0x33, -1, 1, 0x2C, -0, 14, 0xE1, -1, 1, 0xD0, -1, 1, 0x18, -1, 1, 0x17, -1, 1, 0x04, -1, 1, 0x03, -1, 1, 0x04, -1, 1, 0x31, -1, 1, 0x46, -1, 1, 0x43, -1, 1, 0x09, -1, 1, 0x14, -1, 1, 0x13, -1, 1, 0x31, -1, 1, 0x2D, -0, 0, 0x29, -0, 1, 0x36, -1, 1, 0x00, -0, 0, 0x2c, -) -init_data = bytearray(init_param) - -invalid_param = ( -0,4,0x2a, -1,1,0xf0, -1,1,0xf1, -1,1,0xe0, -1,1,0xe1, -0,4,0x2b, -1,1,0xf2, -1,1,0xf3, -1,1,0xe2, -1,1,0xe3, -0,0,0x2c, -) -test_invalid = bytearray(invalid_param) -displayoff = ( -0,0,0x28, -2,0,120, -0,0,0x10, -) -test_displayoff = bytearray(displayoff) -displayon = ( -0,0,0x11, -2,0,20, -0,0,0x29, -) -test_displayon = bytearray(displayon) - -lcd.lcd_init(init_data, 240, 320, 52000, 1, 4, 0, test_invalid, test_displayon, test_displayoff, None) -``` - -### LVGL初始化 - -```python -import lvgl as lv - -lv.init() -``` - -### 注册显示驱动程序 - -```python -LCD_SIZE_W = 240 -LCD_SIZE_H = 320 - -disp_buf1 = lv.disp_draw_buf_t() -buf1_1 = bytearray(LCD_SIZE_W * LCD_SIZE_H * 2) -disp_buf1.init(buf1_1, None, len(buf1_1)) -disp_drv = lv.disp_drv_t() -disp_drv.init() -disp_drv.draw_buf = disp_buf1 -disp_drv.flush_cb = lcd.lcd_write -disp_drv.hor_res = LCD_SIZE_W -disp_drv.ver_res = LCD_SIZE_H -disp_drv.register() -``` - -### 开启lvgl线程 - -按如下代码设置LVGL的心跳以及开启LVGL线程。 - -```python -lv.tick_inc(5) -lv.task_handler() -``` - -至此,我们完成了初始化部分,可以进行GUI界面主体代码的编写了。 - -### 创建界面对象 - -按照前面章节的描述,通过如下语句创建一个没有父类的LVGL基本对象(即界面对象)。 - -``` -screen = lv.obj() -``` - -### 创建图片对象 - -以刚刚创建的LVGL界面为父对象创建一个图片组件,并设置位置及图片源。 - -```python -# create a image object -img1 = lv.img(screen) -img1.set_pos(80, 80) -img1.set_src("U:/quectel.jpg") -``` - -### 创建标签对象 - -以刚刚创建的LVGL界面为父对象创建一个标签组件,设置文本及位置。 - -```python -# create a label object -label1 = lv.label(screen) -label1.set_text("Hello Quecpython") -label1.center() -label1.set_pos(0, 80) -``` - -### 加载界面 - -```python -lv.scr_load(screen) -``` - -## 效果验证 - -将脚本下载至模组,运行脚本,可以看到LCD屏显示界面如下图所示。 - +# LVGL-示例 + +## 概述 + +前面章节介绍了LVGL在嵌入式GUI开发上的优势,以及介绍了LVGL的工作流程和常用组件。 + +本章节将教您如何零基础快速上手使用Quecpython LVGL开发一个GUI应用程序。 + + + +## 实验环境搭建 + +### 硬件准备 + +**开发板**:LTE OPEN-EVB_V1.1和EC600U-EU_AB TE-A + +**LCD屏**:ST7789 240*320 + +### 固件下载 + +请前往[Quecpython官网下载中心](https://python.quectel.com/resource-download?cid=15)下载EC600U-EU_AB的公版固件。 + +![LVGL_demo1](../../media/multi-media/lvgl/LVGL_demo1.png) + +### 硬件连接 + +将LCD屏接好开发板的LCD接口,连接开发板的USB口,长按PWRKEY开机,如下图所示。 + +![lvgl_demo2](../../media/multi-media/lvgl/lvgl_demo2.jpg) + +### 固件烧录 + +使用QPYcom工具([下载地址](https://python.quectel.com/resource-download?cid=8)),进行固件烧录, + +![lvgl_demo3](../../media/multi-media/lvgl/lvgl_demo3.jpg) + +## 脚本编写 + +应用代码[下载链接]()。 + +### LCD初始化 + +LCD的初始化部分参见wiki:[machine LCD](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html) + +本示例使用的是分辨率240*320的ST7789屏。以下为LCD初始化部分代码: + +```python +from machine import LCD + +init_param=( +0, 0, 0x11, +2, 0, 120, +0, 0, 0x00, +0, 1, 0x36, +1, 1, 0x00, +0, 1, 0x3A, +1, 1, 0x05, +0, 1, 0x35, +1, 1, 0x00, +0, 1, 0xC7, +1, 1, 0x00, +0, 1, 0xCC, +1, 1, 0x09, +0, 5, 0xB2, +1, 1, 0x0C, +1, 1, 0x0C, +1, 1, 0x00, +1, 1, 0x33, +1, 1, 0x33, +0, 1, 0xB7, +1, 1, 0x35, +0, 1, 0xBB, +1, 1, 0x36, +0, 1, 0xC0, +1, 1, 0x2C, +0, 1, 0xC2, +1, 1, 0x01, +0, 1, 0xC3, +1, 1, 0x0D, +0, 1, 0xC4, +1, 1, 0x20, +0, 1, 0xC6, +1, 1, 0x0F, +0, 2, 0xD0, +1, 1, 0xA4, +1, 1, 0xA1, +0, 14, 0xE0, +1, 1, 0xD0, +1, 1, 0x17, +1, 1, 0x19, +1, 1, 0x04, +1, 1, 0x03, +1, 1, 0x04, +1, 1, 0x32, +1, 1, 0x41, +1, 1, 0x43, +1, 1, 0x09, +1, 1, 0x14, +1, 1, 0x12, +1, 1, 0x33, +1, 1, 0x2C, +0, 14, 0xE1, +1, 1, 0xD0, +1, 1, 0x18, +1, 1, 0x17, +1, 1, 0x04, +1, 1, 0x03, +1, 1, 0x04, +1, 1, 0x31, +1, 1, 0x46, +1, 1, 0x43, +1, 1, 0x09, +1, 1, 0x14, +1, 1, 0x13, +1, 1, 0x31, +1, 1, 0x2D, +0, 0, 0x29, +0, 1, 0x36, +1, 1, 0x00, +0, 0, 0x2c, +) +init_data = bytearray(init_param) + +invalid_param = ( +0,4,0x2a, +1,1,0xf0, +1,1,0xf1, +1,1,0xe0, +1,1,0xe1, +0,4,0x2b, +1,1,0xf2, +1,1,0xf3, +1,1,0xe2, +1,1,0xe3, +0,0,0x2c, +) +test_invalid = bytearray(invalid_param) +displayoff = ( +0,0,0x28, +2,0,120, +0,0,0x10, +) +test_displayoff = bytearray(displayoff) +displayon = ( +0,0,0x11, +2,0,20, +0,0,0x29, +) +test_displayon = bytearray(displayon) + +lcd.lcd_init(init_data, 240, 320, 52000, 1, 4, 0, test_invalid, test_displayon, test_displayoff, None) +``` + +### LVGL初始化 + +```python +import lvgl as lv + +lv.init() +``` + +### 注册显示驱动程序 + +```python +LCD_SIZE_W = 240 +LCD_SIZE_H = 320 + +disp_buf1 = lv.disp_draw_buf_t() +buf1_1 = bytearray(LCD_SIZE_W * LCD_SIZE_H * 2) +disp_buf1.init(buf1_1, None, len(buf1_1)) +disp_drv = lv.disp_drv_t() +disp_drv.init() +disp_drv.draw_buf = disp_buf1 +disp_drv.flush_cb = lcd.lcd_write +disp_drv.hor_res = LCD_SIZE_W +disp_drv.ver_res = LCD_SIZE_H +disp_drv.register() +``` + +### 开启lvgl线程 + +按如下代码设置LVGL的心跳以及开启LVGL线程。 + +```python +lv.tick_inc(5) +lv.task_handler() +``` + +至此,我们完成了初始化部分,可以进行GUI界面主体代码的编写了。 + +### 创建界面对象 + +按照前面章节的描述,通过如下语句创建一个没有父类的LVGL基本对象(即界面对象)。 + +``` +screen = lv.obj() +``` + +### 创建图片对象 + +以刚刚创建的LVGL界面为父对象创建一个图片组件,并设置位置及图片源。 + +```python +# create a image object +img1 = lv.img(screen) +img1.set_pos(80, 80) +img1.set_src("U:/quectel.jpg") +``` + +### 创建标签对象 + +以刚刚创建的LVGL界面为父对象创建一个标签组件,设置文本及位置。 + +```python +# create a label object +label1 = lv.label(screen) +label1.set_text("Hello Quecpython") +label1.center() +label1.set_pos(0, 80) +``` + +### 加载界面 + +```python +lv.scr_load(screen) +``` + +## 效果验证 + +将脚本下载至模组,运行脚本,可以看到LCD屏显示界面如下图所示。 + ![lvgl_demo4](../../media/multi-media/lvgl/lvgl_demo4.jpg) \ No newline at end of file diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl_flow.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl_flow.md index acb354b820e072f7b897829d86ac5dea534f7557..decc7539c64528ee3493a519a9dc892aa5ed3e7f 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl_flow.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl_flow.md @@ -1,191 +1,191 @@ -# LVGL-流程 - -## 概述 - -在当今嵌入式系统开发领域,图形化用户界面(GUI)的需求越发突显,Quecpython + LVGL将为您的GUI开发助力。 - -本章节从其与硬件设备的关联到界面的绘制和显示过程,为您直观呈现一个完整的LVGL工作流程。 - -## LVGL与显示设备关联 - -LVGL通过注册的LCD显示驱动对象,将绘制的图形数据刷新到LCD屏幕上。LCD作为显示设备,负责在屏幕上显示图形界面的内容。LCD显示驱动对象充当了LVGL与LCD之间的桥梁,它接收LVGL生成的图形数据,并将其有效地传输到LCD屏幕上进行显示。通过这种方式,LVGL库与LCD之间建立了紧密的联系,使开发者能够借助LVGL的功能和灵活性,轻松创建出美观、交互性强的嵌入式用户界面,并通过LCD屏幕进行实时显示和更新。 - -![lvgl_1](../../media/multi-media/lvgl/lvgl_1.png) - -## LVGL工作流程 - -### LVGL初始化 - -#### 流程描述 - -LVGL初始化流程如下: - -1. 正确初始化LCD显示屏,参照[class LCD - LCD显示屏](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html)。 -2. 初始化显示负载。 -3. 初始化显示驱动,指定刷新接口为LCD对象的写屏接口 -4. 如果有TP等输入设备,初始化TP对象。 -5. 初始化输入设备驱动。 -6. 开启LVGL线程。 - -下图为LVGL初始化流程图: - -![lvgl_2](../../media/multi-media/lvgl/LVGL_initialization_flowchart.png) - -#### 代码示例 - -以下为包含Touchpad(触摸板)的LVGL的初始化代码,该示例使用MIPI显示屏。 - -```python -import lvgl as lv -from machine import LCD, Pin -from tp import gt9xx - -# 此处MIPI初始化参数请根据具体屏幕驱动型号填写。 -init_para = (0x29,0,0) -# LCD初始化部分,详见代码下方注意事项。 -mipilcd = LCD() -mipilcd.mipi_init(initbuf=bytearray(init_para), width=480, hight=854) - -# LVGL初始化 -lv.init() -# 创建一个显示缓冲区对象 -disp_buf1 = lv.disp_draw_buf_t() -# 显示缓冲区对象大小为:width * height * 2 -buf1_1 = bytes(480 * 854 * 2) -disp_buf1.init(buf1_1, None, len(buf1_1)) - -# 创建LVGL显示驱动对象 -disp_drv = lv.disp_drv_t() -# 初始化LVGL显示驱动对象 -disp_drv.init() -# 将显示缓冲区对象赋值给驱动对象的draw_buf属性 -disp_drv.draw_buf = disp_buf1 -# 将LCD对象的刷新回调函数lcd_write赋值给驱动对象的flush_cb属性 -disp_drv.flush_cb = mipilcd.lcd_write -# 此处基于实际的屏幕宽度来设置水平分辨率 -disp_drv.hor_res = 480 -# 此处基于实际的屏幕高度来设置垂直分辨率 -disp_drv.ver_res = 854 -# 此处设置是否需要旋转 -disp_drv.sw_rotate = 1 -# 旋转角度 -disp_drv.rotated = lv.DISP_ROT._270 -# 注册LVGL显示驱动对象 -disp_drv.register() - -# Touchpad(触摸板)初始化 -tp_gt911 = gt9xx(irq=40, reset=20) -tp_gt911.activate() -tp_gt911.init() -print("gt911 init...") - -# 创建LVGL输入设备驱动对象 -indev_drv = lv.indev_drv_t() -indev_drv.init() -indev_drv.type = lv.INDEV_TYPE.POINTER -# 将Touchpad对象的读取函数read赋值给LVGL输入设备驱动对象的read_cb属性 -indev_drv.read_cb = tp_gt911.read -indev_drv.register() - -# 启动LVGL 线程 -lv.tick_inc(5) -lv.task_handler() -``` - -> **注意:** -> -> - LCD初始化部分参照[class LCD - LCD显示屏](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html)。 -> -> - LVGL需要LCD对象提供lcd_write接口来刷新屏幕。 -> - LVGL需要TP对象提供read接口来进行触摸输入。 - -### LVGL界面绘制 - -#### 流程描述 - -LVGL绘制流程如下: - -1. 创建LVGL组件对象。 -2. 如有需要自定义样式,则创建LVGL样式对象。 -3. 给LVGL组件对象添加样式对象。 -4. 如有需要自定义事件,则创建LVGL事件回调函数。 -5. 给LVGL组件绑定事件回调函数,并指定触发事件类型。 -6. 加载界面,开始GUI显示逻辑。 - -下图为LVGL绘制流程图: - -![LVGL drawing flowchart](../../media/multi-media/lvgl/LVGL_drawing_flowchart.png) - -#### 代码示例 - -以下为一段示例代码,该示例创建了一个界面,并在界面上创建了一个可以点击的按钮。 - -```python -import lvgl as lv - -#此处省略LVGL初始化流程代码 - -#----------script start---------- - -# 创建一个界面 -screen = lv.obj() - -# 创建button对象 -btn1 = lv.btn(screen) -# button设置位置 -btn1.center() -# button添加文字 -label = lv.label(btn1) -label.set_text("click") - -# 创建样式对象 -style_btn = lv.style_t() -style_btn.init() -# 设置背景颜色 -style_btn.set_bg_color(lv.palette_main(lv.PALETTE.YELLOW)) -# 设置字体颜色 -style_btn.set_text_color(lv.palette_darken(lv.PALETTE.YELLOW, 4)) - -# 给button对象添加样式 -btn1.add_style(style_btn, 0) - -# 定义事件回调函数 -def event_handler(evt): - code = evt.get_code() - if code == lv.EVENT.CLICKED: - print("Clicked event detected") - -# 给button对象添加事件,在点击时触发 -btn1.add_event_cb(event_handler, lv.EVENT.CLICKED, None) - -# 加载界面 -lv.scr_load(screen) -``` - -> **注意:** -> -> - LVGL对象创建需在LVGL线程开始之后,否则会出错。 -> - LVGL绘制流程可以与显示交织进行,或者说可以在显示过程中动态绘制并实时显示。 - -### 效果展示 - -上述实例代码运行效果如下图所示: - -![lvgl_btn_demo](../../media/multi-media/lvgl/lvgl_btn_demo.png) - -## LVGL界面显示 - -LVGL以界面(obj对象)为基本单位进行显示,开发者根据业务逻辑调用界面加载接口进行界面的切换。 - -### 屏幕刷新机制 - -LVGL采用以下几种刷新机制并存的方式进行屏幕刷新,开发者了解即可。 - -1. 自动刷新(Automatic Refresh) - -这是LVGL的默认刷新模式。在这个模式下,LVGL会自动检测对象的状态变化并刷新显示。开发者不需要手动刷新。 - -2. 部分刷新(Partial Refresh) - -当屏幕的局部区域发生变化时,默认只刷新该区域而不是全屏刷新,该机制可以提高性能。 - +# LVGL-流程 + +## 概述 + +在当今嵌入式系统开发领域,图形化用户界面(GUI)的需求越发突显,Quecpython + LVGL将为您的GUI开发助力。 + +本章节从其与硬件设备的关联到界面的绘制和显示过程,为您直观呈现一个完整的LVGL工作流程。 + +## LVGL与显示设备关联 + +LVGL通过注册的LCD显示驱动对象,将绘制的图形数据刷新到LCD屏幕上。LCD作为显示设备,负责在屏幕上显示图形界面的内容。LCD显示驱动对象充当了LVGL与LCD之间的桥梁,它接收LVGL生成的图形数据,并将其有效地传输到LCD屏幕上进行显示。通过这种方式,LVGL库与LCD之间建立了紧密的联系,使开发者能够借助LVGL的功能和灵活性,轻松创建出美观、交互性强的嵌入式用户界面,并通过LCD屏幕进行实时显示和更新。 + +![lvgl_1](../../media/multi-media/lvgl/lvgl_1.png) + +## LVGL工作流程 + +### LVGL初始化 + +#### 流程描述 + +LVGL初始化流程如下: + +1. 正确初始化LCD显示屏,参照[class LCD - LCD显示屏](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html)。 +2. 初始化显示负载。 +3. 初始化显示驱动,指定刷新接口为LCD对象的写屏接口 +4. 如果有TP等输入设备,初始化TP对象。 +5. 初始化输入设备驱动。 +6. 开启LVGL线程。 + +下图为LVGL初始化流程图: + +![lvgl_2](../../media/multi-media/lvgl/LVGL_initialization_flowchart.png) + +#### 代码示例 + +以下为包含Touchpad(触摸板)的LVGL的初始化代码,该示例使用MIPI显示屏。 + +```python +import lvgl as lv +from machine import LCD, Pin +from tp import gt9xx + +# 此处MIPI初始化参数请根据具体屏幕驱动型号填写。 +init_para = (0x29,0,0) +# LCD初始化部分,详见代码下方注意事项。 +mipilcd = LCD() +mipilcd.mipi_init(initbuf=bytearray(init_para), width=480, hight=854) + +# LVGL初始化 +lv.init() +# 创建一个显示缓冲区对象 +disp_buf1 = lv.disp_draw_buf_t() +# 显示缓冲区对象大小为:width * height * 2 +buf1_1 = bytes(480 * 854 * 2) +disp_buf1.init(buf1_1, None, len(buf1_1)) + +# 创建LVGL显示驱动对象 +disp_drv = lv.disp_drv_t() +# 初始化LVGL显示驱动对象 +disp_drv.init() +# 将显示缓冲区对象赋值给驱动对象的draw_buf属性 +disp_drv.draw_buf = disp_buf1 +# 将LCD对象的刷新回调函数lcd_write赋值给驱动对象的flush_cb属性 +disp_drv.flush_cb = mipilcd.lcd_write +# 此处基于实际的屏幕宽度来设置水平分辨率 +disp_drv.hor_res = 480 +# 此处基于实际的屏幕高度来设置垂直分辨率 +disp_drv.ver_res = 854 +# 此处设置是否需要旋转 +disp_drv.sw_rotate = 1 +# 旋转角度 +disp_drv.rotated = lv.DISP_ROT._270 +# 注册LVGL显示驱动对象 +disp_drv.register() + +# Touchpad(触摸板)初始化 +tp_gt911 = gt9xx(irq=40, reset=20) +tp_gt911.activate() +tp_gt911.init() +print("gt911 init...") + +# 创建LVGL输入设备驱动对象 +indev_drv = lv.indev_drv_t() +indev_drv.init() +indev_drv.type = lv.INDEV_TYPE.POINTER +# 将Touchpad对象的读取函数read赋值给LVGL输入设备驱动对象的read_cb属性 +indev_drv.read_cb = tp_gt911.read +indev_drv.register() + +# 启动LVGL 线程 +lv.tick_inc(5) +lv.task_handler() +``` + +> **注意:** +> +> - LCD初始化部分参照[class LCD - LCD显示屏](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html)。 +> +> - LVGL需要LCD对象提供lcd_write接口来刷新屏幕。 +> - LVGL需要TP对象提供read接口来进行触摸输入。 + +### LVGL界面绘制 + +#### 流程描述 + +LVGL绘制流程如下: + +1. 创建LVGL组件对象。 +2. 如有需要自定义样式,则创建LVGL样式对象。 +3. 给LVGL组件对象添加样式对象。 +4. 如有需要自定义事件,则创建LVGL事件回调函数。 +5. 给LVGL组件绑定事件回调函数,并指定触发事件类型。 +6. 加载界面,开始GUI显示逻辑。 + +下图为LVGL绘制流程图: + +![LVGL drawing flowchart](../../media/multi-media/lvgl/LVGL_drawing_flowchart.png) + +#### 代码示例 + +以下为一段示例代码,该示例创建了一个界面,并在界面上创建了一个可以点击的按钮。 + +```python +import lvgl as lv + +#此处省略LVGL初始化流程代码 + +#----------script start---------- + +# 创建一个界面 +screen = lv.obj() + +# 创建button对象 +btn1 = lv.btn(screen) +# button设置位置 +btn1.center() +# button添加文字 +label = lv.label(btn1) +label.set_text("click") + +# 创建样式对象 +style_btn = lv.style_t() +style_btn.init() +# 设置背景颜色 +style_btn.set_bg_color(lv.palette_main(lv.PALETTE.YELLOW)) +# 设置字体颜色 +style_btn.set_text_color(lv.palette_darken(lv.PALETTE.YELLOW, 4)) + +# 给button对象添加样式 +btn1.add_style(style_btn, 0) + +# 定义事件回调函数 +def event_handler(evt): + code = evt.get_code() + if code == lv.EVENT.CLICKED: + print("Clicked event detected") + +# 给button对象添加事件,在点击时触发 +btn1.add_event_cb(event_handler, lv.EVENT.CLICKED, None) + +# 加载界面 +lv.scr_load(screen) +``` + +> **注意:** +> +> - LVGL对象创建需在LVGL线程开始之后,否则会出错。 +> - LVGL绘制流程可以与显示交织进行,或者说可以在显示过程中动态绘制并实时显示。 + +### 效果展示 + +上述实例代码运行效果如下图所示: + +![lvgl_btn_demo](../../media/multi-media/lvgl/lvgl_btn_demo.png) + +## LVGL界面显示 + +LVGL以界面(obj对象)为基本单位进行显示,开发者根据业务逻辑调用界面加载接口进行界面的切换。 + +### 屏幕刷新机制 + +LVGL采用以下几种刷新机制并存的方式进行屏幕刷新,开发者了解即可。 + +1. 自动刷新(Automatic Refresh) + +这是LVGL的默认刷新模式。在这个模式下,LVGL会自动检测对象的状态变化并刷新显示。开发者不需要手动刷新。 + +2. 部分刷新(Partial Refresh) + +当屏幕的局部区域发生变化时,默认只刷新该区域而不是全屏刷新,该机制可以提高性能。 + diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl_fontlib.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl_fontlib.md index 82ca0d5365fcde8d503575487064ff91ba76fbd4..c7cccd63193897cd9011933df0c49b4e40caf42f 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl_fontlib.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl_fontlib.md @@ -1,308 +1,323 @@ -# LVGL-字体库 - -## 概述 - -在 LVGL 中,`字体`是渲染字母(字形)图像所需的位图和其他信息的集合。 - -`字体`具有bpp(像素深度)属性。它显示了使用多少位来描述字体中的像素。为像素存储的值决定了像素的不透明度。 这样,使用更高的 bpp,字母的边缘可以更平滑。可能的 bpp值为 1、2、4 和 8(值越高表示质量越好)。 - -bpp还会影响存储字体所需的内存大小。例如,bpp = 4的字体所占用的内存比 bpp = 1的字体所占用的内存大近4倍。 - -## 字体分类 - -因LVGL字体的实质是字形图像的位图,所以不以字体语种作为分类依据。 - -`Quecpython LVGL字体`可分为: - -1. **内置字体**(built-in fonts) -2. **外置字体**(external fonts) - -> 注意:目前仅EC600M系列,EC600N系列,EC800M系列,EG810M系列支持外置字体。 - -## 内置字体(built-in fonts) - -### 概述 - -顾名思义,内置字体就是已经编辑集成进固件中的LVGL字体,可直接在应用代码中通过接口`style_obj.set_text_font(lv.font_name)`或`obj.set_style_text_font(lv.font_name,0)`使用。 - -### 默认字体 - -Quecpython LVGL默认集成了`MONTSERRAT 14`号字体,包含全部英文字符和部分常见英文符号。 - -默认字体可以通过`lv.font_default()`接口获取,或者直接使用`lv.font_montserrat_14`。 - -### 添加新字体 - -默认字体往往无法满足项目需求,如果您是使用pythonSDK开发,可以按以下方法将新字体编译到固件中。 - -#### 基于Lvgl 官网字体转换工具添加 - -此种方式添加新的内置字体较为简单,缺点是在bpp较小的时候,最后字体的显示质量较差。 - -##### 工具 - -[Lvgl 官网字体转换工具](https://lvgl.io/tools/fontconverter) - -##### 字体C文件生成 - -![lvgl_font1](../../media/multi-media/lvgl/lvgl_font1.png) - -1. 输入要生成的字体名称(最后会生成同名的 C 文件); -2. 输入要转换的字体大小; -3. 选择锯齿平滑度; -4. 选择本地 TTF 或者 WOFF 格式的字体文件,(请确保该字体为免费商用), 即你要转换成的目标字体; -5. 输入字库需要包含的文字,如需空格,符号,数字,字母也需一并输入; -6. 完成上述五步必须操作,点击 convert 进行在线转换,字体会自动下载到本地。 -7. 将生成的C文件复制到你的 LVGL 工程目录:`pythonSDK\services\microPython\lib\lvgl\lvgl\src\font`文件夹下。 - -您可以照上述步骤添加多个你需要的字体C文件到font目录。 - -##### 修改字体C文件 - -为了和其它字库文件统一,对生成的C文件做出以下修改,如果想使用宏控,则添加您项目对应的宏控,如本教程的`#if LV_FONT_UI_DEMO`。 - -![lvgl_font2](../../media/multi-media/lvgl/lvgl_font2.jpg) - -#### 基于LvglFontTool 工具添加 - -此种方式添加新的内置字体较为复杂,优点是在bpp较小的时候,最后字体的显示质量较好。 - -##### 工具 - -[LvglFontTool工具V0.4](http://www.armbbs.cn/forum.php?mod=viewthread&tid=99387) - -> 注意:此工具目前只有中文版本,海外客户可照下面图示及文字描述的步骤操作。 - -##### 字体C文件生成 - -打开工具,在选择字体的时候,有两种选项,第一种可以勾选”使用FreeType TTF“并选择TTF字体文件来制作字体,第二种不勾选”使用FreeType TTF“也可以选择pc上自带的字体来制作字体,步骤如下: - -![lvgl_font8](../../media/multi-media/lvgl/lvgl_font8.jpg) - -![lvgl_font9](../../media/multi-media/lvgl/lvgl_font9.jpg) - -![lvgl_font10](../../media/multi-media/lvgl/lvgl_font10.jpg) - -1. 勾选使用”使用FreeType TTF“(或不勾选); -2. 选择TTF字体文件(或选择电脑自带字体); -3. 设置字体大小,点击确定; -4. 输入字库需要包含的文字,如需空格,符号,数字,字母也需一并输入; -5. 选择6.0版本以上; -6. 选择内部字体; -7. 输入字体名字; -8. 完成上述必须操作,点击开始转换,选择保存路径即可; -9. 打开文件保存目录,将siyuan_light_12.c 复制到你的 LVGL 工程目录: - `pythonSDK\services\microPython\lib\lvgl\lvgl\src\font`文件夹下。 - -您可以照上述步骤添加多个你需要的字体C文件到font目录。 - -##### 修改字体C文件 - -为了和其它字库文件统一,对生成的C文件做出以下修改。 - -![lvgl_font11](../../media/multi-media/lvgl/lvgl_font11.jpg) - -![lvgl_font12](../../media/multi-media/lvgl/lvgl_font12.jpg) - -![image-20230803151622262](../../media/multi-media/lvgl/lvgl_font13.jpg) - -至此,字体C文件修改完成。 - -#### 参与编译 - -按上述步骤完成字体C文件的添加后,还需要按如下操作修改文件,使添加的字体C文件能参与编译。 - -- 在`pythonSDK\services\microPython\lib\lvgl\lvgl\src\font\lv_font.mk`中加入添加的字体文件。 - -![lvgl_font3](../../media/multi-media/lvgl/lvgl_font3.jpg) - -- 在`pythonSDK\services\microPython\microPython.mk`中加入添加的字体文件 - -![lvgl_font4](../../media/multi-media/lvgl/lvgl_font4.jpg) - -- 在`pythonSDK\services\microPython\lib\lvgl\lvgl\src\font\lv_font.h`中声明添加的字体 - -![lvgl_font5](../../media/multi-media/lvgl/lvgl_font5.jpg) - -- 在Quecpython中添加该字体的使用。 - -![lvgl_font6](../../media/multi-media/lvgl/lvgl_font6.jpg) - -![lvgl_font7](../../media/multi-media/lvgl/lvgl_font7.jpg) - -至此修改结束,编译固件并烧录到模块,就可以使用添加的内部字体库了。 - -## 外置字体(external fonts) - -### 概述 - -默认字体往往无法满足项目需求,如果您并未使用pythonSDK开发,您可以选择使用LVGL外置字体。 - -外置字体是将需要的字体制作成二进制bin文件,用指定方式合入固件中使用。 - -> 注意:目前仅EC600M系列,EC600N系列,EC800M系列,EG810M系列支持外置字体。 - -### 添加新字体 - -#### ext_font.bin文件生成 - -##### 工具 - -bin文件生成工具: [LvglFontTool工具V0.4](http://www.armbbs.cn/forum.php?mod=viewthread&tid=99387) - -bin文件合成工具: font_bin_merge.py - -```python -# font_bin_merge.py -from struct import * - -def bin_create(*args): - if len(args) < 1: - print("wrong params number!") - return -1 - - with open("ext_font.bin","wb") as dest_file: - # start - start = "s" - end = "e" - - font_num = len(args) - bin_data = [] - bin_size = [] - font_name = "" - - for i in range(font_num): - with open(args[i], "rb") as bin_file: - data = bin_file.read() - padding = "\0" * (128 - len(args[i])) - string_padded = args[i] + padding - font_name += string_padded - bin_size.append(len(data)) - bin_data.append(data) - - write_data = pack(" 注意:此工具目前只有中文版本,海外客户可照下面图示及文字描述的步骤操作。 -> -> 最终使用的二进制bin文件可能包含多个字体,所以需要先使用bin文件生成工具生成单个bin文件,再使用bin文件合成工具合成最终使用的二进制bin文件:ext_font.bin。 - -##### 单个bin文件生成 - -使用LvglFontTool转换字体工具进行文件生成。 - -![lvgl_font14](../../media/multi-media/lvgl/lvgl_font14.jpg) - -1. 选择您要转换的字体文件,并输入要使用的字体大小(就是汉字在显示器上占用像素的高度),点击确定。 -2. 在左上角的方框中输入需要添加的字体库文字,下方的按钮可以作为辅助。 -3. 选择锯齿平滑度,抗锯齿高占用空间大,需权衡。 -4. 版本选择,选择用于6.0版本以上。 -5. 选择保存类型:XBF字体,外部bin文件。 -6. 输入要保存的字体库名称。 -7. 点击开始转换,选择要保存文件的目录点击确定即可完成转换。该目录会生成bin文件和c文件。 - -操作的时候注意以下几点: - -- 制作字体生成的C文件中,找到该字体的line_height,纪录它,后面使用接口的时候需要传参! line_height也可在生成工具的右上侧代码中找到: - -![lvgl_font15](../../media/multi-media/lvgl/lvgl_font15.jpg) - -- 抗锯齿可以增加字体的圆润度,相应的会增加bin文件的大小 - -- 如果勾选了使用FreeType TTF选项,需要提前准备好一个字体TTF文件,或者可以取消勾选该选项,则可以从本机字体种选取字体进行bin文件制作。 - -- 尤其注意的是,**bin文件的大小,取决于包含的字符在unicode中的index的跨度!** - -##### 字体bin文件合成 - -通过上述步骤,我们创建了单独字体的bin文件,我们需要将它们合成LVGL外部字体库接口可以使用的ext_font.bin文件。 - -> 注意:若只有一个bin文件,也需要执行这一步。 - -打开font_bin_merge.py脚本,将main中的bin_create()的参数改成您需要合并的bin文件的路径即可,有几个bin文件就传几个参数。 - -![lvgl_font16](../../media/multi-media/lvgl/lvgl_font16.jpg) - -执行修改好的font_bin_merge.py脚本,即可在同目录下生成最终需要的bin文件:ext_font.bin。 - -> 注意:请先确保您正确安装了python。 - -#### flash分区调整 - -制作好ext_font.bin后,需要按以下操作将文件合入固件中。 - -#### 修改分区配置文件 - -将固件包中的 xxx_release_pack.zip 拷贝到 release_tool 目录下, 即和 release.exe 同级目录。 -将 xxx_release_pack.zip 解压到当前路径。 会解压出 2 个目录 config 和 images, config 存放分区配置文件, -images 存放烧录时用到的各种 bin 文件。 - -这里以 EC600NCN_LF 系列新增字库分区为例。 具体如下: -1、 config\template\目录下的 CRANE_EVB.json 文件, 需要增加新增分区的信息。 涉及 2 处如下图: - -![lvgl_font17](../../media/multi-media/lvgl/lvgl_font17.jpg) - -![lvgl_font18](../../media/multi-media/lvgl/lvgl_font18.jpg) - -2、 config\partition\目录下的 CRANE_SINGLE_FLASH_LAYOUT_LTEONLY.json 文件, 用来修改分区大小。 -需要增加新增分区的信息, 这里新增字库分区 ext_font 的大小为 1536KB, 根据实际需要决定该分区大小。 -同时由于总的分区空间不变, 所以需要减少另一个分区 customer_app 空间大小, 从 3116KB 减到 1580KB, -同理该分区大小也要根据实际情况调整, 最小不能小于 image\customer_app.bin 文件的实际大小。 如下图: - -![lvgl_font19](../../media/multi-media/lvgl/lvgl_font19.jpg) - -> **注意:** -> -> - 对于 EC600N 系列, 新增的 ext_font 分区空间来源于 customer_app 分区剩余空间+reserved 分区剩余 -> 空间, ext_font 分区的大小不能超过这 2 个之和, reserved 分区是预留的空间, 会自动调整, 不需要专门调整。 即这里 ext_font 分区的大小可以大于或等于 customer_app 分区减小的大小。 -> - 对于 EC600M 系列, 新增的 ext_font 分区空间只能来源于 customer_app 分区剩余空间, 而且 ext_font分区的大小必须等于 customer_app 分区减去的大小, 否则会导致 APP 启动失败。 - -#### ext_font.bin文件放置 - -将ext_font.bin文件copy 到 images\目录下。 - -#### 新固件生成 - -将修改内容后的 config 和 image 目录重新压缩成 xxx_release_pack.zip(注意不要多加一层文件夹, 需要 -xxx_release_pack.zip 点击进去直接是 config 和 image 目录), 然后点击运行 release.exe 即可生成包含字 -库文件 ext_font.bin 的新固件。 - -如果生成固件失败, 基本是因为超过了空间的总大小。 请检查 ext_font 分区大小是否超过了 customer_app -分区剩余的空间大小(对于 EC600N 再加上 reserved 分区剩余的空间大小) 。 如果超了, 只能通过减小字 -库文件 ext_font.bin 的大小来解决。 - -#### 外置字体使用接口 - -按照上文内容,生成了包含ext_font.bin的固件包之后,烧录固件包。 - -#### 接口说明 - -Lvgl外部字体库接口: - -`lvgl.style_t().set_text_font_v2(font_name,line_height, flash_port)` - -参数说明: - -- `font_name`: 字体名称,系合成ext_font.bin文件的bin文件名称; -- `line_height`: 字形高度,可在工具生成的C文件中找到; -- `flash_port`: 内部flash填0即可;外部flash根据连接的spi port填写。 - -> **注意:** -> -> - 这里的font_name是您要使用的字体的原始bin文件名字,不是"ext_font.bin"。比如您制作了font_12.bin和font_14.bin,将它们合成了ext_font.bin,则font_name参数需填”font_12.bin”或”font_14.bin”。 -> - Line_height不要填错,否则可能字体显示不全或显示过高。 \ No newline at end of file +# LVGL-字体库 + +## 概述 + +在 LVGL 中,`字体`是渲染字母(字形)图像所需的位图和其他信息的集合。 + +`字体`具有bpp(像素深度)属性。它显示了使用多少位来描述字体中的像素。为像素存储的值决定了像素的不透明度。 这样,使用更高的 bpp,字母的边缘可以更平滑。可能的 bpp值为 1、2、4 和 8(值越高表示质量越好)。 + +bpp还会影响存储字体所需的内存大小。例如,bpp = 4的字体所占用的内存比 bpp = 1的字体所占用的内存大近4倍。 + +## 字体分类 + +因LVGL字体的实质是字形图像的位图,所以不以字体语种作为分类依据。 + +`Quecpython LVGL字体`可分为: + +1. **内置字体**(built-in fonts) +2. **外置字体**(external fonts) + +> 注意:目前仅EC600M系列,EC600N系列,EC800M系列,EG810M系列支持外置字体。 + +## 内置字体(built-in fonts) + +### 概述 + +顾名思义,内置字体就是已经编辑集成进固件中的LVGL字体,可直接在应用代码中通过接口`style_obj.set_text_font(lv.font_name)`或`obj.set_style_text_font(lv.font_name,0)`使用。 + +### 默认字体 + +Quecpython LVGL默认集成了`MONTSERRAT 14`号字体,包含全部英文字符和部分常见英文符号。 + +默认字体可以通过`lv.font_default()`接口获取,或者直接使用`lv.font_montserrat_14`。 + +### 添加新字体 + +默认字体往往无法满足项目需求,如果您是使用pythonSDK开发,可以按以下方法将新字体编译到固件中。 + +#### 基于Lvgl 官网字体转换工具添加 + +此种方式添加新的内置字体较为简单,缺点是在bpp较小的时候,最后字体的显示质量较差。 + +##### 工具 + +[Lvgl 官网字体转换工具](https://lvgl.io/tools/fontconverter) + +##### 字体C文件生成 + +![lvgl_font1](../../media/multi-media/lvgl/lvgl_font1.png) + +1. 输入要生成的字体名称(最后会生成同名的 C 文件); +2. 输入要转换的字体大小; +3. 选择锯齿平滑度; +4. 选择本地 TTF 或者 WOFF 格式的字体文件,(请确保该字体为免费商用), 即你要转换成的目标字体; +5. 输入字库需要包含的文字,如需空格,符号,数字,字母也需一并输入; +6. 完成上述五步必须操作,点击 convert 进行在线转换,字体会自动下载到本地。 +7. 将生成的C文件复制到你的 LVGL 工程目录:`pythonSDK\services\microPython\lib\lvgl\lvgl\src\font`文件夹下。 + +您可以照上述步骤添加多个你需要的字体C文件到font目录。 + +##### 修改字体C文件 + +为了和其它字库文件统一,对生成的C文件做出以下修改,如果想使用宏控,则添加您项目对应的宏控,如本教程的`#if LV_FONT_UI_DEMO`。 + +![lvgl_font2](../../media/multi-media/lvgl/lvgl_font2.jpg) + +#### 基于LvglFontTool 工具添加 + +此种方式添加新的内置字体较为复杂,优点是在bpp较小的时候,最后字体的显示质量较好。 + +##### 工具 + +[LvglFontTool工具V0.4](http://www.armbbs.cn/forum.php?mod=viewthread&tid=99387) + +> 注意:此工具目前只有中文版本,海外客户可照下面图示及文字描述的步骤操作。 + +##### 字体C文件生成 + +打开工具,在选择字体的时候,有两种选项,第一种可以勾选”使用FreeType TTF“并选择TTF字体文件来制作字体,第二种不勾选”使用FreeType TTF“也可以选择pc上自带的字体来制作字体,步骤如下: + +![lvgl_font8](../../media/multi-media/lvgl/lvgl_font8.jpg) + +![lvgl_font9](../../media/multi-media/lvgl/lvgl_font9.jpg) + +![lvgl_font10](../../media/multi-media/lvgl/lvgl_font10.jpg) + +1. 勾选使用”使用FreeType TTF“(或不勾选); +2. 选择TTF字体文件(或选择电脑自带字体); +3. 设置字体大小,点击确定; +4. 输入字库需要包含的文字,如需空格,符号,数字,字母也需一并输入; +5. 选择6.0版本以上; +6. 选择内部字体; +7. 输入字体名字; +8. 完成上述必须操作,点击开始转换,选择保存路径即可; +9. 打开文件保存目录,将siyuan_light_12.c 复制到你的 LVGL 工程目录: + `pythonSDK\services\microPython\lib\lvgl\lvgl\src\font`文件夹下。 + +您可以照上述步骤添加多个你需要的字体C文件到font目录。 + +##### 修改字体C文件 + +为了和其它字库文件统一,对生成的C文件做出以下修改。 + +![lvgl_font11](../../media/multi-media/lvgl/lvgl_font11.jpg) + +![lvgl_font12](../../media/multi-media/lvgl/lvgl_font12.jpg) + +![image-20230803151622262](../../media/multi-media/lvgl/lvgl_font13.jpg) + +至此,字体C文件修改完成。 + +#### 参与编译 + +按上述步骤完成字体C文件的添加后,还需要按如下操作修改文件,使添加的字体C文件能参与编译。 + +- 在`pythonSDK\services\microPython\lib\lvgl\lvgl\src\font\lv_font.mk`中加入添加的字体文件。 + +![lvgl_font3](../../media/multi-media/lvgl/lvgl_font3.jpg) + +- 在`pythonSDK\services\microPython\microPython.mk`中加入添加的字体文件 + +![lvgl_font4](../../media/multi-media/lvgl/lvgl_font4.jpg) + +- 在`pythonSDK\services\microPython\lib\lvgl\lvgl\src\font\lv_font.h`中声明添加的字体 + +![lvgl_font5](../../media/multi-media/lvgl/lvgl_font5.jpg) + +- 在Quecpython中添加该字体的使用。 + +![lvgl_font6](../../media/multi-media/lvgl/lvgl_font6.jpg) + +![lvgl_font7](../../media/multi-media/lvgl/lvgl_font7.jpg) + +至此修改结束,编译固件并烧录到模块,就可以使用添加的内部字体库了。 + +## 外置字体(external fonts) + +### 概述 + +默认字体往往无法满足项目需求,如果您并未使用pythonSDK开发,您可以选择使用LVGL外置字体。 + +外置字体是将需要的字体制作成二进制bin文件,用指定方式合入固件中使用。 + +> 注意:目前仅EC600M系列,EC600N系列,EC800M系列,EG810M系列支持外置字体。 + +### 添加新字体 + +#### ext_font.bin文件生成 + +##### 工具 + +bin文件生成工具: [LvglFontTool工具V0.4](http://www.armbbs.cn/forum.php?mod=viewthread&tid=99387) + +bin文件合成工具: font_bin_merge.py + +```python +# font_bin_merge.py +from struct import * + +def bin_create(*args): + if len(args) < 1: + print("wrong params number!") + return -1 + + with open("ext_font.bin","wb") as dest_file: + # start + start = "s" + end = "e" + + font_num = len(args) + bin_data = [] + bin_size = [] + font_name = "" + + for i in range(font_num): + with open(args[i], "rb") as bin_file: + data = bin_file.read() + padding = "\0" * (128 - len(args[i])) + string_padded = args[i] + padding + font_name += string_padded + bin_size.append(len(data)) + bin_data.append(data) + + write_data = pack(" 注意:此工具目前只有中文版本,海外客户可照下面图示及文字描述的步骤操作。 +> +> 最终使用的二进制bin文件可能包含多个字体,所以需要先使用bin文件生成工具生成单个bin文件,再使用bin文件合成工具合成最终使用的二进制bin文件:ext_font.bin。 + +##### 单个bin文件生成 + +使用LvglFontTool转换字体工具进行文件生成。 + +![lvgl_font14](../../media/multi-media/lvgl/lvgl_font14.jpg) + +1. 选择您要转换的字体文件,并输入要使用的字体大小(就是汉字在显示器上占用像素的高度),点击确定。 +2. 在左上角的方框中输入需要添加的字体库文字,下方的按钮可以作为辅助。 +3. 选择锯齿平滑度,抗锯齿高占用空间大,需权衡。 +4. 版本选择,选择用于6.0版本以上。 +5. 选择保存类型:XBF字体,外部bin文件。 +6. 输入要保存的字体库名称。 +7. 点击开始转换,选择要保存文件的目录点击确定即可完成转换。该目录会生成bin文件和c文件。 + +操作的时候注意以下几点: + +- 制作字体生成的C文件中,找到该字体的line_height,纪录它,后面使用接口的时候需要传参! line_height也可在生成工具的右上侧代码中找到: + +![lvgl_font15](../../media/multi-media/lvgl/lvgl_font15.jpg) + +- 抗锯齿可以增加字体的圆润度,相应的会增加bin文件的大小 + +- 如果勾选了使用FreeType TTF选项,需要提前准备好一个字体TTF文件,或者可以取消勾选该选项,则可以从本机字体种选取字体进行bin文件制作。 + +- 尤其注意的是,**bin文件的大小,取决于包含的字符在unicode中的index的跨度!** + +##### 字体bin文件合成 + +通过上述步骤,我们创建了单独字体的bin文件,我们需要将它们合成LVGL外部字体库接口可以使用的ext_font.bin文件。 + +> 注意:若只有一个bin文件,也需要执行这一步。 + +打开font_bin_merge.py脚本,将main中的bin_create()的参数改成您需要合并的bin文件的路径即可,有几个bin文件就传几个参数。 + +![lvgl_font16](../../media/multi-media/lvgl/lvgl_font16.jpg) + +执行修改好的font_bin_merge.py脚本,即可在同目录下生成最终需要的bin文件:ext_font.bin。 + +> 注意:请先确保您正确安装了python。 + +#### flash分区调整 + +制作好ext_font.bin后,需要按以下两种操作方法(任选其一)将文件合入固件中。 + +##### 方案一:修改分区配置文件 + +将固件包中的 xxx_release_pack.zip 拷贝到 release_tool 目录下, 即和 release.exe 同级目录。 +将 xxx_release_pack.zip 解压到当前路径。 会解压出 2 个目录 config 和 images, config 存放分区配置文件, +images 存放烧录时用到的各种 bin 文件。 + +这里以 EC600NCN_LF 系列新增字库分区为例。 具体如下: +1、 config\template\目录下的 CRANE_EVB.json 文件, 需要增加新增分区的信息。 涉及 2 处如下图: + +![lvgl_font17](../../media/multi-media/lvgl/lvgl_font17.jpg) + +![lvgl_font18](../../media/multi-media/lvgl/lvgl_font18.jpg) + +2、 config\partition\目录下的 CRANE_SINGLE_FLASH_LAYOUT_LTEONLY.json 文件, 用来修改分区大小。 +需要增加新增分区的信息, 这里新增字库分区 ext_font 的大小为 1536KB, 根据实际需要决定该分区大小。 +同时由于总的分区空间不变, 所以需要减少另一个分区 customer_app 空间大小, 从 3116KB 减到 1580KB, +同理该分区大小也要根据实际情况调整, 最小不能小于 image\customer_app.bin 文件的实际大小。 如下图: + +![lvgl_font19](../../media/multi-media/lvgl/lvgl_font19.jpg) + +> **注意:** +> +> - 对于 EC600N 系列, 新增的 ext_font 分区空间来源于 customer_app 分区剩余空间+reserved 分区剩余 +> 空间, ext_font 分区的大小不能超过这 2 个之和, reserved 分区是预留的空间, 会自动调整, 不需要专门调整。 即这里 ext_font 分区的大小可以大于或等于 customer_app 分区减小的大小。 +> - 对于 EC600M 系列, 新增的 ext_font 分区空间只能来源于 customer_app 分区剩余空间, 而且 ext_font分区的大小必须等于 customer_app 分区减去的大小, 否则会导致 APP 启动失败。 + +3、 ext_font.bin文件放置 + +将ext_font.bin文件copy 到 images\目录下。 + +4、 新固件生成 + +将修改内容后的 config 和 image 目录重新压缩成 xxx_release_pack.zip(注意不要多加一层文件夹, 需要 +xxx_release_pack.zip 点击进去直接是 config 和 image 目录), 然后点击运行 release.exe 即可生成包含字 +库文件 ext_font.bin 的新固件。 + +如果生成固件失败, 基本是因为超过了空间的总大小。 请检查 ext_font 分区大小是否超过了 customer_app +分区剩余的空间大小(对于 EC600N 再加上 reserved 分区剩余的空间大小) 。 如果超了, 只能通过减小字 +库文件 ext_font.bin 的大小来解决。 + +##### 方案二:QPYcom工具生成 + +1、 准备ext_font.bin和完整的固件包 + +2、打开QPYcom,工具箱->分区管理->ASR + +![lvgl_font20](../../media/multi-media/lvgl/lvgl_font20.jpg) + +3、按照下图操作,便会生成新的固件。 + +![lvgl_font21](../../media/multi-media/lvgl/lvgl_font21.jpg) + + + +#### 外置字体使用接口 + +按照上文内容,生成了包含ext_font.bin的固件包之后,烧录固件包。 + +#### 接口说明 + +Lvgl外部字体库接口: + +`lvgl.style_t().set_text_font_v2(font_name,line_height, flash_port)` + +参数说明: + +- `font_name`: 字体名称,系合成ext_font.bin文件的bin文件名称; +- `line_height`: 字形高度,可在工具生成的C文件中找到; +- `flash_port`: 内部flash填0即可;外部flash根据连接的spi port填写。 + +> **注意:** +> +> - 这里的font_name是您要使用的字体的原始bin文件名字,不是"ext_font.bin"。比如您制作了font_12.bin和font_14.bin,将它们合成了ext_font.bin,则font_name参数需填”font_12.bin”或”font_14.bin”。 +> - Line_height不要填错,否则可能字体显示不全或显示过高。 + diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl_notes.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl_notes.md index b531ff377ff9c8dc2ac9c4dac07e5d41481b78c4..349f8cce82ae704615e680a9b861b11fd40a47c8 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl_notes.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl_notes.md @@ -1,143 +1,143 @@ -# LVGL-注意事项 - -## 概述 - -在实际使用Quecpython LVGL的开发过程中,客户可能会遇到很多问题,本章总结一些开发者遇到的常见问题。 - -## 图片的选择与使用 - -> **注意:**图片解码消耗RAM资源! - -项目GUI不可避免要用到图片,Quecpython LVGL提供了三种图片格式的支持,分别是PNG,JPG和SJPG。 - -## 图片格式的优缺点 - -### PNG - -优点 - -- 无损格式,图片质量较好 - -- 支持透明 - -缺点 - -- 解码需要RAM资源大(图像宽度 x 图像高度 x 4字节) -- 解码时间较长(图片放四线外挂flash) - -### JPG - -优点 - -- 较节省资源(解码需RAM:图像宽度 x 图像高度 x 3字节) -- 图片质量较好 - -缺点 - -- 不支持透明 -- 优点同时也是缺点,画质比PNG差,解码消耗资源也较大 - -### SJPG - -SJPG 是LVGL自定义的一种基于普通” JPG 的格式,全称split-jpeg ,它是一段带有 sjpg 标头的小 jpeg 片段数据,它的大小将几乎与 jpg 文件相当,或者可能会稍大一些。 - -优点 - -- 节省资源(解码不需申请较大RAM空间) - -缺点 - -- 不支持透明 -- 画质较差 -- 若图片放四线外挂flash,则加载慢 -- 不适用图片缓存机制 - -## 图片格式的选择 - -首先看透明度需求,有透明度需求的直接选择PNG格式。 - -其次得分以下两种情况说明。 - -### 图片放内置flash或外挂六线flash - -这种情况下,flash访问速度快,解码速度差距不大,对于客户而言,UI加载三种格式图片的速度差距不大。 - -请根据对画质的需求和资源分配权衡选择。 - -一般而言,若画质需求不强烈,可以选择SJPG,其次选择JPG,最后PNG; - -若模块RAM资源富余,可以选择PNG,其次JPG,最后SJPG。 - -需要根据项目实际情况找到一个平衡点。 - -### 图片放外挂四线flash - -外挂四线flash访问速度慢,UI图片较多的时候,对于客户而言,卡顿感知明显。 - -这种情况下,需要打开图片缓存机制,选择JPG或PNG格式,不能选择SJPG! - -## 图片缓存机制 - -上文说到,外挂四线flash文件系统读取速度比较慢,LVGL图片解码也比较耗时,导致GUI显示卡顿。需要使用LVGL的图片缓存机制来解决。 - -### 使用方法 - -使用JPG或者PNG格式图片,在切换界面之前执行以下两步: - -```python -lv.img.cache_invalidate_src(None) -lv.img.cache_set_size(cache_num) -``` - -`cache_num` - 需要缓存的图片数目,最大16。 - -> **注意:** -> -> - SJPG与图片缓存机制不兼容!因为SJPG的实质是很多块小图片。 -> - imgbtn组件不能使用图片缓存机制,不要使用imgbtn组件! -> - 缓存的图片会占据RAM。 - -## LVGL休眠场景 - -首先,在需要进入休眠模式的时候,务必确认外设是否停止交互,USB是否已断开,线程是否都已阻塞或挂起,否则无法进入休眠模式。 - -在确保上述条件满足的情况下,模块一般采取以下流程进休眠,其中背光关闭请根据硬件设计来对应的关闭。 - -```python -import pm -import lvgl as lv - -# Allow module to enter low-power mode in idle state -pm.autosleep(1) -# Allow LVGL to enter low-power mode in idle state -lv.autoSleep(1) -# LCD enters sleep state -lcd.lcd_display_off() -# Touchpad enters sleep state if exists -tp.suspend() -# Close LCD backlight if it can be controlled -``` - -退出休眠的时候执行相反的操作,如下。 - -```python -import pm -import lvgl as lv - -# Module exits from low-power mode -pm.autosleep(0) -# LVGL exits from low-power mode -lv.autoSleep(0) -# Wake LCD up -lcd.lcd_display_on() -# Wake touchpad up -tp.resume() -# Open lcd backlight if it can be controlled -``` - -## 其他注意事项 - -- 避免组件或者样式被gc回收,请将其定义为全局变量。 -- 切换界面之前不要执行太多耗时操作,否则可能造成切换页面卡顿。 -- 因LVGL底层限制,不要给一个组件多次的添加样式(add_style),超过64次会dump。 +# LVGL-注意事项 + +## 概述 + +在实际使用Quecpython LVGL的开发过程中,客户可能会遇到很多问题,本章总结一些开发者遇到的常见问题。 + +## 图片的选择与使用 + +> **注意:**图片解码消耗RAM资源! + +项目GUI不可避免要用到图片,Quecpython LVGL提供了三种图片格式的支持,分别是PNG,JPG和SJPG。 + +## 图片格式的优缺点 + +### PNG + +优点 + +- 无损格式,图片质量较好 + +- 支持透明 + +缺点 + +- 解码需要RAM资源大(图像宽度 x 图像高度 x 4字节) +- 解码时间较长(图片放四线外挂flash) + +### JPG + +优点 + +- 较节省资源(解码需RAM:图像宽度 x 图像高度 x 3字节) +- 图片质量较好 + +缺点 + +- 不支持透明 +- 优点同时也是缺点,画质比PNG差,解码消耗资源也较大 + +### SJPG + +SJPG 是LVGL自定义的一种基于普通” JPG 的格式,全称split-jpeg ,它是一段带有 sjpg 标头的小 jpeg 片段数据,它的大小将几乎与 jpg 文件相当,或者可能会稍大一些。 + +优点 + +- 节省资源(解码不需申请较大RAM空间) + +缺点 + +- 不支持透明 +- 画质较差 +- 若图片放四线外挂flash,则加载慢 +- 不适用图片缓存机制 + +## 图片格式的选择 + +首先看透明度需求,有透明度需求的直接选择PNG格式。 + +其次得分以下两种情况说明。 + +### 图片放内置flash或外挂六线flash + +这种情况下,flash访问速度快,解码速度差距不大,对于客户而言,UI加载三种格式图片的速度差距不大。 + +请根据对画质的需求和资源分配权衡选择。 + +一般而言,若画质需求不强烈,可以选择SJPG,其次选择JPG,最后PNG; + +若模块RAM资源富余,可以选择PNG,其次JPG,最后SJPG。 + +需要根据项目实际情况找到一个平衡点。 + +### 图片放外挂四线flash + +外挂四线flash访问速度慢,UI图片较多的时候,对于客户而言,卡顿感知明显。 + +这种情况下,需要打开图片缓存机制,选择JPG或PNG格式,不能选择SJPG! + +## 图片缓存机制 + +上文说到,外挂四线flash文件系统读取速度比较慢,LVGL图片解码也比较耗时,导致GUI显示卡顿。需要使用LVGL的图片缓存机制来解决。 + +### 使用方法 + +使用JPG或者PNG格式图片,在切换界面之前执行以下两步: + +```python +lv.img.cache_invalidate_src(None) +lv.img.cache_set_size(cache_num) +``` + +`cache_num` - 需要缓存的图片数目,最大16。 + +> **注意:** +> +> - SJPG与图片缓存机制不兼容!因为SJPG的实质是很多块小图片。 +> - imgbtn组件不能使用图片缓存机制,不要使用imgbtn组件! +> - 缓存的图片会占据RAM。 + +## LVGL休眠场景 + +首先,在需要进入休眠模式的时候,务必确认外设是否停止交互,USB是否已断开,线程是否都已阻塞或挂起,否则无法进入休眠模式。 + +在确保上述条件满足的情况下,模块一般采取以下流程进休眠,其中背光关闭请根据硬件设计来对应的关闭。 + +```python +import pm +import lvgl as lv + +# Allow module to enter low-power mode in idle state +pm.autosleep(1) +# Allow LVGL to enter low-power mode in idle state +lv.autoSleep(1) +# LCD enters sleep state +lcd.lcd_display_off() +# Touchpad enters sleep state if exists +tp.suspend() +# Close LCD backlight if it can be controlled +``` + +退出休眠的时候执行相反的操作,如下。 + +```python +import pm +import lvgl as lv + +# Module exits from low-power mode +pm.autosleep(0) +# LVGL exits from low-power mode +lv.autoSleep(0) +# Wake LCD up +lcd.lcd_display_on() +# Wake touchpad up +tp.resume() +# Open lcd backlight if it can be controlled +``` + +## 其他注意事项 + +- 避免组件或者样式被gc回收,请将其定义为全局变量。 +- 切换界面之前不要执行太多耗时操作,否则可能造成切换页面卡顿。 +- 因LVGL底层限制,不要给一个组件多次的添加样式(add_style),超过64次会dump。 - 从heap消耗上看,图片解码会消耗大量的heap,建议尽量少用不必要的大图片。比如纯色背景和渐变色背景都可以使用lvgl的背景色来完成,没必要使用图片。 \ No newline at end of file diff --git a/docs/Application_guide/zh/multi-media/lvgl/lvgl_ui_tool.md b/docs/Application_guide/zh/multi-media/lvgl/lvgl_ui_tool.md index a7b86f5317105f20997e8b6209f9bf29547feb4d..231b8ccf785a1db67670c9562aaf93ec8e876384 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/lvgl_ui_tool.md +++ b/docs/Application_guide/zh/multi-media/lvgl/lvgl_ui_tool.md @@ -1,131 +1,131 @@ -# LVGL-UI工具 - -## 简介 - -`Gui Guider`(恩智浦)是PC端GUI设计工具,可以通过拖放控件方式设计LVGL GUI页面,加速GUI设计。设计完成后可在PC上仿真运行,确认设计完毕后生成python脚本,再整合入模组中。完成开发。 - -[`Gui Guider`下载地址](https://www.nxp.com/products/processors-and-microcontrollers/s32-automotive-platform/s32k-auto-general-purpose-mcus/gui-guider:GUI-GUIDER)。 - -本文将介绍如何使用GUI Guider辅助进行Quecpython LVGL开发。 - -GUI Guider的主要特征 - -- 支持Windows 10和Ubuntu 20.04。 -- 支持中文、英文。 -- 兼容LVGL V8.3.5版本。 -- 支持拖放的所见即所得(WYSIWYG)用户界面设计。 -- 多种字体支持及第三方字体导入。 -- 自动产生python语言源代码。 -- 支持默认样式和自定义样式。 -- 演示应用程序集成。 -- 实时日志显示。 -- 集成上位机仿真器。 - -## 使用说明 - -正确安装好`Gui Guider`就可以开始设计GUI了,设计好模拟完毕后即可一键生成python代码,经过少量修改后就可以下载到模块中运行了。下面是具体的使用步骤。 - -### 创建工程 - -打开`Gui Guider`,在下面界面选择Create a new project。 - -![guiguider1](../../media/multi-media/lvgl/guiguider1.png) - -进入下面界面后选择v8.3.5,点击next进入下一步。 - -![guiguider2](../../media/multi-media/lvgl/guiguider2.png) - -在下面界面选择simulator模拟器。 - -![guiguider3](../../media/multi-media/lvgl/guiguider3.png) - -在下面界面选择一个模板,您可根据需要选择,如下有播放器,标签,仪表盘等,选择完点击next进入下一步。 - -![guiguider4](../../media/multi-media/lvgl/guiguider4.png) - -在下面界面的右侧填写项目名,选择保存路径,色深选择16位,根据项目LCD的实际分辨率选择分辨率,填写完成点击Create创建工程。 - -![guiguider5](../../media/multi-media/lvgl/guiguider5.png) - -### GUI设计 - -创建完项目后进入UI设计界面,下面为几个主要的区域的介绍。 - -- 工具界面左侧Layers下的Screen为当前创建的UI界面列表,可以通过点击“+”按钮来创建新界面。 -- 工具界面左侧Layers下的Widgets为当前编辑UI界面的组件列表。 -- 工具界面中间的UI editor左侧为可以拖拽的组件库,点击下面的扩展可以展开所有的组件。 -- 工具界面中间的UI editor主要部分为当前正在编辑的UI界面。 -- 工具界面右侧的Attributes可以设置UI界面或组件的属性值。 - -![guiguider6](../../media/multi-media/lvgl/guiguider6.png) - -请按照如下步骤完成UI的设计: - -创建所有需要的界面,命名最好规范,方便后面的代码生成及维护; - -设计每个界面,将所需的组件拖拽到界面上,调整位置和大小,设置属性; - -![guiguider7](../../media/multi-media/lvgl/guiguider7.png) - -如需给组件添加事件,比如点击切换界面,则先选中需要添加的组件,再在任意地方鼠标右击,点击Add Event按钮点开添加事件窗口,如下图所示。 - -![image-20230809115014573](../../media/multi-media/lvgl/guiguider10.png) - -![image-20230809115139952](../../media/multi-media/lvgl/guiguider11.png) - -UI设计完成后,点击右上角的三角形图标,选择Micropython模拟器点击启动,在模拟器上查看效果和验证事件。 - -![guiguider8](../../media/multi-media/lvgl/guiguider8.png) - -![guiguider9](../../media/multi-media/lvgl/guiguider9.png) - -### 代码生成 - -完成GUI的设计和模拟器模拟后,点击右上角的按钮生成代码。 - -![guiguider12](../../media/multi-media/lvgl/guiguider12.png) - -点击中间视图的Code Viewer可以预览生成的代码,生成的python代码名为gui_guider.py如下。代码路径为工程下的generated目录下。 - -![image-20230809141858481](../../media/multi-media/lvgl/guiguider13.png) - - - -## 适配Quecpython - -GUI guider生成的脚本与实际应用的脚本还有些轻微差异。稍微修改后即可直接运行于模组中。主要实际操作如下: - -1. 添加对LCD的初始化。 -2. 修改gui guider生成的代码。 -3. 下载脚本到模组运行。 - -### 添加LCD的初始化 - -在gui guider生成的py文件开始添加LCD显示屏初始化代码,参照[wiki](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html)。 - -### 修改生成的代码 - -gui guider生成的py文件还需进行一些修改才能适配Quecpython LVGL。 - -### 修改对LVGL的初始化 - -将生成文件的LVGL初始化代码,参照[LVGL流程](https://gitee.com/qpy-doc-center/teedoc_with_qpydoc/tree/main/docs/Application_guide/zh/multi-media/lvgl/lvgl_flow.md)的LVGL初始化章节进行修改。 - -### 修改对图片的使用 - -生成的文件中,对图片的使用采用的的是其自定义的解码接口,而Quecpython LVGL自带图片解码器,故可直接使用路径调用。 - -把gui guider生成的py文件中所有的set_src接口的参数修改成图片的路径,示例如下。 - -```python -img_obj.set_src("U:/demo.png") -``` - -> **注意:** -> -> gui guider生成的代码中,每个组件都对应生成了一个style,这使得代码非常的臃肿,所以如需进阶开发,还得对其做进一步优化,比如减少不必要的style定义,比如去除不必要的try语句等。 - - - - - +# LVGL-UI工具 + +## 简介 + +`Gui Guider`(恩智浦)是PC端GUI设计工具,可以通过拖放控件方式设计LVGL GUI页面,加速GUI设计。设计完成后可在PC上仿真运行,确认设计完毕后生成python脚本,再整合入模组中。完成开发。 + +[`Gui Guider`下载地址](https://www.nxp.com/products/processors-and-microcontrollers/s32-automotive-platform/s32k-auto-general-purpose-mcus/gui-guider:GUI-GUIDER)。 + +本文将介绍如何使用GUI Guider辅助进行Quecpython LVGL开发。 + +GUI Guider的主要特征 + +- 支持Windows 10和Ubuntu 20.04。 +- 支持中文、英文。 +- 兼容LVGL V8.3.5版本。 +- 支持拖放的所见即所得(WYSIWYG)用户界面设计。 +- 多种字体支持及第三方字体导入。 +- 自动产生python语言源代码。 +- 支持默认样式和自定义样式。 +- 演示应用程序集成。 +- 实时日志显示。 +- 集成上位机仿真器。 + +## 使用说明 + +正确安装好`Gui Guider`就可以开始设计GUI了,设计好模拟完毕后即可一键生成python代码,经过少量修改后就可以下载到模块中运行了。下面是具体的使用步骤。 + +### 创建工程 + +打开`Gui Guider`,在下面界面选择Create a new project。 + +![guiguider1](../../media/multi-media/lvgl/guiguider1.png) + +进入下面界面后选择v8.3.5,点击next进入下一步。 + +![guiguider2](../../media/multi-media/lvgl/guiguider2.png) + +在下面界面选择simulator模拟器。 + +![guiguider3](../../media/multi-media/lvgl/guiguider3.png) + +在下面界面选择一个模板,您可根据需要选择,如下有播放器,标签,仪表盘等,选择完点击next进入下一步。 + +![guiguider4](../../media/multi-media/lvgl/guiguider4.png) + +在下面界面的右侧填写项目名,选择保存路径,色深选择16位,根据项目LCD的实际分辨率选择分辨率,填写完成点击Create创建工程。 + +![guiguider5](../../media/multi-media/lvgl/guiguider5.png) + +### GUI设计 + +创建完项目后进入UI设计界面,下面为几个主要的区域的介绍。 + +- 工具界面左侧Layers下的Screen为当前创建的UI界面列表,可以通过点击“+”按钮来创建新界面。 +- 工具界面左侧Layers下的Widgets为当前编辑UI界面的组件列表。 +- 工具界面中间的UI editor左侧为可以拖拽的组件库,点击下面的扩展可以展开所有的组件。 +- 工具界面中间的UI editor主要部分为当前正在编辑的UI界面。 +- 工具界面右侧的Attributes可以设置UI界面或组件的属性值。 + +![guiguider6](../../media/multi-media/lvgl/guiguider6.png) + +请按照如下步骤完成UI的设计: + +创建所有需要的界面,命名最好规范,方便后面的代码生成及维护; + +设计每个界面,将所需的组件拖拽到界面上,调整位置和大小,设置属性; + +![guiguider7](../../media/multi-media/lvgl/guiguider7.png) + +如需给组件添加事件,比如点击切换界面,则先选中需要添加的组件,再在任意地方鼠标右击,点击Add Event按钮点开添加事件窗口,如下图所示。 + +![image-20230809115014573](../../media/multi-media/lvgl/guiguider10.png) + +![image-20230809115139952](../../media/multi-media/lvgl/guiguider11.png) + +UI设计完成后,点击右上角的三角形图标,选择Micropython模拟器点击启动,在模拟器上查看效果和验证事件。 + +![guiguider8](../../media/multi-media/lvgl/guiguider8.png) + +![guiguider9](../../media/multi-media/lvgl/guiguider9.png) + +### 代码生成 + +完成GUI的设计和模拟器模拟后,点击右上角的按钮生成代码。 + +![guiguider12](../../media/multi-media/lvgl/guiguider12.png) + +点击中间视图的Code Viewer可以预览生成的代码,生成的python代码名为gui_guider.py如下。代码路径为工程下的generated目录下。 + +![image-20230809141858481](../../media/multi-media/lvgl/guiguider13.png) + + + +## 适配Quecpython + +GUI guider生成的脚本与实际应用的脚本还有些轻微差异。稍微修改后即可直接运行于模组中。主要实际操作如下: + +1. 添加对LCD的初始化。 +2. 修改gui guider生成的代码。 +3. 下载脚本到模组运行。 + +### 添加LCD的初始化 + +在gui guider生成的py文件开始添加LCD显示屏初始化代码,参照[wiki](https://python.quectel.com/doc/API_reference/zh/peripherals/machine.LCD.html)。 + +### 修改生成的代码 + +gui guider生成的py文件还需进行一些修改才能适配Quecpython LVGL。 + +### 修改对LVGL的初始化 + +将生成文件的LVGL初始化代码,参照[LVGL流程](https://gitee.com/qpy-doc-center/teedoc_with_qpydoc/tree/main/docs/Application_guide/zh/multi-media/lvgl/lvgl_flow.md)的LVGL初始化章节进行修改。 + +### 修改对图片的使用 + +生成的文件中,对图片的使用采用的的是其自定义的解码接口,而Quecpython LVGL自带图片解码器,故可直接使用路径调用。 + +把gui guider生成的py文件中所有的set_src接口的参数修改成图片的路径,示例如下。 + +```python +img_obj.set_src("U:/demo.png") +``` + +> **注意:** +> +> gui guider生成的代码中,每个组件都对应生成了一个style,这使得代码非常的臃肿,所以如需进阶开发,还得对其做进一步优化,比如减少不必要的style定义,比如去除不必要的try语句等。 + + + + + diff --git a/docs/Application_guide/zh/multi-media/lvgl/startup_logo.md b/docs/Application_guide/zh/multi-media/lvgl/startup_logo.md index 1541104f5e08b465f5f613a760c52e987944405e..313ce108f0b3cb862ffeaa93b0a49033d67daf01 100644 --- a/docs/Application_guide/zh/multi-media/lvgl/startup_logo.md +++ b/docs/Application_guide/zh/multi-media/lvgl/startup_logo.md @@ -1,7 +1,170 @@ -# 开机LOGO - -## 概述 - -从按下开机键到GUI界面显示之间有一段时间的空白期,业务上通常采用显示开机logo的方案来填补。一个大气的开机logo界面也能为您的系统增色不少。 - -本章节将分别介绍如何使用开机logo方案。 \ No newline at end of file +# 开机LOGO + +## 概述 + +从按下开机键到GUI界面显示之间有一段时间的空白期,业务上通常采用显示开机logo的方案来填补。一个大气的开机logo界面也能为您的系统增色不少。 + +本章节将分别介绍如何使用开机logo方案。 +> **注意:**现只支持ASR平台(M,N.P系列)!展锐平台(U,G系列)敬请期待! +> 此处以EC800MCN_GA为例 +### 制作显示图片logo +1. 打开图片编辑工具,将图片裁剪成LCD的分辨率(此处以240*320为例),并保存为jpg格式。 +2. 打开Img2Lcd.exe工具,按照如下图操作配置后点击保存。 +![lvgl_demo2](../../media/multi-media/lvgl/startlogo1.png) +3. 将步骤2的生成文件命名为logo.bin,如下图。 +![lvgl_demo2](../../media/multi-media/lvgl/startlogo2.png) +4. 编写logo加工脚本,logo_bin_creat.py +```python +from struct import * + + +def bin_create(*args): + if len(args) != 2: + print("wrong params number!") + return -1 + # 大端1,小端2 + endian = input("输入大小端(1:小端; 2:大端):") + with open("logo.bin","wb") as dest_file: + # start + start = "start" + end = "end" + + # args handle + width = int(input("请输入宽度:")) + height = int(input("请输入高度:")) + lcd_type = int(input("请输入LCD类型(0:RGB565 1:FSTN):")) + init_data_len = len(args[0]) + init_data = args[0] + blk_pin = int(input("请输入背光引脚:")) + interface = int(input("请输入lcd接口类型(0:LCD;1:SPI):")) + # logo.bin handle + with open(args[1],"rb") as logo_file: + logo_data = logo_file.read() + logo_len = len(logo_data) + + # LCD interface + if interface == 0: + dataline = int(input("请输入dataline:")) + linenum = int(input("请输入linenum:")) + endian_type = int(input("请输入大小端(0:LSB 1:MSB):")) + clk = int(input("请输入时钟clk(0:6.5M 1:13M 2:26M 3:52M 4:3.25M5:1.625M 6:812.5K):")) + # 大端 + if endian == "1": + write_data = pack(">2HBH%dB6BI"%init_data_len,width,height,lcd_type,init_data_len,*init_data, + blk_pin,interface,dataline,linenum,endian_type,clk,logo_len) + # 小端 + else: + write_data = pack("<2HBH%dB6BI" % init_data_len, width, height, lcd_type, init_data_len, *init_data, + blk_pin, interface, dataline, linenum, endian_type, clk, logo_len) + # SPI interface + elif interface == 1: + spi_port = int(input("请输入spi_port:")) + spi_mode = int(input("请输入spi_mode:")) + spi_clk = int(input("请输入spi_clk(0:100K 1:200K 2:300K 3:400K 4:500K 5:600K 6:700K 7:812.5K 8:1.625M 9:3.25M 10:6.5M 11:13M 12:26M 13:52M):")) + cs_pin = int(input("请输入cs引脚:")) + dc_pin = int(input("请输入dc引脚:")) + rst_pin = int(input("请输入rst引脚:")) + # 大端 + if endian == "1": + write_data = pack(">2HBH%dB8BI" % init_data_len, width, height, lcd_type, init_data_len,*init_data, + blk_pin, interface, spi_port, spi_mode, cs_pin, dc_pin, rst_pin,spi_clk,logo_len) + # 小端 + else: + write_data = pack("<2HBH%dB8BI" % init_data_len, width, height, lcd_type, init_data_len, *init_data, + blk_pin, interface, spi_port, spi_mode, cs_pin, dc_pin, rst_pin, spi_clk, logo_len) + else: + print("wrong interface!") + return -1 + dest_file.write(start.encode()) + dest_file.write(write_data) + dest_file.write(logo_data) + dest_file.write(end.encode()) + +# init_data_RGB +#该部分为st7789 240*320驱动 +init_data_ST7789_240_320 = ( + 2, 0, 120, + 0, 0, 0x11, + 0, 1, 0x36, + 1, 1, 0x00, + 0, 1, 0x3A, + 1, 1, 0x05, + 0, 0, 0x20, + 0, 5, 0xB2, + 1, 1, 0x05, + 1, 1, 0x05, + 1, 1, 0x00, + 1, 1, 0x33, + 1, 1, 0x33, + 0, 1, 0xB7, + 1, 1, 0x23, + 0, 1, 0xBB, + 1, 1, 0x22, + 0, 1, 0xC0, + 1, 1, 0x2C, + 0, 1, 0xC2, + 1, 1, 0x01, + 0, 1, 0xC3, + 1, 1, 0x13, + 0, 1, 0xC4, + 1, 1, 0x20, + 0, 1, 0xC6, + 1, 1, 0x0F, + 0, 2, 0xD0, + 1, 1, 0xA4, + 1, 1, 0xA1, + 0, 1, 0xD6, + 1, 1, 0xA1, + 0, 14, 0xE0, + 1, 1, 0x70, + 1, 1, 0x06, + 1, 1, 0x0C, + 1, 1, 0x08, + 1, 1, 0x09, + 1, 1, 0x27, + 1, 1, 0x2E, + 1, 1, 0x34, + 1, 1, 0x46, + 1, 1, 0x37, + 1, 1, 0x13, + 1, 1, 0x13, + 1, 1, 0x25, + 1, 1, 0x2A, + 0, 14, 0xE1, + 1, 1, 0x70, + 1, 1, 0x04, + 1, 1, 0x08, + 1, 1, 0x09, + 1, 1, 0x07, + 1, 1, 0x03, + 1, 1, 0x2C, + 1, 1, 0x42, + 1, 1, 0x42, + 1, 1, 0x38, + 1, 1, 0x14, + 1, 1, 0x14, + 1, 1, 0x27, + 1, 1, 0x2C, + 0, 0, 0x29, + 0, 4, 0x2a, + 1, 1, 0x00, + 1, 1, 0x00, + 1, 1, 0x00, + 1, 1, 0xef, + 0, 4, 0x2b, + 1, 1, 0x00, + 1, 1, 0x00, + 1, 1, 0x01, + 1, 1, 0x3f, + 0, 0, 0x2c, +) + +# from pathlib import Path +bin_create(init_data_ST7789_240_320,"logo_240_320.bin") +``` +4. 将logo_bin_creat.py和步骤3生成的logo_240_320.bin文件置于同一目录下。 +![lvgl_demo2](../../media/multi-media/lvgl/startlogo3.png) +5. 当前目录下打开cmd,并且运行logo_bin_creat.py脚本,并按照实际参数填写,成功会在当前目录下生成一个logo.bin文件。 +![lvgl_demo2](../../media/multi-media/lvgl/startlogo4.png) +6. 将上面步骤的logo.bin拖进usr目录或者ext目录下,重启模块即可显示图片。 +![lvgl_demo2](../../media/multi-media/lvgl/startlogo5.png) \ No newline at end of file