/*
* 文件名称 : mainwindow.c
*
* 背景利用图片填充,在图片上面的全屏控件设置为透明,避免遮挡背景
* 主页ICON加载方式,用结构体保存图像指针,文本指针,图像存储路径指针,app函数指针
* 用一个数组保存每个icon的结构体信息
* 上电从SD卡根据图像存储路径指针加载图像到图像指针
* 指定一个父对象,依次创建按钮往按钮添加图片和文字达到icon的效果,共3个页面
* 所有icon的事件回调函数公用一个,创建的按钮的返回对象利用链表保存,在事件回调函数中遍历链表找到索引
* 根据索引找到对应的结构体数组,执行相应的APP函数
* APP函数默认带有一个void*的形参,暂未使用
* 创建一个任务定时更新状态栏信息
* 用户添加APP只需要在对应页面的保存信息的数组中添加APP相关的参数即可(图像指针,文本,文件名,函数)
* 191230 图片文件改为从gui_user.c进行加载,在mainwindow里面会检查资源加载的返回结果,未正确加载不进入桌面
*
*/
/* 头文件 -----------------------------------------------------------*/
#include "gui_user.h"
/**
* @brief APP空函数
* @param user_data-自定义数据
* @retval None
*/
lv_obj_t * app_null(lv_obj_t *parent, void *user_data)
{
(void)user_data;
(void)parent;
//printf("\napp1\n");
//message_box(lv_scr_act(), "抱歉,您的设备暂时不支持该功能");
message_box_win(lv_scr_act(), LV_SYMBOL_WARNING"ERROR", "抱歉, 您的设备暂时不支持该功能请联系管理员","确定",NULL);
return NULL;
}
/* 桌面的ICON信息定义 */
static const icon_item icon_desktop_page1[] =
{
{ &icon_tiaotu, "Tiaotu", "跳兔", app_tiaotu_create },
#if 0
{ &icon_led, "LED", "灯光", app_led_create },
{ &icon_key, "KEY", "按键", app_key_create },
{ &icon_beep, "BEEP", "蜂鸣", app_beep_create },
{ &icon_album, "ALBUM", "相册 ", app_null },
{ &icon_wireless, "WIRELESS", "无线", app_null },
{ &icon_wechat, "Wechat", "微信", app_wechat_create },
{ &icon_wifi, "WIFI", "WIFI", app_wlan_create },
{ &icon_weather, "Weather", "天气", app_weather_create },
{ &icon_set, "Set", "设置", app_set_create },
{ &icon_folder, "Folder", "文件", app_null },
{ &icon_note, "Note", "日记", app_null },
{ &icon_nbiot, "NB", "NB-IOT", app_nb_iot_create },
{ &icon_touchpad, "TouchPad", "画板", app_touchpad_create },
#endif
//{ &icon_onenet, "OneNet", "OneNet", app_null },
};
static const icon_item icon_desktop_page2[] =
{
{ &icon_mall, "Mall", "商城", app_null},
{ &icon_light, "Light", "光照", app_light_create },
{ &icon_temp, "Temperature", "温度", app_temperature_create },
};
static const icon_item icon_desktop_page3[] =
{
{ &icon_ir, "IR", "红外", app_ir_create },
{ &icon_triaxial, "Triaxial", "三轴", app_null },
};
/* 保存icon的对象的链表结构 */
typedef struct icon_obj
{
lv_obj_t *obj;
struct icon_obj *next;
}_icon_obj_list;
/* 链表表头定义 */
_icon_obj_list *icon_obj_list = NULL;
/* 全局对象指针定义 */
static lv_obj_t *label_header_device_name;
static lv_obj_t *label_header_time;
static lv_obj_t *label_header_ele;
static lv_obj_t *label_header_wlan;
static lv_obj_t *label_header_sysclk;
static lv_obj_t *label_device_vendor;
static lv_style_t style_label_ele;
static uint8_t *label_ele_array[5] = { LV_SYMBOL_BATTERY_EMPTY, LV_SYMBOL_BATTERY_1, LV_SYMBOL_BATTERY_2, LV_SYMBOL_BATTERY_3, LV_SYMBOL_BATTERY_FULL };
static uint8_t *label_ele_array_chrg[5] = { LV_SYMBOL_CHARGE LV_SYMBOL_BATTERY_EMPTY, LV_SYMBOL_CHARGE LV_SYMBOL_BATTERY_1, LV_SYMBOL_CHARGE LV_SYMBOL_BATTERY_2, LV_SYMBOL_CHARGE LV_SYMBOL_BATTERY_3, LV_SYMBOL_CHARGE LV_SYMBOL_BATTERY_FULL };
static const uint8_t device_vendor[] = { "跳兔科技" };
static const uint8_t device_name[] = { "野牛STM32" };
static uint8_t time_buf[6] = { 0 };
static uint8_t clk_buf[11] = { 0 };
static uint8_t gui_wlan_status = 0;
gui_theme gui_current_theme;
void lv_create_desktop(void);
void lv_load_icon_desktop(icon_item *item, uint16_t icon_num);
void lv_create_icon_desktop(lv_obj_t *parent, icon_item *item, uint16_t icon_num, lv_event_cb_t icon_event_cb);
static void mainwindow_update_task(lv_task_t *t);
static void gui_hal_message_hander(uint8_t *buffer);
lv_obj_t *label_info;
/**
* @brief 用户GUI主函数
* @param None
* @retval None
* @note 此函数一定要返回,禁止死循环
*/
void lv_app_main(void)
{
gui_setting gui_init_setting;
gui_hal_setting_read(&gui_init_setting);
uint8_t bg_fname_buf[32] = { 0 };
/* 先加载一些文字然后加载字库和图片资源 */
static lv_style_t style_label_info;
lv_style_copy(&style_label_info, &lv_style_scr);
style_label_info.text.color = LV_COLOR_BLUE;
style_label_info.text.font = &lv_font_roboto_28;
lv_obj_t *label_info = lv_label_create(lv_scr_act(), NULL);
lv_label_set_style(label_info, LV_LABEL_STYLE_MAIN, &style_label_info);
lv_label_set_text(label_info, "Bison-Board\n" LV_SYMBOL_DOWNLOAD " Load Resources...\n From Tiaotu Technology\nwww.whtiaotu.com");
lv_label_set_align(label_info, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label_info, NULL, LV_ALIGN_CENTER, 0, -50);
lv_task_handler(); //进行一次任务调度让label先显示出来
if (lv_load_user_font_from_file() != 0)
{
lv_label_set_text(label_info, LV_SYMBOL_WARNING " Load Resources Error!!!\nwww.whtiaotu.com");
lv_obj_realign(label_info);
lv_task_handler();
return;
}
if (lv_load_user_img_from_file() != 0)
{
lv_label_set_text(label_info, LV_SYMBOL_WARNING " Load Resources Error!!!\nwww.whtiaotu.com");
lv_obj_realign(label_info);
lv_task_handler();
return;
}
lv_font_cn_style_init();
sprintf((char*)bg_fname_buf, "0:/lvgl/bg%02d.bin", gui_init_setting.wallpaper_index);
lv_load_img_bin_from_file(&img_desktop, (const char*)bg_fname_buf);
gui_current_theme = (gui_theme)gui_init_setting.theme_index;
/* 设置主题 */
switch (gui_current_theme)
{
/* 索引跟主题的顺序不要随便改,涉及到配色 */
case THEME_MATERIAL:
lv_theme_set_current(lv_theme_material_init(210, NULL));
break;
case THEME_NIGHT:
lv_theme_set_current(lv_theme_night_init(210, NULL));
break;
case THEME_ALIEN:
lv_theme_set_current(lv_theme_alien_init(210, NULL));
break;
case THEME_ZEN:
lv_theme_set_current(lv_theme_zen_init(210, NULL));
break;
case THEME_NEMO:
lv_theme_set_current(lv_theme_nemo_init(210, NULL));
break;
case THEME_MONO:
lv_theme_set_current(lv_theme_mono_init(210, NULL));
break;
case THEME_DEFAULT:
lv_theme_set_current(lv_theme_default_init(210, NULL));
break;
case THEME_TEMPL:
lv_theme_set_current(lv_theme_templ_init(210, NULL));
break;
}
/* 创建桌面 */
lv_create_desktop();
//lv_task_create(mainwindow_update_task,10,LV_TASK_PRIO_LOW,NULL);
lv_task_ready(lv_task_create(mainwindow_update_task, 10, LV_TASK_PRIO_LOW, NULL));
/* 调试用的 */
//app_temperature_create(lv_scr_act(), NULL);
}
/**
* @brief ICON的事件回调函数
* @param obj-触发事件的对象
* @param event-事件类型
* @retval None
* @note 根据对象找链表中的索引,根据索引执行APP
*/
static void icon_obj_event_cb(lv_obj_t * obj, lv_event_t event)
{
if (event == LV_EVENT_RELEASED)
{
uint16_t index = 0;
_icon_obj_list *p = icon_obj_list;
while (p)
{
if (p->obj == obj)
{
break;
}
index++;
p = p->next;
}
uint8_t icon_num_page1, icon_num_page2;
icon_num_page1 = sizeof(icon_desktop_page1) / sizeof(icon_desktop_page1[0]);
icon_num_page2 = sizeof(icon_desktop_page2) / sizeof(icon_desktop_page2[0]);
if (index < icon_num_page1)
{
/* 第一个页面 */
//printf("page1\n");
current_app_obj_user = icon_desktop_page1[index].app(lv_scr_act(), NULL);
}
else if ((index < icon_num_page1 + icon_num_page2))
{
/* 第二个页面 */
//printf("page2\n");
current_app_obj_user = icon_desktop_page2[index - icon_num_page1].app(lv_scr_act(), NULL);
}
else
{
/* 第三个界面 */
//printf("page3\n");
current_app_obj_user = icon_desktop_page3[index - icon_num_page1 - icon_num_page2].app(lv_scr_act(), NULL);
}
//printf("index:%d\r\n", index);
}
}
/**
* @brief 追加list
* @param obj-list对象
* @retval None
* @note 在链表结尾添加
*/
void icon_obj_list_append(lv_obj_t *obj)
{
if (icon_obj_list == NULL)
{
icon_obj_list = (_icon_obj_list*)lv_mem_alloc(sizeof(_icon_obj_list));
icon_obj_list->next = NULL;
icon_obj_list->obj = obj;
}
else
{
_icon_obj_list *p = icon_obj_list;
_icon_obj_list *node;
node = (_icon_obj_list*)lv_mem_alloc(sizeof(_icon_obj_list));
while (p)
{
if (p->next == NULL)
{
p->next = node;
node->next = NULL;
node->obj = obj;
}
p = p->next;
}
}
}
/**
* @brief 更新顶部状态栏信息
* @param t-任务指针
* @retval None
*/
static void mainwindow_update_task(lv_task_t *t)
{
(void)t;
static uint16_t tick = 0;
static gui_rtc_date_time date_time;
static uint8_t mq_rec_bufffer[MQ_MAX_LEN] = { 0 };
static uint8_t memory_cpuusage_buf[32] = { 0 };
static uint8_t ele = 0;
static uint8_t last_ele = 0;
bool chrg = false;
bool stdby = false;
if (gui_hal_message_recv(mq_rec_bufffer, MQ_MAX_LEN) == 0)
{
gui_hal_message_hander(mq_rec_bufffer);
}
if (tick == 0)
{
tick = 100;
gui_hal_get_time(&date_time);
if (date_time.Seconds % 2)
sprintf((char*)time_buf, "%02d %02d", date_time.Hours, date_time.Minutes);
else
sprintf((char*)time_buf, "%02d:%02d", date_time.Hours, date_time.Minutes);
lv_label_set_text(label_header_time, (const char*)time_buf);
if (gui_wlan_status)
lv_label_set_text(label_header_wlan, LV_SYMBOL_WIFI);
else
lv_label_set_text(label_header_wlan, "");
gui_hal_bat_get(&ele, &stdby, &chrg);
if (abs(ele - last_ele) >= 2)
{
last_ele = ele;
if (last_ele >= 100)
last_ele = 99;
}
if (last_ele < 20)
style_label_ele.text.color = LV_COLOR_RED;
else
style_label_ele.text.color = LV_COLOR_WHITE;
if (chrg == true) //正在充电
lv_label_set_text(label_header_ele, (const char*)label_ele_array_chrg[last_ele / 20]);
else if (stdby == true) //充满
{
style_label_ele.text.color = lv_color_hex(0x03d005);
lv_label_set_text(label_header_ele, (const char*)label_ele_array_chrg[last_ele / 20]);
}
else
lv_label_set_text(label_header_ele, (const char*)label_ele_array[last_ele / 20]);
lv_obj_realign(label_header_ele);
}
tick--;
}
static void gui_hal_message_hander(uint8_t *buffer)
{
switch (buffer[0])
{
case GUI_MQ_KEY:
//printf("key:%d",buffer[1]);
if (current_app_obj_user != NULL)
{
lv_event_send(current_app_obj_user, LV_EVENT_KEY, (const void *)buffer[1]);
}
break;
case GUI_MQ_WLAN_STATUS:
gui_wlan_status = buffer[1];
//printf("gui_wlan_status:%d", gui_wlan_status);
break;
case GUI_MQ_MPU_UPDATA:
break;
default:
break;
}
}
/**
* @brief 创建桌面
* @param None
* @retval None
*/
void lv_create_desktop(void)
{
/* 新建个样式 */
static lv_style_t style_desktop;
static lv_style_t style_tabview;
static lv_style_t style_label;
static lv_style_t style_label_1; /* 符号字体用 */
static lv_style_t style_label_2; /* 小字体用 */
lv_style_copy(&style_desktop, &lv_style_scr);
style_desktop.body.main_color = LV_COLOR_WHITE; /* 设置底色 */
style_desktop.body.grad_color = LV_COLOR_WHITE; /* 设置渐变色 */
/* 设置样式的字体颜色 */
style_cn_12.text.color = LV_COLOR_WHITE;
style_cn_16.text.color = LV_COLOR_WHITE;
style_cn_24.text.color = LV_COLOR_WHITE;
style_cn_32.text.color = LV_COLOR_WHITE;
lv_obj_t *scr = lv_disp_get_scr_act(NULL); /* 获取当前屏幕 */
lv_obj_set_style(scr, &style_desktop); /* 设置样式 */
lv_obj_t *img_bg = lv_img_create(scr, NULL);
lv_img_set_src(img_bg, &img_desktop);
lv_obj_t *tabview = lv_tabview_create(scr, NULL);
lv_tabview_set_btns_hidden(tabview, true);
lv_style_copy(&style_tabview, lv_tabview_get_style(tabview, LV_TABVIEW_STYLE_BG));
style_tabview.body.opa = 0; // 背景利用图片填充,在图片上面的全屏控件设置为透明,避免遮挡背景
lv_tabview_set_style(tabview, LV_TABVIEW_STYLE_BG, &style_tabview);
lv_tabview_set_anim_time(tabview, 10);
lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Tab 1");
lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Tab 2");
lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Tab 3");
lv_page_set_sb_mode(tab1, LV_SB_MODE_OFF);
#if 1
lv_page_set_sb_mode(tab2, LV_SB_MODE_OFF);
lv_page_set_sb_mode(tab3, LV_SB_MODE_OFF);
lv_create_icon_desktop(tab1, (icon_item*)icon_desktop_page1, sizeof(icon_desktop_page1) / sizeof(icon_desktop_page1[0]), icon_obj_event_cb);
#if 0 // richard
lv_create_icon_desktop(tab2, (icon_item*)icon_desktop_page2, sizeof(icon_desktop_page2) / sizeof(icon_desktop_page2[0]), icon_obj_event_cb);
lv_create_icon_desktop(tab3, (icon_item*)icon_desktop_page3, sizeof(icon_desktop_page3) / sizeof(icon_desktop_page3[0]), icon_obj_event_cb);
#endif
lv_style_copy(&style_label, &lv_style_pretty);
#if 1
style_label.text.font = style_cn_16.text.font;
style_label.text.color = LV_COLOR_WHITE;
style_label.body.opa = LV_OPA_50;
style_label.body.border.width = 0;
style_label.body.radius = 0;
style_label.body.main_color = LV_COLOR_BLUE;
style_label.body.grad_color = LV_COLOR_BLUE;
lv_style_copy(&style_label_ele, &lv_style_scr);
lv_style_copy(&style_label_1, &style_label);
lv_style_copy(&style_label_2, &style_label);
style_label_1.text.font = &lv_font_roboto_28;
style_label_2.text.font = &lv_font_roboto_22;
style_label_ele.text.font = &lv_font_roboto_28;
style_label_ele.text.color = LV_COLOR_WHITE;
lv_obj_t *count = lv_cont_create(scr, NULL);
lv_obj_set_size(count, LV_HOR_RES, 32);
lv_cont_set_style(count, LV_CONT_STYLE_MAIN, &style_label);
label_header_device_name = lv_label_create(count, NULL);
lv_label_set_style(label_header_device_name, LV_LABEL_STYLE_MAIN, &style_label);
lv_label_set_static_text(label_header_device_name, device_name);
lv_obj_align(label_header_device_name, count, LV_ALIGN_IN_TOP_LEFT, 0, 2);
label_header_time = lv_label_create(count, NULL);
lv_label_set_style(label_header_time, LV_LABEL_STYLE_MAIN, &style_label_2);
lv_label_set_text(label_header_time, " ");
lv_obj_align(label_header_time, count, LV_ALIGN_IN_TOP_MID, 0, 6);
label_header_wlan = lv_label_create(count, NULL);
lv_label_set_style(label_header_wlan, LV_LABEL_STYLE_MAIN, &style_label_1);
lv_label_set_text(label_header_wlan, "");
lv_obj_align(label_header_wlan, label_header_time, LV_ALIGN_OUT_RIGHT_MID, 130, 0);
label_header_ele = lv_label_create(count, label_header_device_name);
lv_label_set_style(label_header_ele, LV_LABEL_STYLE_MAIN, &style_label_ele);
lv_label_set_recolor(label_header_ele, true);
lv_label_set_text(label_header_ele, LV_SYMBOL_BATTERY_1);
lv_obj_align(label_header_ele, count, LV_ALIGN_IN_TOP_RIGHT, -5, 2);
sprintf((char*)clk_buf, "CLK:%dM", gui_hal_get_sysclk()/1000/1000);
label_header_sysclk = lv_label_create(count, NULL);
lv_label_set_style(label_header_sysclk, LV_LABEL_STYLE_MAIN, &style_label_2);
lv_label_set_text(label_header_sysclk, (char*)clk_buf);
lv_obj_align(label_header_sysclk, count, LV_ALIGN_CENTER, 90, 2);
label_device_vendor = lv_label_create(count, NULL);
lv_label_set_style(label_device_vendor, LV_LABEL_STYLE_MAIN, &style_label);
lv_label_set_static_text(label_device_vendor, device_vendor);
lv_obj_align(label_device_vendor, count, LV_ALIGN_IN_TOP_LEFT, 124, 2);
#endif
#endif
}
/**
* @brief 创建ICON
* @param parent-父对象
* @param item-保存ICON信息的数组
* @param icon_num-数量
* @param icon_event_cb-事件回调函数
* @retval None
* @note 所有ICON公用一个事件回调函数
*/
void lv_create_icon_desktop(lv_obj_t *parent, icon_item *item, uint16_t icon_num, lv_event_cb_t icon_event_cb)
{
uint16_t i = 0;
uint16_t x_pos = 0, y_pos = 0;
static lv_style_t style_label;
lv_style_copy(&style_label, &lv_style_pretty);
style_label.text.font = style_cn_16.text.font;
x_pos = 32;
y_pos = 40;
printf("icon_num = %d\n", icon_num);
for (i = 0; i < icon_num; ++i)
{
x_pos = ((i % 4) * 120) + 10;
y_pos = ((i / 4) * 120) + 32;
lv_obj_t *btn = lv_btn_create(parent, NULL);
lv_obj_t *image = lv_img_create(btn, NULL);
lv_obj_t *label = lv_label_create(btn, NULL);
lv_obj_set_event_cb(btn, icon_event_cb);
icon_obj_list_append(btn);
lv_obj_set_pos(btn, x_pos, y_pos);
lv_obj_set_size(btn, 100, 120);
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &lv_style_transp);
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &lv_style_btn_ina);
lv_img_set_src(image, item[i].icon_img);
style_label.body.opa = 150;
style_label.body.border.width = 0;
lv_label_set_body_draw(label, true);
lv_label_set_style(label, LV_LABEL_STYLE_MAIN, &style_label);
lv_label_set_text(label, item[i].text_en);
lv_obj_align(label, btn, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
}
}
LVGL-mainwindow.c
于 2022-03-20 21:16:38 首次发布
该代码实现了一个基于LVGL图形库的GUI桌面系统,包括主窗口、图标加载、事件回调和桌面页面管理。它通过结构体数组存储不同页面的图标信息,使用链表管理按钮对象,并根据用户点击调用相应的应用程序。此外,系统还包含了状态栏的更新任务,用于显示时间和电池信息。
摘要由CSDN通过智能技术生成