LVGL 库提交

This commit is contained in:
2026-08-30 08:57:07 +08:00
parent 26c9098630
commit e2f199c6bf
1056 changed files with 556743 additions and 45 deletions
+144
View File
@@ -0,0 +1,144 @@
/*
* 模块名称:UI Menu (菜单页面构建)
* 模块功能:基于 lv_menu 复现 DTU-HMI 树形菜单,支持方向键导航与返回
* 适用平台:STM32F407ZGTx
* 作者:王建锋
* 创建日期:2026-08-29
* 修改记录:
* 2026-08-29 王建锋 创建初始版本
*/
#include "ui_menu.h"
#include "lvgl.h"
/* 菜单节点表(简化自 DTU-HMI menuTab):层级 + 名称 */
typedef struct {
uint8_t level; /* 0=根页面, 1..3=子层次 */
const char *name;
} ui_menu_node_t;
static const ui_menu_node_t g_menu_tab[] = {
{0, "主界面"},
{1, "装置信息"},
{1, "实时数据"},
{2, "交流量"},
{2, "直流量"},
{2, "开入量"},
{1, "定值参数"},
{2, "定值"},
{3, "定值"},
{3, "遥调"},
{3, "零压"},
{3, "电压"},
{2, "查看"},
{3, "定值"},
{3, "遥调"},
{3, "零压"},
{3, "电压"},
{1, "遥测量"},
{2, "测量值"},
{2, "遥调系数"},
{2, "遥测系数"},
{2, "双字节"},
{2, "装置遥调"},
{1, "装置维护"},
{2, "时间设置"},
{2, "强制复归"},
{2, "手动录波"},
{2, "自动录波"},
{1, "通讯设置"},
{2, "通讯参数"},
{2, "网络配置"},
{2, "SNTP设置"},
{1, "记录查询"},
{2, "SOE记录"},
{2, "事故记录"},
{2, "操作记录"},
{2, "告警记录"},
{2, "变位告警"},
{2, "遥信记录"},
{2, "自检记录"},
{2, "定值记录"},
{2, "录波记录"},
{0, "厂家设置"},
{1, "元件设置"},
{1, "恢复默认"},
{2, "全部恢复"},
{2, "默认参数"},
{2, "默认定值"},
{2, "默认系数"},
{2, "电压"},
{2, "元件参数"},
{1, "版本显示"},
{1, "装置遥调"},
{2, "测量遥调"},
{2, "装置遥调"},
{2, "直流遥调"},
{2, "开出遥调"},
{2, "装置记录"},
{2, "告警记录"},
{2, "遥调记录"},
{2, "信号复归"},
{1, "版本信息"},
};
/*
* 函数功能:构建菜单(lv_menu 页面树),复现参考项目菜单结构
* 入口参数:无
* 返回值:0 - 成功,其他 - 失败(对象创建失败)
* 限定条件:ui_port_init() 已成功调用,活动屏幕存在
* 函数说明:1. 依据紧凑节点表按层级生成 lv_menu 页面与返回栈
* 2. 将菜单对象加入默认输入组,支持远端按键导航
* 3. 叶子节点挂占位页,等待后续逐项填充具体功能
*/
int ui_menu_init(void)
{
lv_obj_t *menu = lv_menu_create(lv_screen_active());
if (menu == NULL) {
return -1;
}
lv_obj_set_size(menu, 160, 160);
lv_menu_set_mode_root_back_button(menu, LV_MENU_ROOT_BACK_BUTTON_ENABLED);
lv_group_add_obj(lv_group_get_default(), menu);
uint32_t n = sizeof(g_menu_tab) / sizeof(g_menu_tab[0]);
lv_obj_t *root_page = NULL;
lv_obj_t *parent_stack[4] = {NULL, NULL, NULL, NULL};
for (uint32_t i = 0; i < n; i++) {
uint8_t L = g_menu_tab[i].level;
const char *name = g_menu_tab[i].name;
if (i == 0) {
/* 第 0 节点为根(主界面) */
root_page = lv_menu_page_create(menu, name);
parent_stack[0] = root_page;
continue;
}
/* 当前节点页面 */
lv_obj_t *page = lv_menu_page_create(menu, name);
/* 叶子:页内挂占位内容 */
int leaf = (i + 1 >= n) || (g_menu_tab[i + 1].level <= L);
if (leaf) {
lv_obj_t *ph = lv_menu_cont_create(page);
lv_obj_t *pl = lv_label_create(ph);
lv_label_set_text(pl, "功能未实现(占位)");
}
/* 挂到父页:level0 直挂根,其余挂到上一级页面 */
lv_obj_t *parent = (L == 0) ? root_page : parent_stack[L - 1];
/* 在父页创建一个容器项,点击加载当前页 */
lv_obj_t *item = lv_menu_cont_create(parent);
lv_obj_t *lbl = lv_label_create(item);
lv_label_set_text(lbl, name);
lv_menu_set_load_page_event(menu, item, page);
parent_stack[L] = page;
}
lv_menu_set_page(menu, root_page);
return 0;
}