WouoUI-Page移植
一,移植文件
仅仅将WouoUI-Page的Csource资源移植到项目中
二,菜单配置
在WouoUI_conf.h中进行,这个配置文件允许你定制菜单的外观(屏幕尺寸、字体、图标、间距等)和行为,而无需修改框架的核心代码,提高了可维护性和易用性
三,缓存刷新函数
这个函数将WouoUI-Page的内容发送到屏幕上
WouoUI-Page 菜单框架本身不直接操作硬件,它将绘制好的菜单界面存储在一个缓冲区中。你需要提供一个函数,该函数能接收这个缓冲区,并将其内容发送到 OLED 屏幕上显示出来。函数的接口由 WouoUI-Page 定义
原因: 这是框架与具体显示驱动解耦的关键。WouoUI-Page 只负责生成菜单的像素数据,而如何将这些数据显示到屏幕上,则由用户提供的这个"刷新函数"决定。这样,WouoUI-Page 就可以适配各种不同的 OLED 驱动(如基础驱动、u8g2 驱动等)。
下面是基于基础驱动写的缓存刷新函数
#include "oled.h" // 假设你的基础驱动头文件是 oled.h
/**
* @brief 将 WouoUI 缓冲区的数据发送到 OLED 显示
* @param buff WouoUI 提供的缓冲区指针,大小为 [高度/8][宽度] 或 [4][128] for 128x32
*/
void OLED_SendBuff(uint8_t buff[4][128])
{
// 遍历每一页 (0-3)
for(uint8_t page = 0; page < 4; page++)
{
// 设置 OLED 的页地址
OLED_Write_cmd(0xb0 + page); // 0xB0 - 0xB3
// 设置 OLED 的列地址 (从第 0 列开始)
OLED_Write_cmd(0x00); // 低半字节列地址
OLED_Write_cmd(0x10); // 高半字节列地址 (0x10 | 0 = 0)
// 循环写入该页的 128 列数据
for (uint8_t column = 0; column < 128; column++)
{
// 从 WouoUI 缓冲区取数据,并通过基础驱动的数据写入函数发送
OLED_Write_data(buff[page][column]);
}
}
}
注意:此处的
OLED_Write_cmd
和OLED_Write_data
是你基础 OLED 驱动库提供的函数,你需要根据实际情况调整。缓冲区buff
的维度也需要与你的屏幕和 WouoUI 配置匹配。
四,初始化
1,包含头文件
#include "WouoUI.h" // WouoUI 核心框架
#include "WouoUI_user.h" // 用户自定义的菜单结构和回调函数 (通常需要用户创建或修改)
2,在 main 函数中进行初始化
// 假设你的缓存刷新函数是 OLED_SendBuff
extern void OLED_SendBuff(uint8_t buff[4][128]);
int main(void)
{
// ... 系统初始化 ...
OLED_Init(); // 假设调用基础驱动的初始化
// 或者 u8g2 初始化序列...
// --- WouoUI 初始化 ---
// 1. 选择默认UI (如果 WouoUI_user.c 中定义了多个 UI 实例)
WouoUI_SelectDefaultUI();
// 2. 绑定缓存刷新函数 (关键步骤)
// 将你实现的 OLED_SendBuff 函数地址传递给 WouoUI 框架
WouoUI_AttachSendBuffFun(OLED_SendBuff);
// 3. 初始化用户菜单 (执行 WouoUI_user.c/h 中定义的菜单结构初始化)
TestUI_Init(); // 函数名取决于用户文件,通常是初始化页面、列表项等
// --- WouoUI 初始化完成 ---
原因: 这是将 WouoUI 框架与你的系统连接起来的关键步骤:
WouoUI_SelectDefaultUI()
: (如果需要)选择要激活的菜单实例。
WouoUI_AttachSendBuffFun()
: 极其重要。告诉 WouoUI 框架当它完成菜单绘制后,应该调用哪个函数 (OLED_SendBuff
) 来将缓冲区内容刷新到屏幕上。
TestUI_Init()
(或类似名称): 执行用户定义的菜单初始化代码,这部分通常在WouoUI_user.c/h
中实现,用于创建菜单页面、添加列表项、绑定回调函数等。没有这一步,菜单就是空的。
3,修改 Oled 显示任务函数
void oled_task(void)
{
// 调用 WouoUI 处理函数,参数为两次调用之间的间隔时间 (ms)
// 这个函数会处理按键输入、更新菜单状态、绘制缓冲区
WouoUI_Proc(10); // 假设任务每 10ms 调用一次
}
性能提示:如果
WouoUI_Proc()
执行时间较长或包含阻塞操作(如效率低的刷屏函数),可能会导致系统卡顿。参考文档建议可以将其放在定时器中断回调中执行(例如 10ms 定时中断),以保证固定的调用频率。但这需要注意中断服务程序应尽可能快地执行完毕。
// 示例:在 TIM2 中断回调中调用 (需要先配置并启动 TIM2)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2) // 确保是 TIM2 中断
{
WouoUI_Proc(10); // 假设 TIM2 配置为 10ms 中断一次
}
}
// 在 main 函数中初始化后启动定时器中断
// HAL_TIM_Base_Start_IT(&htim2);
4,解决命名冲突 (如果需要):
参考文档提到,如果基础 OLED 驱动 (oled.c
, oledfont.h
) 中有与 WouoUI 库(或其依赖的库)冲突的名称(例如 F8X16
字体),需要重命名其中一个以解决冲突。例如,将驱动中的 F8X16
改为 Oled_F8X16
。
原因: C 语言不允许在同一作用域内存在同名的函数或全局变量。如果两个不同的库使用了相同的名称,编译器会报错。重命名是解决此问题的常用方法。
5,绑定按键操作
菜单需要响应用户的按键输入(上、下、左、右、确认、返回等)才能进行导航和交互。WouoUI-Page 提供了一个消息队列机制来接收按键事件。
WOUOUI_MSG_QUE_SEND() 函数可以将消息类型(用户的操作)发送给菜单
typedef enum {
msg_up = 0x00, // 上移 / 上一个
msg_down, // 下移 / 下一个
msg_left, // 左移 / 上一个 (混合模式)
msg_right, // 右移 / 下一个 (混合模式)
msg_click, // 确认 / 点击
msg_return, // 返回 / 退出
msg_home, // 回主界面 (可能未完全实现)
msg_none = 0xFF, // 无操作
} InputMsg;
6,使用 u8g2 提高刷新效率
如果在实际使用中感觉菜单响应迟缓、不够流畅,尤其是在菜单切换或滚动时,这很可能是因为你在 6.3 节实现的 OLED_SendBuff
函数效率不高。
原因: 基础的 OLED 驱动通常是逐字节或逐页发送数据,并且每次发送前可能需要设置页地址和列地址,这涉及到多次 I2C 命令传输,相对耗时。而像 u8g2 这样的图形库,其底层通信回调 (u8x8_byte_hw_i2c
) 通常经过优化,能够更高效地批量发送数据。此外,u8g2 的 SendBuffer
函数内部可能包含了更优化的传输策略
#include "u8g2.h" // 需要包含 u8g2 头文件
#include // 需要包含 string.h 以使用 memcpy
// 假设全局 u8g2 实例变量名为 u8g2
extern u8g2_t u8g2;
/**
* @brief 使用 u8g2 的缓冲区和发送函数来刷新 WouoUI 的内容
* @param buff WouoUI 提供的缓冲区指针,大小 [4][128] for 128x32
*/
void OLED_SendBuff(uint8_t buff[4][128])
{
// 1. 获取 u8g2 内部 RAM 缓冲区的指针
uint8_t *u8g2_buffer = u8g2_GetBufferPtr(&u8g2);
// 2. 将 WouoUI 缓冲区的内容完整地复制到 u8g2 的缓冲区中
// 注意:确保两个缓冲区大小完全一致 (4 * 128 bytes)
memcpy(u8g2_buffer, buff, 4 * 128);
// 3. 调用 u8g2 的发送函数,将 u8g2 缓冲区的内容发送到 OLED
// 这将使用 u8g2 配置的高效 I2C 回调函数来完成传输
u8g2_SendBuffer(&u8g2);
}
原因: 这个修改利用了 u8g2 可能更优化的底层 I2C/SPI 传输实现。通过 memcpy
将 WouoUI 生成的图像数据快速复制到 u8g2 的 RAM 缓冲区,然后调用 u8g2_SendBuffer()
,让 u8g2 接管实际的硬件发送过程,从而可能获得更流畅的菜单体验。
五,应用
md文件和user文件 交给ai
初始化的TestUI_Init(); 修改
7. 实战:WouoUI-Page 应用开发指南
完成了 WouoUI-Page 库的底层移植后,现在我们来深入了解如何在应用层使用它来构建你的用户界面。本指南旨在帮助你快速上手。
7.1 基本概念
在开始编码之前,理解 WouoUI-Page 的几个核心概念非常重要:
页面 (Page): UI 的基本单元,可以是占据整个屏幕的全屏页面(如标题页 TitlePage, 列表页 ListPage, 波形页 WavePage),也可以是覆盖在当前页面之上的弹窗页面(如消息窗 MsgWin, 确认窗 ConfWin, 数值调节窗 ValWin, 旋钮调节窗 SpinWin, 列表选择窗 ListWin)。每个页面都有其类型 (PageType) 和特定的处理逻辑。
选项 (Option): 页面上可供用户交互的元素。通常,一个页面的内容由一个 Option 结构体数组定义。Option 结构体包含了选项的显示文本 (text)、可能关联的内容字符串 (content)、关联的数值 (val) 等信息。text 字符串的第一个字符往往具有特殊含义,决定了该选项的基本行为:
-: 仅用作标题或分隔符,通常不可选中。
+: 点击后通常用于跳转到另一个指定的页面。
!: 点击后通常用于触发一个动作或弹出消息窗口。
~: 点击后通常打开一个数值调节弹窗 (ValWin 或 SpinWin),让用户修改此选项关联的 val 值。
@: 用于创建一个二值(开/关)选择框,点击切换状态,状态通常也存储在 val 中 (0 或 1)。
(其他字符): 普通的可选中文本项。
消息 (InputMsg): 代表用户的输入操作,例如按键按下。WouoUI 定义了一组标准输入消息,如 msg_up (上), msg_down (下), msg_left (左), msg_right (右), msg_click (确认/点击), msg_return (返回)。你需要将你的硬件按键事件映射到这些消息。
回调函数 (CallBackFunc): 你可以为每个页面(全屏页或弹窗)绑定一个回调函数。当该页面处于活动状态并接收到用户输入消息时,这个回调函数就会被 WouoUI 框架自动调用。你可以在回调函数中编写该页面的具体响应逻辑,例如:根据用户点击的选项跳转到新页面、修改选项的值、弹出确认窗口、执行特定硬件操作等。回调函数的原型通常是 bool CallBackFunc(const Page *cur_page_addr, InputMsg msg)。
7.2 初始化 WouoUI
在你的应用程序启动代码中(例如 main 函数或专门的初始化函数),需要执行一系列步骤来初始化 WouoUI 框架,使其准备好工作。
// 假设在你的 Application_Init() 函数中
#include “WouoUI.h”
#include “WouoUI_user.h” // 必须包含你定义的菜单结构头文件
#include “oled.h” // 假设你的屏幕驱动接口在这里
// 假设你的屏幕刷新函数是这个 (已在移植部分实现)
extern void OLED_SendBuff(uint8_t buff[4][128]);
void Application_Init() {
// … 其他硬件初始化代码 (GPIO, Clock, I2C, OLED Driver Init …) …
OLED_Init(); // 确保 OLED 驱动已初始化
// --- WouoUI 初始化序列 ---
// 1. 选择默认 UI 配置 (如果 WouoUI_user.c 中有多个 UI 定义,可选)
WouoUI_SelectDefaultUI();
// 2. 绑定屏幕刷新函数 (关键!)
// 将你实现的 `OLED_SendBuff` 函数指针传递给 WouoUI
WouoUI_AttachSendBuffFun(OLED_SendBuff);
// 3. 清空 WouoUI 内部缓冲区并首次发送到屏幕 (可选, 用于清屏)
// 这会确保屏幕初始状态是干净的
WouoUI_BuffClear(); // 清空 WouoUI 的 RAM 缓冲区
WouoUI_BuffSend(); // 调用 OLED_SendBuff 将空缓冲区刷到屏幕
// 4. 初始化你定义的所有 UI 页面 (关键!)
// 这会调用 WouoUI_user.c 中实现的 TestUI_Init() (或其他自定义名称) 函数
// 该函数负责创建所有页面实例、定义选项、绑定回调等
TestUI_Init();
// 5. 设置默认绘图颜色 (可选)
// 对于单色屏,1 通常代表前景色 (点亮的像素)
WouoUI_GraphSetPenColor(1);
// --- WouoUI 初始化完成 ---
}
关键点解释:
WouoUI_AttachSendBuffFun(OLED_SendBuff)
: 这是连接 WouoUI 内部渲染结果和你实际屏幕显示驱动的桥梁,必须正确设置。
TestUI_Init()
: 这个函数通常在 WouoUI_user.c
中实现,是你定义整个 UI 结构的核心。没有它,菜单就是空的。
7.3 创建页面 (以列表页为例)
创建 UI 界面的主要工作通常在 WouoUI_user.c
和 WouoUI_user.h
文件中完成。你需要定义页面对象、选项数组,并编写回调函数来处理交互。
步骤 1: 定义页面对象和选项数组 (通常在 .h 或 .c 文件顶部)
// WouoUI_user.h 或 WouoUI_user.c
#include “WouoUI.h”
// — 定义页面实例 —
// 假设我们有一个主页面 (main_page) 和一个列表设置页面 (settings_list_page)
extern TitlePage main_page; // 主页面可能是磁贴类型 (TitlePage)
extern ListPage settings_list_page; // 设置页面是列表类型 (ListPage)
// — 定义设置页面的选项 —
// Option 结构体数组定义了列表页的内容和行为
Option settings_options[] = {
{.text = (char*)“- Settings Menu”}, // 标题项,不可选
{.text = (char*)“! Beep On/Off”}, // 点击触发动作 (通过回调处理)
{.text = (char*)“~ Brightness”, .val=80}, // 点击打开数值调节弹窗, 初始值80
{.text = (char*)“@ Auto Save”, .val=1}, // 二值选择框,初始值为 1 (开)
{.text = (char*)“+ About”}, // 点击跳转到 “About” 页面
{.text = (char*)“-”}, // 分隔符
{.text = (char*)“< Back to Main”}, // 返回项 (也可以用 ‘+’ 跳转或在回调处理返回)
};
// 计算选项数量 (C 语言常用技巧)
#define SETTINGS_OPTIONS_NUM (sizeof(settings_options) / sizeof(Option))
// — 定义共用的弹窗页面实例 (可选, 推荐) —
// 定义一些通用的弹窗实例,可以在多个页面中复用
extern MsgWin common_msg_page; // 用于显示提示信息
extern ConfWin common_conf_page; // 用于显示确认对话框
extern ValWin common_val_page; // 用于调节数值
步骤 2: 定义页面的回调函数 (在 .c 文件中)
回调函数是处理页面交互逻辑的核心。
// WouoUI_user.c
#include “WouoUI_user.h”
// — 设置列表页面的回调函数 —
// 当 settings_list_page 活动时,发生按键输入会调用此函数
bool SettingsListPage_CallBack(const Page cur_page_addr, InputMsg msg) {
// 检查是否是 “确认/点击” 消息
if (msg == msg_click) {
// 获取当前光标选中的是哪个选项
Option selected_option = WouoUI_ListTitlePageGetSelectOpt(cur_page_addr);
// --- 根据选中的选项文本执行不同操作 ---
if (strcmp(selected_option->text, "! Beep On/Off") == 0) {
// 切换蜂鸣器状态 (假设有 Beep_Toggle() 函数)
// Beep_Toggle();
// (可选) 弹出提示消息
WouoUI_MsgWinPageSetContent(&common_msg_page, (char*)"Beep Toggled!");
WouoUI_JumpToPage((PageAddr)cur_page_addr, &common_msg_page); // 跳转到消息弹窗
return true; // 返回 true 表示消息已处理
}
else if (strcmp(selected_option->text, "~ Brightness") == 0) {
// 用户点击了亮度调节项,WouoUI 会自动处理跳转到 ValWin
// 因为选项文本以 '~' 开头。
// 我们可以在 ValWin 的回调中获取最终调节的值,或者让它自动写回
// (如果 ValWin 初始化时 auto_set_bg_opt 设置为 true)
// (可选) 在跳转前,可以预设 ValWin 的参数
WouoUI_ValWinPageSetMinStepMax(&common_val_page, 0, 5, 100); // 设置范围 0-100, 步长 5
// 注意:跳转是自动的,无需手动调用 WouoUI_JumpToPage
}
else if (strcmp(selected_option->text, "@ Auto Save") == 0) {
// 用户点击了自动保存选项,WouoUI 会自动切换 val 的值 (0/1)
// 并更新界面上的勾选框状态。
// 我们可以在这里读取切换后的值 selected_option->val 来执行实际操作
// Apply_AutoSave_Setting(selected_option->val);
return true; // 消息已处理
}
else if (strcmp(selected_option->text, "+ About") == 0) {
// 用户点击了跳转项,WouoUI 会自动跳转到 'about_page'
// (前提是 about_page 已经在 TestUI_Init 中正确初始化)
// 跳转是自动的,无需手动调用 WouoUI_JumpToPage
}
else if (strcmp(selected_option->text, "< Back to Main") == 0) {
// 手动跳转回主页面
WouoUI_JumpToPage((PageAddr)cur_page_addr, &main_page);
return true; // 消息已处理
}
}
// 检查是否是 "返回" 消息
else if (msg == msg_return) {
// 在列表页按返回键,跳转回主页面
WouoUI_JumpToPage((PageAddr)cur_page_addr, &main_page);
return true; // 返回 true 阻止 WouoUI 的默认返回处理 (如果有)
}
// 如果这个回调函数没有完全处理该消息 (例如上下移动 msg_up/down),
// 返回 false,让 WouoUI 继续执行其默认处理 (如列表滚动)
return false;
}
步骤 3: 在 TestUI_Init() 中初始化页面 (在 .c 文件中)
TestUI_Init 函数负责创建所有页面实例,并将它们连接起来。
// WouoUI_user.c
// — 定义页面和弹窗的实例变量 —
// (这些变量需要与 .h 文件中的 extern 声明对应)
TitlePage main_page;
ListPage settings_list_page;
// … 其他页面 …
MsgWin common_msg_page;
ConfWin common_conf_page;
ValWin common_val_page;
// — TestUI_Init 函数 —
void TestUI_Init() {
// (可选) 在这里修改全局 UI 参数,例如动画速度
// g_default_ui_para.ani_param[LIST_ANI] = 300; // 减慢列表动画
// --- 初始化主页面 (假设是磁贴类型) ---
// WouoUI_TitlePageInit(&main_page, MAIN_OPTIONS_NUM, main_options, Setting_loop, MainPage_CallBack);
// (需要先定义 main_options 和 MainPage_CallBack)
// --- 初始化设置列表页面 ---
// 参数: 页面实例指针, 选项数量, 选项数组指针, 页面设置(如循环滚动), 回调函数指针
WouoUI_ListPageInit(&settings_list_page, SETTINGS_OPTIONS_NUM, settings_options, Setting_loop, SettingsListPage_CallBack);
// --- 初始化其他页面 (例如 About 页面) ---
// WouoUI_XXXPageInit(&about_page, ...);
// --- 初始化共用的弹窗页面 ---
// 这些弹窗通常只需要初始化一次,然后在需要时通过设置内容和跳转来使用
// 消息弹窗: 标题 null, 不模糊背景, 显示 2 秒自动返回, 无回调
WouoUI_MsgWinPageInit(&common_msg_page, NULL, false, 2000, NULL);
// 确认弹窗: 标题 null, 模糊背景, 阻塞(需用户选Yes/No), 有回调处理结果
WouoUI_ConfWinPageInit(&common_conf_page, NULL, true, true, CommonConfPage_CallBack);
// 数值弹窗: 标题 null, 默认值0, 范围0-100, 步长1, 自动写回背景选项, 循环, 无回调
WouoUI_ValWinPageInit(&common_val_page, NULL, 0, 0, 100, 1, true, true, NULL);
// ... 初始化其他弹窗 ...
// --- 设置 UI 的主页/起始页 ---
// 告诉 WouoUI 哪个页面是应用程序启动时或按 Home 键时应该显示的页面
p_cur_ui->home_page = &main_page; // 将 main_page 设为主页
// --- 设置共用弹窗页面 ---
// 将之前初始化的共用弹窗实例地址告诉 WouoUI 框架
// 这样当选项文本以 '!', '~' 等开头时,框架知道跳转到哪个弹窗
p_cur_ui->msg_win = &common_msg_page;
p_cur_ui->val_win = &common_val_page;
p_cur_ui->conf_win = &common_conf_page;
// ... 设置其他共用弹窗 ...
}
7.4 页面跳转
页面之间的切换主要通过 WouoUI_JumpToPage(PageAddr self_page, PageAddr terminate_page) 函数实现。
self_page: 当前页面的地址。在回调函数中,通常传入其第一个参数 cur_page_addr。
terminate_page: 要跳转到的目标页面的地址(例如 &settings_list_page, &common_msg_page)。
跳转可以在回调函数中根据用户操作显式调用,或者由 WouoUI 根据选项文本的特殊前缀(如 +
, ~
, !
)自动触发。
// 在某个回调函数中,根据条件跳转到设置页面
if (user_action == GO_TO_SETTINGS) {
WouoUI_JumpToPage((PageAddr)cur_page_addr, &settings_list_page);
}
7.5 处理用户输入
自动处理: 对于列表页 (ListPage) 和磁贴页 (TitlePage),WouoUI 会自动处理 msg_up 和 msg_down 消息,实现光标的上下移动(如果设置了循环模式 Setting_loop,则会循环滚动)。
回调函数处理: 你需要在页面的回调函数中捕获关键的交互消息,主要是 msg_click (确认) 和 msg_return (返回),并根据当前选中的选项执行相应逻辑。
获取选中项: 在列表页或磁贴页的回调函数中,使用 WouoUI_ListTitlePageGetSelectOpt(cur_page_addr) 函数可以获取当前光标所在的 Option 结构体的指针,从而访问其 text, val 等成员。
消息传递: 确保你的按键驱动(或中断处理)能够将按键事件转换为正确的 InputMsg,并使用 WOUOUI_MSG_QUE_SEND(msg) 发送到 WouoUI 的消息队列。
7.6 使用弹窗
弹窗是覆盖在当前页面之上的临时页面,用于显示信息、获取用户确认或输入。
定义与初始化: 如 7.3 节所示,在 WouoUI_user.c/h
中定义弹窗页面实例 (MsgWin, ConfWin, ValWin 等),并在 TestUI_Init()
中调用对应的 WouoUI_XXXWinPageInit()
函数进行初始化。通常建议将常用的弹窗设为共用实例 (如 common_msg_page
),并在 TestUI_Init
中通过 p_cur_ui->msg_win = &common_msg_page;
等方式将其注册到框架。
触发弹窗:
自动触发: 如果列表项文本以特定字符开头(如 ! 对应 MsgWin
或 ConfWin
,~ 对应 ValWin
或 SpinWin
,@ 触发内置逻辑),WouoUI 会自动跳转到注册的共用弹窗页面。
手动触发: 在任何页面的回调函数中,可以通过调用 WouoUI_JumpToPage((PageAddr)cur_page_addr, &my_specific_popup_page); 来跳转到任何已初始化的弹窗页面。
配置弹窗内容/行为 (跳转前): 在手动跳转到弹窗前,通常需要设置其内容或参数:
WouoUI_MsgWinPageSetContent(&common_msg_page, “Action Done!”); 设置消息内容。
WouoUI_ConfWinPageSetContent(&common_conf_page, “Save Changes?”); 设置确认框的提示文本。
WouoUI_ValWinPageSetMinStepMax(&common_val_page, 0, 10, 100); 设置数值调节范围和步长。
WouoUI_ValWinPageSetCurVal(&common_val_page, current_value); 设置数值调节的初始值。
处理弹窗结果:
MsgWin: 通常用于显示信息,可设置显示一段时间后自动返回 (auto_ret_time
参数)。
ConfWin: 如果设置了回调函数,可以在回调函数中检查 conf_ret 成员 (true 为 Yes, false 为 No) 来获取用户的选择。
ValWin / SpinWin:
如果初始化时设置了 auto_set_bg_opt = true,弹窗关闭时会自动将用户调节好的值写回触发它的那个列表选项的 val 成员。
也可以在弹窗的回调函数中,通过访问页面结构体的 val 成员获取最终值。
ListWin: 在回调函数中检查 sel_str_index 获取用户选择的列表项索引。
7.7 配置 UI 参数 (进阶)
可以通过修改全局结构体变量 g_default_ui_para 中的成员来调整 UI 的一些默认视觉和行为参数。这些修改通常放在 TestUI_Init() 函数的开头,页面初始化之前。
// 在 TestUI_Init() 开头
void TestUI_Init() {
// 示例:加快列表动画速度 (数值越小越快)
g_default_ui_para.ani_param[LIST_ANI] = 150;
// 示例:禁用列表页的循环滚动模式
g_default_ui_para.loop_param[LIST_LOOP] = 0; // 0 表示禁用
// 示例:修改弹窗背景模糊程度 (数值越大越模糊?)
g_default_ui_para.blur_param = 5;
// ... 然后开始初始化页面 ...
// WouoUI_ListPageInit(...);
}
可配置的参数包括动画速度、循环模式、各种边距、字体、颜色、模糊效果等,具体可查阅 WouoUI_common.h
中 UI_Params 结构体的定义。
7.8 主循环集成
在你的应用程序主循环 (例如 main
函数的 while(1)
或 RTOS 任务循环) 中,需要确保以下几点:
获取用户输入: 持续检测按键状态(或其他输入方式)。
发送消息: 当检测到有效的用户操作时,将其转换为对应的 InputMsg,并使用 WOUOUI_MSG_QUE_SEND(msg) 发送给 WouoUI。
处理 UI: 周期性地调用 WouoUI_Proc(delta_time) 函数。delta_time 是两次调用之间经过的时间(毫秒),用于动画和时间相关的处理。
#include “WouoUI.h”
#include “key_driver.h” // 假设你的按键驱动接口在这里
#include “timing.h” // 假设你的计时函数在这里
uint32_t last_tick = 0; // 用于计算时间间隔
int main(void) {
// … 系统初始化 …
Application_Init(); // 执行之前的 WouoUI 和硬件初始化
last_tick = Get_System_Millis(); // 获取初始时间
while (1) {
// --- 1. 获取用户输入 ---
InputMsg current_msg = Get_Mapped_UserInput(); // 返回 WouoUI 定义的 InputMsg
// --- 2. 发送消息 ---
if (current_msg != msg_none) {
WOUOUI_MSG_QUE_SEND(current_msg);
}
// --- 3. 计算时间间隔 ---
uint32_t current_tick = Get_System_Millis();
uint16_t delta_time = current_tick - last_tick;
// 防止时间戳回绕或 delta_time 过大 (根据实际情况调整阈值)
if (delta_time == 0 || delta_time > 500) {
delta_time = 10; // 提供一个默认或最小间隔
}
last_tick = current_tick;
// --- 4. 处理 UI ---
// 可以直接在主循环调用,也可以如前所述放在定时中断或任务中
WouoUI_Proc(delta_time);
// ... 其他主循环任务 ...
}
}
// — 示例:按键输入映射函数 —
InputMsg Get_Mapped_UserInput() {
if (Is_KeyUp_Pressed_Event()) return msg_up;
if (Is_KeyDown_Pressed_Event()) return msg_down;
if (Is_KeyLeft_Pressed_Event()) return msg_left;
if (Is_KeyRight_Pressed_Event()) return msg_right;
if (Is_KeyConfirm_Pressed_Event()) return msg_click;
if (Is_KeyBack_Pressed_Event()) return msg_return;
return msg_none; // 没有有效按键事件
}
7.9 简单示例回顾
结合以上步骤,一个最简单的应用流程如下:
硬件和 WouoUI 初始化: 在 Application_Init()
中完成屏幕驱动初始化、绑定 OLED_SendBuff
、调用 TestUI_Init
。
定义页面和选项: 在 WouoUI_user.c/.h
中定义你的页面实例(如 main_page
, settings_list_page
)、选项数组 (Option settings_options[] = {…}) 和页面回调函数 (SettingsListPage_CallBack)。
初始化页面: 在 WouoUI_user.c
的 TestUI_Init()
函数中,调用 WouoUI_ListPageInit()
, WouoUI_TitlePageInit()
等函数创建页面实例,设置主页,注册共用弹窗。
主循环:
检测按键输入 -> Get_Mapped_UserInput()
发送 WouoUI 消息 -> WOUOUI_MSG_QUE_SEND()
处理 UI 状态和渲染 -> WouoUI_Proc()
页面逻辑: 在页面的回调函数中,响应 msg_click
和 msg_return
,根据选中的选项 WouoUI_ListTitlePageGetSelectOpt()
,使用 WouoUI_JumpToPage()
进行页面切换或弹出窗口,或者执行其他应用逻辑。
希望这份详细的应用开发指南能帮助你更好地使用 WouoUI-Page 框架构建嵌入式菜单系统!如有疑问,请仔细阅读 WouoUI 源码中的注释,并参考其提供的 WouoUI_user.c
示例代码。
©