第4部分:进阶应用与项目实战(下)
第13章:综合实战(一)- 设计一个智能家居控制面板UI
文章目录
- **第4部分:进阶应用与项目实战(下)**
- **第13章:综合实战(一)- 设计一个智能家居控制面板UI**
- **13.1 项目需求分析与架构设计**
- **13.1.1 功能需求分析**
- **13.1.2 UI架构设计**
- **13.2 创建主界面布局**
- **13.3 创建环境监控页面**
- **第14章:综合实战(二)- 为面板注入逻辑**
- **14.1 设备控制页面与事件处理**
- **14.2 场景管理与数据驱动**
- **14.3 数据持久化与状态管理**
- **14.4 应用初始化与主循环**
- **项目总结与扩展**
13.1 项目需求分析与架构设计
在本章中,我们将创建一个完整的智能家居控制面板。这个项目将综合运用我们之前学到的所有知识:布局、样式、事件处理、动画、图表和高级控件。
13.1.1 功能需求分析
我们的智能家居控制面板需要包含以下核心功能:
13.1.2 UI架构设计
基于功能需求,我们设计以下UI架构:
// 应用状态数据结构
typedef struct {
// 环境数据
float temperature;
float humidity;
float air_quality;
// 设备状态
struct {
bool living_room_light;
bool bedroom_light;
bool kitchen_light;
int light_brightness;
bool curtains_open;
int ac_temperature;
bool security_armed;
} devices;
// 场景状态
const char * current_scene;
// 能源数据
float power_consumption;
float energy_cost;
} smart_home_state_t;
static smart_home_state_t app_state = {
.temperature = 24.5f,
.humidity = 65.0f,
.air_quality = 85.0f,
.devices = {
.living_room_light = true,
.bedroom_light = false,
.kitchen_light = true,
.light_brightness = 75,
.curtains_open = true,
.ac_temperature = 24,
.security_armed = false
},
.current_scene = "居家模式",
.power_consumption = 2.3f,
.energy_cost = 1.2f
};
13.2 创建主界面布局
我们将使用Grid布局创建响应式的主界面:
#include <lvgl.h>
// 全局UI组件引用
typedef struct {
lv_obj_t * main_container;
lv_obj_t * header;
lv_obj_t * content_area;
lv_obj_t * sidebar;
lv_obj_t * status_bar;
} ui_components_t;
static ui_components_t ui;
/**
* 创建智能家居主界面
*/
void create_smart_home_ui() {
lv_obj_t * parent = lv_scr_act();
// 设置屏幕背景
lv_obj_set_style_bg_color(parent, lv_color_hex(0x1A2530), 0);
/********************
* 1. 定义主网格布局
********************/
// 列定义:侧边栏 | 主要内容区域
static lv_coord_t col_dsc[] = {
280, // 侧边栏固定宽度
LV_GRID_FR(1), // 主要内容区域占据剩余空间
LV_GRID_TEMPLATE_LAST
};
// 行定义:头部 | 内容区域 | 状态栏
static lv_coord_t row_dsc[] = {
80, // 头部高度
LV_GRID_FR(1), // 内容区域
60, // 状态栏高度
LV_GRID_TEMPLATE_LAST
};
// 创建主容器
ui.main_container = lv_obj_create(parent);
lv_obj_set_size(ui.main_container, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_bg_opa(ui.main_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(ui.main_container, 0, 0);
lv_obj_set_style_pad_all(ui.main_container, 0, 0);
lv_obj_set_grid_dsc_array(ui.main_container, col_dsc, row_dsc);
/********************
* 2. 创建头部区域
********************/
create_header_area();
/********************
* 3. 创建侧边栏
********************/
create_sidebar();
/********************
* 4. 创建内容区域
********************/
create_content_area();
/********************
* 5. 创建状态栏
********************/
create_status_bar();
}
/**
* 创建头部区域
*/
void create_header_area() {
// 头部占据第一行,跨越两列
ui.header = lv_obj_create(ui.main_container);
lv_obj_set_style_bg_color(ui.header, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_border_width(ui.header, 0, 0);
lv_obj_set_style_radius(ui.header, 0, 0);
lv_obj_set_grid_cell(ui.header,
LV_GRID_ALIGN_STRETCH, 0, 2,
LV_GRID_ALIGN_STRETCH, 0, 1
);
// 头部内容使用Flex布局
lv_obj_set_flex_flow(ui.header, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(ui.header, LV_FLEX_ALIGN_SPACE_BETWEEN,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_hor(ui.header, 30, 0);
// 左侧:Logo和标题
lv_obj_t * title_container = lv_obj_create(ui.header);
lv_obj_set_size(title_container, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(title_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(title_container, 0, 0);
lv_obj_set_flex_flow(title_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(title_container, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * logo = lv_label_create(title_container);
lv_label_set_text(logo, "🏠");
lv_obj_set_style_text_font(logo, &lv_font_montserrat_24, 0);
lv_obj_t * title = lv_label_create(title_container);
lv_label_set_text(title, "智能家居控制中心");
lv_obj_set_style_text_color(title, lv_color_white(), 0);
lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
lv_obj_set_style_pad_left(title, 10, 0);
// 右侧:用户信息和通知
lv_obj_t * user_container = lv_obj_create(ui.header);
lv_obj_set_size(user_container, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(user_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(user_container, 0, 0);
lv_obj_set_flex_flow(user_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(user_container, LV_FLEX_ALIGN_END,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
// 通知图标
lv_obj_t * notification_btn = lv_btn_create(user_container);
lv_obj_set_size(notification_btn, 40, 40);
lv_obj_set_style_bg_opa(notification_btn, LV_OPA_0, 0);
lv_obj_set_style_border_width(notification_btn, 0, 0);
lv_obj_t * notification_icon = lv_label_create(notification_btn);
lv_label_set_text(notification_icon, LV_SYMBOL_BELL);
lv_obj_set_style_text_color(notification_icon, lv_color_white(), 0);
lv_obj_set_style_text_font(notification_icon, &lv_font_montserrat_18, 0);
lv_obj_center(notification_icon);
// 用户头像
lv_obj_t * user_avatar = lv_obj_create(user_container);
lv_obj_set_size(user_avatar, 45, 45);
lv_obj_set_style_bg_color(user_avatar, lv_color_hex(0x3498DB), 0);
lv_obj_set_style_radius(user_avatar, 22, 0);
lv_obj_set_style_pad_left(user_avatar, 15, 0);
lv_obj_t * avatar_text = lv_label_create(user_avatar);
lv_label_set_text(avatar_text, "用户");
lv_obj_set_style_text_color(avatar_text, lv_color_white(), 0);
lv_obj_set_style_text_font(avatar_text, &lv_font_montserrat_14, 0);
lv_obj_center(avatar_text);
}
/**
* 创建侧边栏导航
*/
void create_sidebar() {
// 侧边栏占据第二行第一列
ui.sidebar = lv_obj_create(ui.main_container);
lv_obj_set_style_bg_color(ui.sidebar, lv_color_hex(0x34495E), 0);
lv_obj_set_style_border_width(ui.sidebar, 0, 0);
lv_obj_set_style_radius(ui.sidebar, 0, 0);
lv_obj_set_grid_cell(ui.sidebar,
LV_GRID_ALIGN_STRETCH, 0, 1,
LV_GRID_ALIGN_STRETCH, 1, 1
);
// 侧边栏使用垂直Flex布局
lv_obj_set_flex_flow(ui.sidebar, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(ui.sidebar, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_all(ui.sidebar, 20, 0);
lv_obj_set_style_pad_gap(ui.sidebar, 10, 0);
// 导航菜单项
struct {
const char * icon;
const char * text;
const char * id;
} menu_items[] = {
{"📊", "环境监控", "environment"},
{"💡", "设备控制", "devices"},
{"🎭", "场景模式", "scenes"},
{"🔋", "能源管理", "energy"},
{"⚙️", "系统设置", "settings"},
};
for(int i = 0; i < sizeof(menu_items) / sizeof(menu_items[0]); i++) {
create_nav_item(ui.sidebar, menu_items[i].icon, menu_items[i].text, menu_items[i].id);
}
// 底部信息区域
create_sidebar_footer();
}
/**
* 创建导航菜单项
*/
void create_nav_item(lv_obj_t * parent, const char * icon, const char * text, const char * id) {
lv_obj_t * nav_btn = lv_btn_create(parent);
lv_obj_set_size(nav_btn, LV_PCT(100), 55);
lv_obj_set_style_bg_color(nav_btn, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_bg_color(nav_btn, lv_color_hex(0x3498DB), LV_STATE_CHECKED);
lv_obj_set_style_radius(nav_btn, 10, 0);
lv_obj_set_style_border_width(nav_btn, 0, 0);
lv_obj_add_flag(nav_btn, LV_OBJ_FLAG_CHECKABLE);
// 默认选中第一个菜单项
if(strcmp(id, "environment") == 0) {
lv_obj_add_state(nav_btn, LV_STATE_CHECKED);
}
// 内容容器
lv_obj_t * content = lv_obj_create(nav_btn);
lv_obj_set_size(content, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_bg_opa(content, LV_OPA_0, 0);
lv_obj_set_style_border_width(content, 0, 0);
lv_obj_set_flex_flow(content, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(content, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(content, 15, 0);
// 图标
lv_obj_t * icon_label = lv_label_create(content);
lv_label_set_text(icon_label, icon);
lv_obj_set_style_text_color(icon_label, lv_color_white(), 0);
lv_obj_set_style_text_font(icon_label, &lv_font_montserrat_18, 0);
// 文本
lv_obj_t * text_label = lv_label_create(content);
lv_label_set_text(text_label, text);
lv_obj_set_style_text_color(text_label, lv_color_white(), 0);
lv_obj_set_style_text_font(text_label, &lv_font_montserrat_16, 0);
lv_obj_set_style_pad_left(text_label, 15, 0);
// 存储菜单ID用于事件处理
lv_obj_set_user_data(nav_btn, (void*)id);
// 添加点击事件
lv_obj_add_event_cb(nav_btn, nav_item_click_handler, LV_EVENT_CLICKED, NULL);
}
/**
* 创建侧边栏底部信息
*/
void create_sidebar_footer() {
// 底部容器
lv_obj_t * footer = lv_obj_create(ui.sidebar);
lv_obj_set_size(footer, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(footer, LV_OPA_0, 0);
lv_obj_set_style_border_width(footer, 0, 0);
lv_obj_set_flex_flow(footer, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(footer, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_top(footer, 20, 0);
// 系统状态
lv_obj_t * status_title = lv_label_create(footer);
lv_label_set_text(status_title, "系统状态");
lv_obj_set_style_text_color(status_title, lv_color_hex(0xBDC3C7), 0);
lv_obj_set_style_text_font(status_title, &lv_font_montserrat_14, 0);
lv_obj_t * status_info = lv_label_create(footer);
lv_label_set_text(status_info, "✅ 所有系统正常");
lv_obj_set_style_text_color(status_info, lv_color_hex(0x2ECC71), 0);
lv_obj_set_style_text_font(status_info, &lv_font_montserrat_12, 0);
lv_obj_set_style_pad_top(status_info, 5, 0);
// 版本信息
lv_obj_t * version = lv_label_create(footer);
lv_label_set_text(version, "v2.1.0");
lv_obj_set_style_text_color(version, lv_color_hex(0x7F8C8D), 0);
lv_obj_set_style_text_font(version, &lv_font_montserrat_10, 0);
lv_obj_set_style_pad_top(version, 15, 0);
}
/**
* 创建内容区域
*/
void create_content_area() {
// 内容区域占据第二行第二列
ui.content_area = lv_obj_create(ui.main_container);
lv_obj_set_style_bg_color(ui.content_area, lv_color_hex(0x1A2530), 0);
lv_obj_set_style_border_width(ui.content_area, 0, 0);
lv_obj_set_style_radius(ui.content_area, 0, 0);
lv_obj_set_grid_cell(ui.content_area,
LV_GRID_ALIGN_STRETCH, 1, 1,
LV_GRID_ALIGN_STRETCH, 1, 1
);
// 初始化显示环境监控页面
create_environment_page();
}
/**
* 创建状态栏
*/
void create_status_bar() {
// 状态栏占据第三行,跨越两列
ui.status_bar = lv_obj_create(ui.main_container);
lv_obj_set_style_bg_color(ui.status_bar, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_border_width(ui.status_bar, 0, 0);
lv_obj_set_style_radius(ui.status_bar, 0, 0);
lv_obj_set_grid_cell(ui.status_bar,
LV_GRID_ALIGN_STRETCH, 0, 2,
LV_GRID_ALIGN_STRETCH, 2, 1
);
// 状态栏使用Flex布局
lv_obj_set_flex_flow(ui.status_bar, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(ui.status_bar, LV_FLEX_ALIGN_SPACE_BETWEEN,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_hor(ui.status_bar, 30, 0);
// 左侧:当前场景和连接状态
lv_obj_t * left_info = lv_obj_create(ui.status_bar);
lv_obj_set_size(left_info, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(left_info, LV_OPA_0, 0);
lv_obj_set_style_border_width(left_info, 0, 0);
lv_obj_set_flex_flow(left_info, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(left_info, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * scene_label = lv_label_create(left_info);
lv_label_set_text_fmt(scene_label, "当前场景: %s", app_state.current_scene);
lv_obj_set_style_text_color(scene_label, lv_color_white(), 0);
lv_obj_set_style_text_font(scene_label, &lv_font_montserrat_14, 0);
lv_obj_t * conn_status = lv_label_create(left_info);
lv_label_set_text(conn_status, " 🌐 已连接");
lv_obj_set_style_text_color(conn_status, lv_color_hex(0x2ECC71), 0);
lv_obj_set_style_text_font(conn_status, &lv_font_montserrat_12, 0);
lv_obj_set_style_pad_left(conn_status, 20, 0);
// 右侧:时间和日期
lv_obj_t * time_label = lv_label_create(ui.status_bar);
lv_label_set_text(time_label, "2024-06-15 14:30:25");
lv_obj_set_style_text_color(time_label, lv_color_white(), 0);
lv_obj_set_style_text_font(time_label, &lv_font_montserrat_14, 0);
// 更新时间显示
lv_timer_t * timer = lv_timer_create(update_time_display, 1000, time_label);
}
/**
* 导航菜单点击事件处理
*/
static void nav_item_click_handler(lv_event_t * e) {
lv_obj_t * target = lv_event_get_target(e);
const char * page_id = (const char *)lv_obj_get_user_data(target);
// 清除其他菜单项的选中状态
lv_obj_t * sibling = lv_obj_get_child(ui.sidebar, 0);
while(sibling) {
if(sibling != target && lv_obj_has_flag(sibling, LV_OBJ_FLAG_CHECKABLE)) {
lv_obj_clear_state(sibling, LV_STATE_CHECKED);
}
sibling = lv_obj_get_child(ui.sidebar, lv_obj_get_index(sibling) + 1);
}
// 设置当前菜单项为选中状态
lv_obj_add_state(target, LV_STATE_CHECKED);
// 根据ID切换到对应页面
if(strcmp(page_id, "environment") == 0) {
create_environment_page();
} else if(strcmp(page_id, "devices") == 0) {
create_devices_page();
} else if(strcmp(page_id, "scenes") == 0) {
create_scenes_page();
} else if(strcmp(page_id, "energy") == 0) {
create_energy_page();
} else if(strcmp(page_id, "settings") == 0) {
create_settings_page();
}
}
/**
* 更新时间显示
*/
static void update_time_display(lv_timer_t * timer) {
// 这里应该获取系统时间,这里使用静态变量模拟
static int seconds = 0;
seconds++;
int hours = (14 + seconds / 3600) % 24;
int minutes = (30 + (seconds % 3600) / 60) % 60;
int secs = seconds % 60;
char time_str[32];
snprintf(time_str, sizeof(time_str), "2024-06-15 %02d:%02d:%02d", hours, minutes, secs);
lv_label_set_text((lv_obj_t *)timer->user_data, time_str);
}
13.3 创建环境监控页面
现在让我们创建第一个功能页面 - 环境监控:
/**
* 创建环境监控页面
*/
void create_environment_page() {
// 清除之前的内容
lv_obj_clean(ui.content_area);
// 设置内容区域为垂直Flex布局
lv_obj_set_flex_flow(ui.content_area, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(ui.content_area, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_all(ui.content_area, 25, 0);
lv_obj_set_style_pad_gap(ui.content_area, 20, 0);
// 页面标题
lv_obj_t * page_title = lv_label_create(ui.content_area);
lv_label_set_text(page_title, "环境监控");
lv_obj_set_style_text_color(page_title, lv_color_white(), 0);
lv_obj_set_style_text_font(page_title, &lv_font_montserrat_24, 0);
// 环境数据卡片容器
lv_obj_t * cards_container = lv_obj_create(ui.content_area);
lv_obj_set_size(cards_container, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(cards_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(cards_container, 0, 0);
lv_obj_set_flex_flow(cards_container, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(cards_container, LV_FLEX_ALIGN_SPACE_EVENLY,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_gap(cards_container, 20, 0);
// 创建环境数据卡片
create_environment_card(cards_container, "🌡️", "温度", "24.5°C", "舒适", lv_color_hex(0xE74C3C));
create_environment_card(cards_container, "💧", "湿度", "65%", "正常", lv_color_hex(0x3498DB));
create_environment_card(cards_container, "🍃", "空气质量", "85", "良好", lv_color_hex(0x2ECC71));
create_environment_card(cards_container, "🔊", "噪音", "42dB", "安静", lv_color_hex(0x9B59B6));
// 创建图表区域
create_environment_charts();
}
/**
* 创建环境数据卡片
*/
void create_environment_card(lv_obj_t * parent, const char * icon, const char * title,
const char * value, const char * status, lv_color_t color) {
lv_obj_t * card = lv_obj_create(parent);
lv_obj_set_size(card, 180, 140);
lv_obj_set_style_bg_color(card, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_radius(card, 15, 0);
lv_obj_set_style_shadow_width(card, 10, 0);
lv_obj_set_style_shadow_color(card, lv_color_hex(0x1A2530), 0);
lv_obj_set_flex_flow(card, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(card, LV_FLEX_ALIGN_SPACE_AROUND,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(card, 20, 0);
// 图标
lv_obj_t * icon_label = lv_label_create(card);
lv_label_set_text(icon_label, icon);
lv_obj_set_style_text_color(icon_label, color, 0);
lv_obj_set_style_text_font(icon_label, &lv_font_montserrat_24, 0);
// 标题
lv_obj_t * title_label = lv_label_create(card);
lv_label_set_text(title_label, title);
lv_obj_set_style_text_color(title_label, lv_color_hex(0xBDC3C7), 0);
lv_obj_set_style_text_font(title_label, &lv_font_montserrat_14, 0);
// 数值
lv_obj_t * value_label = lv_label_create(card);
lv_label_set_text(value_label, value);
lv_obj_set_style_text_color(value_label, lv_color_white(), 0);
lv_obj_set_style_text_font(value_label, &lv_font_montserrat_20, 0);
// 状态
lv_obj_t * status_label = lv_label_create(card);
lv_label_set_text(status_label, status);
lv_obj_set_style_text_color(status_label, color, 0);
lv_obj_set_style_text_font(status_label, &lv_font_montserrat_12, 0);
}
/**
* 创建环境数据图表
*/
void create_environment_charts() {
lv_obj_t * charts_container = lv_obj_create(ui.content_area);
lv_obj_set_size(charts_container, LV_PCT(100), 300);
lv_obj_set_style_bg_opa(charts_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(charts_container, 0, 0);
lv_obj_set_flex_flow(charts_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(charts_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
// 温度图表
lv_obj_t * temp_chart = lv_chart_create(charts_container);
lv_obj_set_size(temp_chart, LV_PCT(48), LV_PCT(100));
lv_obj_set_style_bg_color(temp_chart, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_radius(temp_chart, 15, 0);
lv_chart_set_type(temp_chart, LV_CHART_TYPE_LINE);
lv_chart_set_range(temp_chart, LV_CHART_AXIS_PRIMARY_Y, 15, 35);
lv_chart_set_point_count(temp_chart, 24);
lv_chart_set_div_line_count(temp_chart, 4, 6);
lv_chart_series_t * temp_series = lv_chart_add_series(temp_chart, lv_color_hex(0xE74C3C), LV_CHART_AXIS_PRIMARY_Y);
// 湿度图表
lv_obj_t * humi_chart = lv_chart_create(charts_container);
lv_obj_set_size(humi_chart, LV_PCT(48), LV_PCT(100));
lv_obj_set_style_bg_color(humi_chart, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_radius(humi_chart, 15, 0);
lv_chart_set_type(humi_chart, LV_CHART_TYPE_LINE);
lv_chart_set_range(humi_chart, LV_CHART_AXIS_PRIMARY_Y, 30, 90);
lv_chart_set_point_count(humi_chart, 24);
lv_chart_set_div_line_count(humi_chart, 4, 6);
lv_chart_series_t * humi_series = lv_chart_add_series(humi_chart, lv_color_hex(0x3498DB), LV_CHART_AXIS_PRIMARY_Y);
// 模拟历史数据
for(int i = 0; i < 24; i++) {
lv_chart_set_next_value(temp_chart, temp_series, 20 + rand() % 10);
lv_chart_set_next_value(humi_chart, humi_series, 40 + rand() % 40);
}
// 图表标题
lv_obj_t * temp_title = lv_label_create(temp_chart);
lv_label_set_text(temp_title, "温度趋势");
lv_obj_set_style_text_color(temp_title, lv_color_white(), 0);
lv_obj_align(temp_title, LV_ALIGN_TOP_LEFT, 10, 10);
lv_obj_t * humi_title = lv_label_create(humi_chart);
lv_label_set_text(humi_title, "湿度趋势");
lv_obj_set_style_text_color(humi_title, lv_color_white(), 0);
lv_obj_align(humi_title, LV_ALIGN_TOP_LEFT, 10, 10);
}
第14章:综合实战(二)- 为面板注入逻辑
14.1 设备控制页面与事件处理
现在让我们创建设备控制页面并实现完整的交互逻辑:
/**
* 创建设备控制页面
*/
void create_devices_page() {
// 清除之前的内容
lv_obj_clean(ui.content_area);
// 设置内容区域布局
lv_obj_set_flex_flow(ui.content_area, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(ui.content_area, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_all(ui.content_area, 25, 0);
lv_obj_set_style_pad_gap(ui.content_area, 20, 0);
// 页面标题
lv_obj_t * page_title = lv_label_create(ui.content_area);
lv_label_set_text(page_title, "设备控制");
lv_obj_set_style_text_color(page_title, lv_color_white(), 0);
lv_obj_set_style_text_font(page_title, &lv_font_montserrat_24, 0);
// 创建设备控制卡片
create_device_control_section("💡 灯光控制", create_lighting_controls);
create_device_control_section("🌡️ 空调控制", create_ac_controls);
create_device_control_section("🪟 窗帘控制", create_curtain_controls);
create_device_control_section("🔒 安防系统", create_security_controls);
}
/**
* 创建设备控制区域
*/
void create_device_control_section(const char * title, void (*create_controls_func)(lv_obj_t*)) {
lv_obj_t * section = lv_obj_create(ui.content_area);
lv_obj_set_size(section, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_color(section, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_radius(section, 15, 0);
lv_obj_set_flex_flow(section, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(section, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_all(section, 20, 0);
lv_obj_set_style_pad_gap(section, 15, 0);
// 区域标题
lv_obj_t * section_title = lv_label_create(section);
lv_label_set_text(section_title, title);
lv_obj_set_style_text_color(section_title, lv_color_white(), 0);
lv_obj_set_style_text_font(section_title, &lv_font_montserrat_18, 0);
// 创建设备控制
create_controls_func(section);
}
/**
* 创建灯光控制
*/
void create_lighting_controls(lv_obj_t * parent) {
lv_obj_t * controls_container = lv_obj_create(parent);
lv_obj_set_size(controls_container, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(controls_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(controls_container, 0, 0);
lv_obj_set_flex_flow(controls_container, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(controls_container, LV_FLEX_ALIGN_SPACE_EVENLY,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
// 客厅灯光
create_light_switch(controls_container, "客厅主灯", &app_state.devices.living_room_light,
lv_color_hex(0xF39C12));
// 卧室灯光
create_light_switch(controls_container, "卧室灯光", &app_state.devices.bedroom_light,
lv_color_hex(0x3498DB));
// 厨房灯光
create_light_switch(controls_container, "厨房灯光", &app_state.devices.kitchen_light,
lv_color_hex(0x2ECC71));
// 亮度调节
create_brightness_control(parent);
}
/**
* 创建灯光开关
*/
void create_light_switch(lv_obj_t * parent, const char * room, bool * state, lv_color_t color) {
lv_obj_t * switch_container = lv_obj_create(parent);
lv_obj_set_size(switch_container, 150, 100);
lv_obj_set_style_bg_opa(switch_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(switch_container, 0, 0);
lv_obj_set_flex_flow(switch_container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(switch_container, LV_FLEX_ALIGN_SPACE_AROUND,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
// 房间名称
lv_obj_t * room_label = lv_label_create(switch_container);
lv_label_set_text(room_label, room);
lv_obj_set_style_text_color(room_label, lv_color_white(), 0);
lv_obj_set_style_text_font(room_label, &lv_font_montserrat_14, 0);
// 开关
lv_obj_t * sw = lv_switch_create(switch_container);
lv_obj_set_style_bg_color(sw, lv_color_hex(0x7F8C8D), LV_PART_MAIN);
lv_obj_set_style_bg_color(sw, color, LV_PART_INDICATOR);
// 设置初始状态
if(*state) {
lv_obj_add_state(sw, LV_STATE_CHECKED);
}
// 事件处理
lv_obj_add_event_cb(sw, [](lv_event_t * e) {
lv_obj_t * sw = lv_event_get_target(e);
bool * device_state = (bool *)lv_event_get_user_data(e);
*device_state = lv_obj_has_state(sw, LV_STATE_CHECKED);
const char * room_name = (const char *)lv_obj_get_user_data(sw);
printf("%s %s\n", room_name, *device_state ? "开启" : "关闭");
// 这里可以添加实际的设备控制逻辑
// control_light_device(room_name, *device_state);
}, LV_EVENT_VALUE_CHANGED, state);
lv_obj_set_user_data(sw, (void*)room);
}
/**
* 创建亮度调节
*/
void create_brightness_control(lv_obj_t * parent) {
lv_obj_t * brightness_container = lv_obj_create(parent);
lv_obj_set_size(brightness_container, LV_PCT(100), 80);
lv_obj_set_style_bg_opa(brightness_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(brightness_container, 0, 0);
lv_obj_set_flex_flow(brightness_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(brightness_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
// 亮度标签
lv_obj_t * brightness_label = lv_label_create(brightness_container);
lv_label_set_text(brightness_label, "整体亮度");
lv_obj_set_style_text_color(brightness_label, lv_color_white(), 0);
lv_obj_set_style_text_font(brightness_label, &lv_font_montserrat_14, 0);
// 亮度值显示
lv_obj_t * value_label = lv_label_create(brightness_container);
lv_label_set_text_fmt(value_label, "%d%%", app_state.devices.light_brightness);
lv_obj_set_style_text_color(value_label, lv_color_hex(0xF39C12), 0);
lv_obj_set_style_text_font(value_label, &lv_font_montserrat_16, 0);
// 亮度滑块
lv_obj_t * slider = lv_slider_create(brightness_container);
lv_obj_set_size(slider, LV_PCT(60), 20);
lv_slider_set_range(slider, 0, 100);
lv_slider_set_value(slider, app_state.devices.light_brightness, LV_ANIM_OFF);
lv_obj_set_style_bg_color(slider, lv_color_hex(0xF39C12), LV_PART_INDICATOR);
lv_obj_set_style_bg_color(slider, lv_color_hex(0xF39C12), LV_PART_KNOB);
// 事件处理
lv_obj_add_event_cb(slider, [](lv_event_t * e) {
lv_obj_t * slider = lv_event_get_target(e);
int brightness = lv_slider_get_value(slider);
app_state.devices.light_brightness = brightness;
lv_obj_t * value_label = (lv_obj_t *)lv_event_get_user_data(e);
lv_label_set_text_fmt(value_label, "%d%%", brightness);
printf("调整亮度到: %d%%\n", brightness);
// 这里可以添加实际的亮度控制逻辑
// set_light_brightness(brightness);
}, LV_EVENT_VALUE_CHANGED, value_label);
}
/**
* 创建空调控制
*/
void create_ac_controls(lv_obj_t * parent) {
lv_obj_t * controls_container = lv_obj_create(parent);
lv_obj_set_size(controls_container, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(controls_container, LV_OPA_0, 0);
lv_obj_set_style_border_width(controls_container, 0, 0);
lv_obj_set_flex_flow(controls_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(controls_container, LV_FLEX_ALIGN_SPACE_AROUND,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
// 温度显示和调节
lv_obj_t * temp_control = lv_obj_create(controls_container);
lv_obj_set_size(temp_control, 200, 120);
lv_obj_set_style_bg_opa(temp_control, LV_OPA_0, 0);
lv_obj_set_style_border_width(temp_control, 0, 0);
lv_obj_set_flex_flow(temp_control, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(temp_control, LV_FLEX_ALIGN_SPACE_AROUND,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * temp_label = lv_label_create(temp_control);
lv_label_set_text(temp_label, "设定温度");
lv_obj_set_style_text_color(temp_label, lv_color_white(), 0);
lv_obj_t * temp_value = lv_label_create(temp_control);
lv_label_set_text_fmt(temp_value, "%d°C", app_state.devices.ac_temperature);
lv_obj_set_style_text_color(temp_value, lv_color_hex(0x3498DB), 0);
lv_obj_set_style_text_font(temp_value, &lv_font_montserrat_24, 0);
// 温度调节按钮
lv_obj_t * temp_buttons = lv_obj_create(temp_control);
lv_obj_set_size(temp_buttons, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_bg_opa(temp_buttons, LV_OPA_0, 0);
lv_obj_set_style_border_width(temp_buttons, 0, 0);
lv_obj_set_flex_flow(temp_buttons, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(temp_buttons, LV_FLEX_ALIGN_SPACE_AROUND,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_t * temp_down = lv_btn_create(temp_buttons);
lv_obj_set_size(temp_down, 40, 40);
lv_obj_set_style_bg_color(temp_down, lv_color_hex(0xE74C3C), 0);
lv_obj_t * down_label = lv_label_create(temp_down);
lv_label_set_text(down_label, "-");
lv_obj_center(down_label);
lv_obj_t * temp_up = lv_btn_create(temp_buttons);
lv_obj_set_size(temp_up, 40, 40);
lv_obj_set_style_bg_color(temp_up, lv_color_hex(0x2ECC71), 0);
lv_obj_t * up_label = lv_label_create(temp_up);
lv_label_set_text(up_label, "+");
lv_obj_center(up_label);
// 温度调节事件
lv_obj_add_event_cb(temp_down, [](lv_event_t * e) {
if(app_state.devices.ac_temperature > 16) {
app_state.devices.ac_temperature--;
update_ac_temperature_display();
}
}, LV_EVENT_CLICKED, NULL);
lv_obj_add_event_cb(temp_up, [](lv_event_t * e) {
if(app_state.devices.ac_temperature < 30) {
app_state.devices.ac_temperature++;
update_ac_temperature_display();
}
}, LV_EVENT_CLICKED, NULL);
// 存储温度显示标签的引用
lv_obj_set_user_data(temp_control, temp_value);
}
/**
* 更新空调温度显示
*/
void update_ac_temperature_display() {
// 这里需要遍历UI找到温度显示标签并更新
// 在实际项目中,应该维护UI组件的引用
printf("空调温度设置为: %d°C\n", app_state.devices.ac_temperature);
}
14.2 场景管理与数据驱动
现在让我们实现场景管理功能和数据驱动的UI更新:
/**
* 创建场景模式页面
*/
void create_scenes_page() {
// 清除之前的内容
lv_obj_clean(ui.content_area);
// 设置内容区域布局
lv_obj_set_flex_flow(ui.content_area, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(ui.content_area, LV_FLEX_ALIGN_START,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_all(ui.content_area, 25, 0);
lv_obj_set_style_pad_gap(ui.content_area, 20, 0);
// 页面标题
lv_obj_t * page_title = lv_label_create(ui.content_area);
lv_label_set_text(page_title, "场景模式");
lv_obj_set_style_text_color(page_title, lv_color_white(), 0);
lv_obj_set_style_text_font(page_title, &lv_font_montserrat_24, 0);
// 当前场景显示
lv_obj_t * current_scene_container = lv_obj_create(ui.content_area);
lv_obj_set_size(current_scene_container, LV_PCT(100), 80);
lv_obj_set_style_bg_color(current_scene_container, lv_color_hex(0x2C3E50), 0);
lv_obj_set_style_radius(current_scene_container, 15, 0);
lv_obj_set_flex_flow(current_scene_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(current_scene_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_hor(current_scene_container, 20, 0);
lv_obj_t * current_label = lv_label_create(current_scene_container);
lv_label_set_text(current_label, "当前场景");
lv_obj_set_style_text_color(current_label, lv_color_hex(0xBDC3C7), 0);
lv_obj_t * scene_name = lv_label_create(current_scene_container);
lv_label_set_text_fmt(scene_name, "🏠 %s", app_state.current_scene);
lv_obj_set_style_text_color(scene_name, lv_color_hex(0x2ECC71), 0);
lv_obj_set_style_text_font(scene_name, &lv_font_montserrat_18, 0);
// 场景网格
lv_obj_t * scenes_grid = lv_obj_create(ui.content_area);
lv_obj_set_size(scenes_grid, LV_PCT(100), LV_PCT(100));
lv_obj_set_style_bg_opa(scenes_grid, LV_OPA_0, 0);
lv_obj_set_style_border_width(scenes_grid, 0, 0);
lv_obj_set_flex_flow(scenes_grid, LV_FLEX_FLOW_ROW_WRAP);
lv_obj_set_flex_align(scenes_grid, LV_FLEX_ALIGN_SPACE_EVENLY,
LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
lv_obj_set_style_pad_gap(scenes_grid, 20, 0);
// 定义场景
struct {
const char * name;
const char * icon;
const char * description;
lv_color_t color;
} scenes[] = {
{"居家模式", "🏠", "舒适的居家环境", lv_color_hex(0x3498DB)},
{"影院模式", "🎬", "沉浸式观影体验", lv_color_hex(0x9B59B6)},
{"睡眠模式", "😴", "安静舒适的睡眠", lv_color_hex(0x2C3E50)},
{"阅读模式", "📖", "专注的阅读光线", lv_color_hex(0xF39C12)},
{"聚会模式", "🎉", "欢乐的聚会氛围", lv_color_hex(0xE74C3C)},
{"离家模式", "🚪", "节能安全模式", lv_color_hex(0x7F8C8D)},
};
for(int i = 0; i < sizeof(scenes) / sizeof(scenes[0]); i++) {
create_scene_card(scenes_grid, &scenes[i]);
}
}
/**
* 创建场景卡片
*/
void create_scene_card(lv_obj_t * parent, void * scene_data) {
typedef struct {
const char * name;
const char * icon;
const char * description;
lv_color_t color;
} scene_info_t;
scene_info_t * scene = (scene_info_t *)scene_data;
lv_obj_t * card = lv_btn_create(parent);
lv_obj_set_size(card, 170, 150);
lv_obj_set_style_bg_color(card, scene->color, 0);
lv_obj_set_style_bg_color(card, lv_color_lighten(scene->color, 50), LV_STATE_PRESSED);
lv_obj_set_style_radius(card, 15, 0);
lv_obj_set_style_shadow_width(card, 15, 0);
lv_obj_set_style_shadow_color(card, lv_color_darken(scene->color, 100), 0);
lv_obj_set_flex_flow(card, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(card, LV_FLEX_ALIGN_SPACE_AROUND,
LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
// 场景图标
lv_obj_t * icon = lv_label_create(card);
lv_label_set_text(icon, scene->icon);
lv_obj_set_style_text_color(icon, lv_color_white(), 0);
lv_obj_set_style_text_font(icon, &lv_font_montserrat_24, 0);
// 场景名称
lv_obj_t * name = lv_label_create(card);
lv_label_set_text(name, scene->name);
lv_obj_set_style_text_color(name, lv_color_white(), 0);
lv_obj_set_style_text_font(name, &lv_font_montserrat_16, 0);
// 场景描述
lv_obj_t * desc = lv_label_create(card);
lv_label_set_text(desc, scene->description);
lv_obj_set_style_text_color(desc, lv_color_white(), 0);
lv_obj_set_style_text_font(desc, &lv_font_montserrat_12, 0);
lv_obj_set_style_text_align(desc, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_set_width(desc, LV_PCT(90));
// 事件处理
lv_obj_add_event_cb(card, [](lv_event_t * e) {
scene_info_t * scene = (scene_info_t *)lv_event_get_user_data(e);
// 更新当前场景
app_state.current_scene = scene->name;
printf("切换到场景: %s\n", scene->name);
printf("场景描述: %s\n", scene->description);
// 这里可以添加实际的场景切换逻辑
// apply_scene_configuration(scene->name);
// 更新状态栏显示
update_status_bar_scene();
// 添加切换动画
lv_obj_t * card = lv_event_get_target(e);
lv_anim_t a;
lv_anim_init(&a);
lv_anim_set_var(&a, card);
lv_anim_set_values(&a, 255, 150, 255);
lv_anim_set_time(&a, 300);
lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_style_opa);
lv_anim_start(&a);
}, LV_EVENT_CLICKED, scene);
}
/**
* 更新状态栏场景显示
*/
void update_status_bar_scene() {
// 在实际项目中,应该维护状态栏组件的引用
printf("状态栏更新: 当前场景 = %s\n", app_state.current_scene);
}
14.3 数据持久化与状态管理
为了实现完整的数据驱动,我们需要添加状态管理和数据持久化:
/**
* 应用状态管理器
*/
typedef struct {
smart_home_state_t current_state;
void (*state_change_callback)(smart_home_state_t new_state);
} state_manager_t;
static state_manager_t state_mgr;
/**
* 初始化状态管理器
*/
void init_state_manager() {
state_mgr.current_state = app_state;
state_mgr.state_change_callback = NULL;
}
/**
* 更新应用状态
*/
void update_application_state(smart_home_state_t new_state) {
state_mgr.current_state = new_state;
app_state = new_state; // 更新全局状态
// 通知状态变化
if(state_mgr.state_change_callback) {
state_mgr.state_change_callback(new_state);
}
// 更新UI
update_ui_for_new_state();
}
/**
* 注册状态变化回调
*/
void register_state_change_callback(void (*callback)(smart_home_state_t)) {
state_mgr.state_change_callback = callback;
}
/**
* 根据新状态更新UI
*/
void update_ui_for_new_state() {
// 更新环境监控页面
update_environment_display();
// 更新设备控制页面
update_device_controls();
// 更新场景页面
update_scene_display();
// 更新状态栏
update_status_bar();
}
/**
* 模拟数据更新
*/
void simulate_sensor_data() {
lv_timer_t * sensor_timer = lv_timer_create([](lv_timer_t * timer) {
// 模拟传感器数据变化
app_state.temperature += (rand() % 10 - 5) * 0.1f;
app_state.humidity += (rand() % 10 - 5) * 0.1f;
app_state.air_quality += (rand() % 20 - 10) * 0.1f;
// 限制数值范围
app_state.temperature = LV_CLAMP(18.0f, app_state.temperature, 32.0f);
app_state.humidity = LV_CLAMP(30.0f, app_state.humidity, 80.0f);
app_state.air_quality = LV_CLAMP(0.0f, app_state.air_quality, 100.0f);
// 模拟用电量变化
float base_power = 1.5f;
if(app_state.devices.living_room_light) base_power += 0.2f;
if(app_state.devices.bedroom_light) base_power += 0.2f;
if(app_state.devices.kitchen_light) base_power += 0.3f;
app_state.power_consumption = base_power + (rand() % 10) * 0.1f;
app_state.energy_cost = app_state.power_consumption * 0.52f; // 假设电价0.52元/度
printf("传感器数据更新: 温度=%.1f°C, 湿度=%.1f%%, 用电量=%.1fkW\n",
app_state.temperature, app_state.humidity, app_state.power_consumption);
// 触发UI更新
update_ui_for_new_state();
}, 5000, NULL); // 每5秒更新一次
}
/**
* 保存配置到持久化存储
*/
void save_configuration() {
// 这里应该实现实际的存储逻辑
printf("保存配置到持久化存储...\n");
printf(" - 灯光状态: 客厅=%d, 卧室=%d, 厨房=%d\n",
app_state.devices.living_room_light,
app_state.devices.bedroom_light,
app_state.devices.kitchen_light);
printf(" - 亮度: %d%%\n", app_state.devices.light_brightness);
printf(" - 空调温度: %d°C\n", app_state.devices.ac_temperature);
printf(" - 当前场景: %s\n", app_state.current_scene);
}
/**
* 从持久化存储加载配置
*/
void load_configuration() {
// 这里应该实现实际的加载逻辑
printf("从持久化存储加载配置...\n");
// 模拟加载的配置
app_state.devices.living_room_light = true;
app_state.devices.bedroom_light = false;
app_state.devices.kitchen_light = true;
app_state.devices.light_brightness = 75;
app_state.devices.ac_temperature = 24;
app_state.current_scene = "居家模式";
}
14.4 应用初始化与主循环
最后,让我们完成应用的初始化和主循环:
/**
* 应用初始化
*/
void app_init() {
// 初始化状态管理器
init_state_manager();
// 加载保存的配置
load_configuration();
// 创建用户界面
create_smart_home_ui();
// 注册状态变化回调
register_state_change_callback([](smart_home_state_t new_state) {
printf("应用状态发生变化,更新UI...\n");
});
// 启动传感器数据模拟
simulate_sensor_data();
// 创建自动保存定时器
lv_timer_t * save_timer = lv_timer_create([](lv_timer_t * timer) {
save_configuration();
}, 30000, NULL); // 每30秒自动保存
}
/**
* 主函数
*/
int main(void) {
// LVGL初始化(参考第一部分)
lv_init();
// ... 显示和输入设备初始化
// 应用初始化
app_init();
// 主循环
while(1) {
lv_timer_handler();
SDL_Delay(5);
}
return 0;
}
项目总结与扩展
恭喜!你已经完成了一个功能完整的智能家居控制面板。这个项目综合运用了:
- 高级布局技术:Grid和Flex布局创建复杂界面
- 事件处理系统:完整的用户交互逻辑
- 数据驱动架构:状态管理和UI更新机制
- 动画效果:提升用户体验的视觉反馈
- 多页面管理:模块化的页面切换系统
项目扩展建议:
- 网络通信:添加MQTT或WebSocket支持,连接真实的智能家居设备
- 数据持久化:实现真正的配置保存和加载
- 用户认证:添加登录系统和多用户支持
- 语音控制:集成语音识别功能
- 移动端适配:创建响应式设计,支持手机和平板
性能优化提示:
- 虚拟列表:对于大量数据,使用虚拟列表优化内存使用
- 图片缓存:对频繁使用的图片进行缓存
- 事件去抖:对频繁触发的事件进行去抖处理
- 内存管理:合理使用静态分配,避免内存碎片
这个项目展示了LVGL在真实世界应用中的强大能力。通过这个完整的示例,你已经掌握了创建复杂、专业的嵌入式GUI应用所需的所有技能。
在接下来的第五部分中,我们将深入LVGL的原理和优化技术,帮助你从使用者成长为LVGL专家!
研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)
LVGL智能家居控制面板实战
598

被折叠的 条评论
为什么被折叠?



