一、回调函数基础体系
1. 回调函数本质
// 典型LVGL回调函数原型
typedef void (*lv_event_cb_t)(lv_event_t * e);
// 事件结构体关键成员
struct _lv_event_t {
lv_obj_t * target; // 触发事件的对象
lv_obj_t * current_target; // 当前处理对象
lv_event_code_t code; // 事件类型
void * user_data; // 用户自定义数据
};
2. 基础绑定方式
// 案例1:按钮点击回调
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);
void btn_event_cb(lv_event_t * e) {
if(lv_event_get_code(e) == LV_EVENT_CLICKED) {
AmbaPrint("按钮被点击");
}
}
二、事件传递机制
1. 事件冒泡(Bubbling)

// 案例2:阻止事件冒泡
void child_event_cb(lv_event_t * e) {
lv_event_stop_bubbling(e); // 停止向上传递
}
2. 事件标记(Event Marks)
// 案例3:标记已处理事件
lv_obj_add_event_cb(obj, event_cb, LV_EVENT_ALL, NULL);
void event_cb(lv_event_t * e) {
if(lv_event_get_code(e) == LV_EVENT_PRESSED) {
lv_obj_add_state(obj, LV_STATE_PRESSED);
lv_event_mark_stop(e); // 标记为已处理
}
}
三、用户数据传递
1. 静态数据传递
// 案例4:传递整型参数
int param = 42;
lv_obj_add_event_cb(btn, event_cb, LV_EVENT_CLICKED, (void*)param);
void event_cb(lv_event_t * e) {
int received = (int)lv_event_get_user_data(e);
AmbaPrint("收到参数: %d", received);
}
2. 动态数据传递
// 案例5:传递结构体(需内存管理)
typedef struct {
int id;
char name[20];
} MyData;
MyData *data = lv_mem_alloc(sizeof(MyData));
lv_obj_add_event_cb(obj, event_cb, LV_EVENT_ALL, data);
void event_cb(lv_event_t * e) {
if(lv_event_get_code(e) == LV_EVENT_DELETE) {
lv_mem_free(lv_event_get_user_data(e));
}
}
四、手动触发事件
1. 基础触发方式
// 案例6:手动发送点击事件
lv_event_send(btn, LV_EVENT_CLICKED, NULL);
// 案例7:带参数触发
int value = 100;
lv_event_send(slider, LV_EVENT_VALUE_CHANGED, &value);
2. 自定义事件
// 定义自定义事件码(建议>1024)
#define LV_EVENT_MY_CUSTOM (LV_EVENT_LAST + 1)
// 案例8:发送与接收
lv_event_send(obj, LV_EVENT_MY_CUSTOM, "Hello");
void event_cb(lv_event_t * e) {
if(lv_event_get_code(e) == LV_EVENT_MY_CUSTOM) {
char* msg = (char*)lv_event_get_param(e);
AmbaPrint("自定义消息: %s", msg);
}
}
五、高级应用模式
1. 事件代理模式
// 案例9:集中处理多个对象事件
void register_buttons(lv_obj_t * parent) {
for(int i=0; i<3; i++) {
lv_obj_t * btn = lv_btn_create(parent);
lv_obj_add_event_cb(btn, button_delegate, LV_EVENT_ALL, (void*)i);
}
}
void button_delegate(lv_event_t * e) {
int btn_id = (int)lv_event_get_user_data(e);
switch(lv_event_get_code(e)) {
case LV_EVENT_CLICKED:
AmbaPrint("按钮%d被点击", btn_id);
break;
}
}
2. 状态机模式
// 案例10:基于事件的UI状态管理
typedef enum {
STATE_IDLE,
STATE_ACTIVE,
STATE_ERROR
} AppState;
void state_machine_cb(lv_event_t * e) {
static AppState state = STATE_IDLE;
switch(state) {
case STATE_IDLE:
if(lv_event_get_code(e) == LV_EVENT_PRESSED) {
state = STATE_ACTIVE;
update_ui_state();
}
break;
// 其他状态处理...
}
}
六、实战项目案例
案例11:智能家居控制面板
// 场景:多房间灯光控制
typedef struct {
uint8_t room_id;
lv_obj_t * switch_obj;
lv_obj_t * brightness_slider;
} RoomControl;
void init_room_controls() {
RoomControl * living_room = lv_mem_alloc(sizeof(RoomControl));
living_room->room_id = 1;
living_room->switch_obj = lv_switch_create(lv_scr_act());
lv_obj_add_event_cb(living_room->switch_obj, room_switch_cb, LV_EVENT_ALL, living_room);
}
void room_switch_cb(lv_event_t * e) {
RoomControl * room = (RoomControl *)lv_event_get_user_data(e);
if(lv_event_get_code(e) == LV_EVENT_VALUE_CHANGED) {
bool is_on = lv_obj_has_state(room->switch_obj, LV_STATE_CHECKED);
mqtt_publish("home/light/%d", room->room_id, is_on);
// 手动更新亮度滑块状态
lv_obj_set_enabled(room->brightness_slider, is_on);
}
}
案例12:工业仪表盘
// 场景:实时数据更新
void data_update_timer_cb(lv_timer_t * timer) {
static int count = 0;
lv_obj_t * gauge = (lv_obj_t *)timer->user_data;
// 模拟数据更新
int new_value = rand() % 100;
lv_gauge_set_value(gauge, 0, new_value);
// 超过阈值触发告警事件
if(new_value > 80) {
lv_event_send(gauge, LV_EVENT_ALARM_TRIGGERED, &new_value);
}
}
void gauge_event_cb(lv_event_t * e) {
if(lv_event_get_code(e) == LV_EVENT_ALARM_TRIGGERED) {
int * value = (int*)lv_event_get_param(e);
AmbaPrint("警报!当前值: %d", *value);
lv_obj_add_state(gauge, LV_STATE_ERROR);
}
}
七、调试与优化
1. 事件调试技巧
// 打印事件信息
void debug_event_cb(lv_event_t * e) {
AmbaPrint("事件[0x%x]来自对象%p",
lv_event_get_code(e),
lv_event_get_target(e));
}
// 绑定到测试对象
lv_obj_add_event_cb(test_obj, debug_event_cb, LV_EVENT_ALL, NULL);
2. 性能优化
// 案例13:事件节流
static uint32_t last_event_time = 0;
void throttle_event_cb(lv_event_t * e) {
uint32_t now = lv_tick_get();
if(now - last_event_time < 200) return; // 200ms内不重复处理
last_event_time = now;
// 实际处理逻辑...
}
知识体系总结
