概述
消息框表现为一种弹出式的用户界面元素。当需要向用户显示信息、警告或请求确认时,会暂时覆盖部分或全部屏幕以展示消息内容。
消息框中的文本内容能够自动换行以适应空间大小,并且消息框的高度会根据实际包含的文本内容及按钮数量自动调整,确保所有内容都被适当地显示在框内。
消息框具有两种模式:
- 模态:消息框会阻止用户点击屏幕上的其他区域,直到用户对消息框做出响应为止。
- 非模态:用户可以在查看消息的同时操作界面的其他部分,不会被消息框阻断交互。
包含组件元素
消息框的各个组成部分:
- 背景:是一个基本的对象容器 lv_obj,它为消息框提供了基础的布局和样式设定。
- 关闭按钮:如果消息框包含了关闭按钮,该按钮是通过 lv_btn 对象实现的。
- 标题与文本:消息框中的标题和正文内容都是使用 lv_label 组件来显示的。
- 按钮:消息框底部用于用户交互的一系列按钮是由 lv_btnmatrix 组件构建的。lv_btnmatrix 允许创建多列按钮,并可以对单个按钮进行独立的样式和功能设置。
使用示例
// 消息框事件处理器
void msgbox_event_handler(lv_event_t *event)
{
lv_event_code_t code = lv_event_get_code(event);
lv_obj_t * mbox = lv_event_get_current_target(event);
if(code == LV_EVENT_VALUE_CHANGED)
{
// 获取被点击的按钮索引
int active_btn_index = lv_msgbox_get_active_btn(mbox);
// 获取被点击的按钮文本
const char * active_btn_text = lv_msgbox_get_active_btn_text(mbox);
cout << active_btn_text <<std::endl;
// 根据点击的按钮进行相应操作
if(strcmp(active_btn_text, "Ok") == 0)
{
LV_LOG_USER("Ok button clicked.\n");
}
else if(strcmp(active_btn_text, "Cancel") == 0)
{
LV_LOG_USER("Cancel button clicked.\n");
lv_msgbox_close(mbox);// 如果需要,可以在此处关闭消息框
}
}
}
int main(int argc, char **argv)
{
lv_init();
hal_init();
lv_log_register_print_cb(esp32_log_cb);
{
static const char * btns[] = {"Ok", "Cancel", ""};
lv_obj_t * mbox = lv_msgbox_create(lv_scr_act(), "Title", "This is a message box.", btns, true);
lv_obj_add_event_cb(mbox, msgbox_event_handler, LV_EVENT_ALL, NULL);
lv_obj_center(mbox);
}
while (1)
{
lv_task_handler();
usleep(5 * 1000);
}
return 0;
}
当点击消息框中的任意一个按钮时,该按钮会发送 LV_EVENT_VALUE_CHANGED 事件。在LVGL中,按钮矩阵的事件传播模式被设置为 LV_OBJ_FLAG_EVENT_BUBBLE,也就是即使事件首先由按钮触发,它也会向上传递到消息框本身。
在事件处理器中:
- 可以使用 lv_event_get_target(e) 获取触发事件的实际对象,即按钮矩阵。
- 可以使用 lv_event_get_current_target(e) 可以获取当前处理事件的目标对象,也就是消息框本身。
相关函数
1、lv_obj_t *lv_msgbox_create(lv_obj_t *parent, const char *title, const char *txt, const char *btn_txts[], bool add_close_btn);
创建一个消息框对象的函数。
- parent:指向父容器对象的指针,如果传入 NULL,则会创建一个全屏模态的消息框。
- title:消息框标题。
- txt:消息框正文文本。
- btn_txts:按钮文本数组,数组中的每个元素代表一个按钮上的文本,数组以空字符串 ("") 结束。例如:{"Yes", "No", ""} 表示创建两个按钮,分别标注为“是”和“否”。
- add_close_btn:是否要在消息框上添加一个关闭按钮。
全屏模态消息框:
2、lv_obj_t *lv_msgbox_get_title(lv_obj_t *obj)
获取消息框的标题对象。通过这个指针可以修改标题内容、样式等属性。
3、lv_obj_t *lv_msgbox_get_close_btn(lv_obj_t *obj)
获取消息框上的关闭按钮对象。可以使用这个指针对关闭按钮进行事件绑定或样式调整等操作。
4、lv_obj_t *lv_msgbox_get_text(lv_obj_t *obj)
获取消息框主体文本区域的对象(lv_label)。可以使用它更改或获取消息框内的详细文本信息。
5、lv_obj_t *lv_msgbox_get_content(lv_obj_t *obj)
获取消息框的内容对象。使用它可以自定义内容布局或其他操作。
static const char * btns[] = {"Ok", "Cancel", ""};
lv_obj_t * mbox = lv_msgbox_create(lv_scr_act(), "Title", "", btns, true);
lv_obj_add_event_cb(mbox, msgbox_event_handler, LV_EVENT_ALL, NULL);
lv_obj_center(mbox);
lv_obj_t *content_area = lv_msgbox_get_content(mbox);
// 在内容区域内添加自定义对象(例如:一个标签)
lv_obj_t *custom_label = lv_label_create(content_area);
lv_label_set_text(custom_label, "Custom text added to the content area.");
lv_obj_set_width(custom_label,250);
6、lv_obj_t *lv_msgbox_get_btns(lv_obj_t *obj)
获取消息框底部按钮矩阵对象(lv_btnmatrix)。使用它可以访问和控制消息框的所有按钮,包括但不限于添加事件处理器、修改按钮文字或样式等。
7、uint16_t lv_msgbox_get_active_btn(lv_obj_t *mbox)
获取消息框中当前被选中的按钮的索引。
返回当前被选中的按钮在按钮矩阵中的索引。如果没有任何按钮被选中,则返回 LV_BTNMATRIX_BTN_NONE。
8、const char *lv_msgbox_get_active_btn_text(lv_obj_t *mbox)
获取消息框中当前被选中的按钮的文本。
9、void lv_msgbox_close(lv_obj_t *mbox)
关闭并删除指定的消息框对象。执行此操作后,消息框将从屏幕上消失,并且与之相关的资源会被释放。
10、void lv_msgbox_close_async(lv_obj_t *mbox)
用于关闭指定的消息框对象,并且是以异步的方式进行的。异步函数意味着函数会立即返回,而不会等待关闭操作完成。这样可以避免在操作过程中堵塞用户界面。
当调用此函数时,它并不会立即删除并释放与消息框相关的资源,而是将关闭消息框的操作放入到事件队列中,使其在下一个事件处理周期执行。这样可以避免在当前UI更新过程中直接销毁消息框导致的界面刷新异常或其他潜在问题。
bool need_create_popup = false;
lv_obj_t *msgbox_closed_popup;
// 定义一个定时器回调函数,用于延迟关闭弹出窗口
static void close_popup_timer_cb(lv_timer_t *timer)
{
// 关闭弹出窗口
need_create_popup = false;
lv_msgbox_close_async(msgbox_closed_popup);
lv_timer_del(timer); // 删除定时器
}
// 定义一个定时器回调函数,用于延迟创建新的弹出窗口
static void create_popup_timer_cb(lv_timer_t *timer)
{
// 创建新的弹出窗口
static const char * btns[] = {""};
msgbox_closed_popup = lv_msgbox_create(lv_scr_act(), "notice", "Message box closed", btns, false);
lv_obj_center(msgbox_closed_popup);
lv_obj_add_flag(msgbox_closed_popup, LV_OBJ_FLAG_HIDDEN);//隐藏对象
lv_timer_del(timer);// 删除定时器
need_create_popup = true;
// 创建一个定时器,延迟三秒后关闭弹出窗口
lv_timer_create(close_popup_timer_cb, 3000, NULL);
}
// 消息框事件处理器
void msgbox_event_handler(lv_event_t *event)
{
lv_event_code_t code = lv_event_get_code(event);
if(code == LV_EVENT_VALUE_CHANGED)
{
lv_obj_t * mbox = lv_event_get_current_target(event);
const char * active_btn_text = lv_msgbox_get_active_btn_text(mbox);// 获取被点击的按钮文本
// 根据点击的按钮进行相应操作
if(strcmp(active_btn_text, "Ok") == 0)
{
LV_LOG_USER("Ok button clicked.\n");
}
else if(strcmp(active_btn_text, "Cancel") == 0)
{
LV_LOG_USER("Cancel button clicked.\n");
lv_msgbox_close_async(mbox);
lv_timer_create(create_popup_timer_cb, 200, NULL);
}
}
}
int main(int argc, char **argv)
{
lv_init();
hal_init();
lv_log_register_print_cb(esp32_log_cb);
{
static const char * btns[] = {"Ok", "Cancel", ""};
lv_obj_t * mbox = lv_msgbox_create(lv_scr_act(), "Title", "this is msg", btns, true);
lv_obj_add_event_cb(mbox, msgbox_event_handler, LV_EVENT_ALL, NULL);
lv_obj_center(mbox);
}
// ProjectManager_Run_Lvgl::getInstance()->openProject();
while (1)
{
lv_task_handler();
usleep(5 * 1000);
if(need_create_popup)
{
lv_obj_clear_flag(msgbox_closed_popup, LV_OBJ_FLAG_HIDDEN);//取消隐藏
need_create_popup = false;
}
}
return 0;
}