LVGL-mainwindow.c

该代码实现了一个基于LVGL图形库的GUI桌面系统,包括主窗口、图标加载、事件回调和桌面页面管理。它通过结构体数组存储不同页面的图标信息,使用链表管理按钮对象,并根据用户点击调用相应的应用程序。此外,系统还包含了状态栏的更新任务,用于显示时间和电池信息。
摘要由CSDN通过智能技术生成
/*
* 文件名称 : 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);

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值