文本框对齐问题
添加功能现在可以正常工作
添加成功后显示2秒提示
添加的数据可以在View Students中查看
#include "ui.h"
#include "lvgl/lvgl.h"
#include "student.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// 编辑学生回调
void edit_student_cb(lv_event_t *e);
// 删除学生回调
void delete_student_cb(lv_event_t *e);
// 退出系统回调
void exit_system_cb(lv_event_t *e);
// 全局UI组件
static lv_obj_t *main_page;
static lv_obj_t *add_page;
static lv_obj_t *list_page;
static lv_obj_t *edit_page;
static lv_obj_t *kb;
static lv_obj_t *student_list;
// 输入框
static lv_obj_t *ta_id;
static lv_obj_t *ta_name;
static lv_obj_t *ta_score;
static lv_obj_t *ta_edit_score;
// 当前编辑的学生ID
static int current_edit_id = 0;
// 关闭键盘
void hide_keyboard() {
if (kb) {
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
// 移除当前文本框的焦点状态
lv_obj_t *ta = lv_keyboard_get_textarea(kb);
if (ta) {
lv_obj_clear_state(ta, LV_STATE_FOCUSED);
}
// 解除键盘与文本框的绑定
lv_keyboard_set_textarea(kb, NULL);
}
}
// 键盘事件处理
static void kb_event_cb(lv_event_t *e) {
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t *kb = lv_event_get_target(e);
if (code == LV_EVENT_READY || code == LV_EVENT_CANCEL) {
// 隐藏键盘并移除文本框焦点
hide_keyboard();
}
}
// 定时器回调函数 - 用于延迟隐藏键盘
static void hide_keyboard_timer_cb(lv_timer_t *timer) {
hide_keyboard();
lv_timer_del(timer); // 删除定时器
}
// 文本框事件处理
static void ta_event_cb(lv_event_t *e) {
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t *ta = lv_event_get_target(e);
if (code == LV_EVENT_CLICKED || code == LV_EVENT_FOCUSED) {
if (kb) {
// 显示键盘
lv_obj_clear_flag(kb, LV_OBJ_FLAG_HIDDEN);
lv_keyboard_set_textarea(kb, ta);
lv_obj_move_foreground(kb);
// 滚动视图确保文本框可见
lv_obj_scroll_to_view_recursive(ta, LV_ANIM_OFF);
}
}
else if (code == LV_EVENT_DEFOCUSED) {
// 文本框失去焦点时隐藏键盘(延迟100ms执行)
lv_timer_t* timer = lv_timer_create(hide_keyboard_timer_cb, 100, NULL);
}
}
// 页面点击事件处理 - 用于关闭键盘
static void page_click_cb(lv_event_t *e) {
// 点击页面时隐藏键盘
hide_keyboard();
}
// 显示主页面
void show_main_page() {
lv_screen_load(main_page);
}
// 显示添加页面
void show_add_page() {
// 清空输入框
lv_textarea_set_text(ta_id, "");
lv_textarea_set_text(ta_name, "");
lv_textarea_set_text(ta_score, "");
// 设置下一个可用ID
char id_buf[20];
snprintf(id_buf, sizeof(id_buf), "%d", get_next_id());
lv_textarea_set_text(ta_id, id_buf);
lv_screen_load(add_page);
}
// 显示列表页面
void show_list_page() {
// 清空现有列表
lv_obj_clean(student_list);
// 获取学生数据
Student *students = NULL;
int count = get_students(&students);
if (count <= 0) {
lv_obj_t *label = lv_label_create(student_list);
lv_label_set_text(label, "No student records");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
return;
}
// 创建标题行
lv_obj_t *header = lv_obj_create(student_list);
lv_obj_set_size(header, LV_PCT(100), 40);
lv_obj_set_flex_flow(header, LV_FLEX_FLOW_ROW);
lv_obj_t *id_label = lv_label_create(header);
lv_label_set_text(id_label, "ID");
lv_obj_set_width(id_label, LV_PCT(15));
lv_obj_t *name_label = lv_label_create(header);
lv_label_set_text(name_label, "Name");
lv_obj_set_width(name_label, LV_PCT(35));
lv_obj_t *score_label = lv_label_create(header);
lv_label_set_text(score_label, "Score");
lv_obj_set_width(score_label, LV_PCT(20));
lv_obj_t *action_label = lv_label_create(header);
lv_label_set_text(action_label, "Actions");
lv_obj_set_width(action_label, LV_PCT(30));
// 添加学生记录
for (int i = 0; i < count; i++) {
if (students[i].delete) continue;
lv_obj_t *row = lv_obj_create(student_list);
lv_obj_set_size(row, LV_PCT(100), 50);
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
// ID
char id_buf[10];
snprintf(id_buf, sizeof(id_buf), "%d", students[i].id);
lv_obj_t *id = lv_label_create(row);
lv_label_set_text(id, id_buf);
lv_obj_set_width(id, LV_PCT(15));
// 姓名
lv_obj_t *name = lv_label_create(row);
lv_label_set_text(name, students[i].name);
lv_obj_set_width(name, LV_PCT(35));
// 成绩
char score_buf[20];
snprintf(score_buf, sizeof(score_buf), "%.1f", students[i].score);
lv_obj_t *score = lv_label_create(row);
lv_label_set_text(score, score_buf);
lv_obj_set_width(score, LV_PCT(20));
// 操作按钮
lv_obj_t *btn_container = lv_obj_create(row);
lv_obj_set_size(btn_container, LV_PCT(30), LV_PCT(100));
lv_obj_set_flex_flow(btn_container, LV_FLEX_FLOW_ROW);
lv_obj_set_style_pad_all(btn_container, 5, 0);
// 编辑按钮
lv_obj_t *edit_btn = lv_btn_create(btn_container);
lv_obj_set_size(edit_btn, 80, 35);
lv_obj_t *edit_label = lv_label_create(edit_btn);
lv_label_set_text(edit_label, "Edit");
// 保存学生ID用于编辑
int *student_id = malloc(sizeof(int));
*student_id = students[i].id;
lv_obj_add_event_cb(edit_btn, edit_student_cb, LV_EVENT_CLICKED, student_id);
// 删除按钮
lv_obj_t *del_btn = lv_btn_create(btn_container);
lv_obj_set_size(del_btn, 80, 35);
lv_obj_t *del_label = lv_label_create(del_btn);
lv_label_set_text(del_label, "Delete");
// 保存学生ID用于删除
student_id = malloc(sizeof(int));
*student_id = students[i].id;
lv_obj_add_event_cb(del_btn, delete_student_cb, LV_EVENT_CLICKED, student_id);
}
free(students);
lv_screen_load(list_page);
}
// 显示编辑页面
void show_edit_page(int student_id, float current_score) {
current_edit_id = student_id;
char score_buf[20];
snprintf(score_buf, sizeof(score_buf), "%.1f", current_score);
lv_textarea_set_text(ta_edit_score, score_buf);
lv_screen_load(edit_page);
}
// 添加学生回调
void add_student_cb(lv_event_t *e) {
const char* id_str = lv_textarea_get_text(ta_id);
const char* name = lv_textarea_get_text(ta_name);
const char* score_str = lv_textarea_get_text(ta_score);
if (!id_str || !name || !score_str ||
strlen(id_str) == 0 || strlen(name) == 0 || strlen(score_str) == 0) {
return;
}
Student s;
s.id = atoi(id_str);
strncpy(s.name, name, sizeof(s.name) - 1);
s.name[sizeof(s.name) - 1] = '\0';
s.score = atof(score_str);
s.delete = 0;
int ret = add_student(&s);
if (ret == 0) {
show_list_page();
}
}
// 编辑学生回调
void edit_student_cb(lv_event_t *e) {
int *student_id = (int *)lv_event_get_user_data(e);
if (student_id) {
// 获取当前分数
Student *students = NULL;
int count = get_students(&students);
float current_score = 0.0;
for (int i = 0; i < count; i++) {
if (students[i].id == *student_id) {
current_score = students[i].score;
break;
}
}
free(students);
show_edit_page(*student_id, current_score);
free(student_id);
}
}
// 更新学生回调
void update_student_cb(lv_event_t *e) {
const char* score_str = lv_textarea_get_text(ta_edit_score);
if (!score_str || strlen(score_str) == 0) {
return;
}
float new_score = atof(score_str);
int ret = update_student(current_edit_id, new_score);
if (ret == 0) {
show_list_page();
}
}
// 删除学生回调
void delete_student_cb(lv_event_t *e) {
int *student_id = (int *)lv_event_get_user_data(e);
if (student_id) {
int ret = delete_student(*student_id);
if (ret == 0) {
show_list_page();
}
free(student_id);
}
}
// 创建主页面
void create_main_page() {
main_page = lv_obj_create(NULL);
lv_obj_t *title = lv_label_create(main_page);
lv_label_set_text(title, "Student Management System");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 30);
lv_obj_set_style_text_font(title, &lv_font_montserrat_24, 0);
// 创建按钮容器
lv_obj_t *btn_container = lv_obj_create(main_page);
lv_obj_set_size(btn_container, 400, 300);
lv_obj_align(btn_container, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_flex_flow(btn_container, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(btn_container, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(btn_container, 20, 0);
lv_obj_set_style_pad_row(btn_container, 20, 0);
// 添加学生按钮
lv_obj_t *add_btn = lv_btn_create(btn_container);
lv_obj_set_size(add_btn, 250, 60);
lv_obj_t *add_label = lv_label_create(add_btn);
lv_label_set_text(add_label, "Add Student");
lv_obj_add_event_cb(add_btn, show_add_page, LV_EVENT_CLICKED, NULL);
// 查看学生按钮
lv_obj_t *list_btn = lv_btn_create(btn_container);
lv_obj_set_size(list_btn, 250, 60);
lv_obj_t *list_label = lv_label_create(list_btn);
lv_label_set_text(list_label, "View Students");
lv_obj_add_event_cb(list_btn, show_list_page, LV_EVENT_CLICKED, NULL);
// 退出按钮
lv_obj_t *exit_btn = lv_btn_create(btn_container);
lv_obj_set_size(exit_btn, 250, 60);
lv_obj_t *exit_label = lv_label_create(exit_btn);
lv_label_set_text(exit_label, "Exit System");
lv_obj_add_event_cb(exit_btn, exit_system_cb, LV_EVENT_CLICKED, NULL);
}
// 创建添加页面 - 改进版(居中布局)
void create_add_page() {
add_page = lv_obj_create(NULL);
lv_obj_set_size(add_page, LV_HOR_RES, LV_VER_RES);
lv_obj_set_scrollbar_mode(add_page, LV_SCROLLBAR_MODE_OFF);
// 添加页面点击事件(用于关闭键盘)
lv_obj_add_event_cb(add_page, page_click_cb, LV_EVENT_CLICKED, NULL);
lv_obj_t *title = lv_label_create(add_page);
lv_label_set_text(title, "Add New Student");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 30);
lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
// 创建表单容器(居中)
lv_obj_t *form = lv_obj_create(add_page);
lv_obj_remove_flag(form, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_size(form, 500, 400);
lv_obj_center(form);
lv_obj_set_style_bg_opa(form, LV_OPA_TRANSP, 0); // 透明背景
lv_obj_set_style_border_width(form, 0, 0); // 移除边框
// ID 标签和文本框
lv_obj_t *id_label = lv_label_create(form);
lv_label_set_text(id_label, "ID:");
lv_obj_set_style_text_font(id_label, &lv_font_montserrat_18, 0);
lv_obj_align(id_label, LV_ALIGN_TOP_LEFT, 10, 30);
ta_id = lv_textarea_create(form);
lv_obj_remove_flag(ta_id, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_size(ta_id, 300, 50);
lv_obj_align_to(ta_id, id_label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
lv_textarea_set_one_line(ta_id, true);
lv_textarea_set_max_length(ta_id, 10);
lv_obj_add_event_cb(ta_id, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_set_style_bg_color(ta_id, lv_color_hex(0xFFFFFF), 0);
lv_obj_set_style_border_width(ta_id, 1, 0);
// 姓名标签和文本框
lv_obj_t *name_label = lv_label_create(form);
lv_label_set_text(name_label, "Name:");
lv_obj_set_style_text_font(name_label, &lv_font_montserrat_18, 0);
lv_obj_align_to(name_label, id_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 50);
ta_name = lv_textarea_create(form);
lv_obj_remove_flag(ta_name, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_size(ta_name, 300, 50);
lv_obj_align_to(ta_name, name_label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
lv_textarea_set_one_line(ta_name, true);
lv_textarea_set_max_length(ta_name, 49);
lv_obj_add_event_cb(ta_name, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_set_style_bg_color(ta_name, lv_color_hex(0xFFFFFF), 0);
lv_obj_set_style_border_width(ta_name, 1, 0);
// 成绩标签和文本框
lv_obj_t *score_label = lv_label_create(form);
lv_label_set_text(score_label, "Score:");
lv_obj_set_style_text_font(score_label, &lv_font_montserrat_18, 0);
lv_obj_align_to(score_label, name_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 50);
ta_score = lv_textarea_create(form);
lv_obj_remove_flag(ta_score, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_size(ta_score, 300, 50);
lv_obj_align_to(ta_score, score_label, LV_ALIGN_OUT_RIGHT_MID, 20, 0);
lv_textarea_set_one_line(ta_score, true);
lv_textarea_set_max_length(ta_score, 5);
lv_textarea_set_accepted_chars(ta_score, "0123456789.");
lv_obj_add_event_cb(ta_score, ta_event_cb, LV_EVENT_ALL, NULL);
lv_obj_set_style_bg_color(ta_score, lv_color_hex(0xFFFFFF), 0);
lv_obj_set_style_border_width(ta_score, 1, 0);
// 按钮容器
lv_obj_t *btn_container = lv_obj_create(form);
lv_obj_remove_flag(btn_container, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_size(btn_container, 400, 60);
lv_obj_align(btn_container, LV_ALIGN_BOTTOM_MID, 0, -10);
lv_obj_set_flex_flow(btn_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(btn_container, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_bg_opa(btn_container, LV_OPA_TRANSP, 0);
// 添加按钮
lv_obj_t *add_btn = lv_btn_create(btn_container);
lv_obj_set_size(add_btn, 180, 50);
lv_obj_t *add_label = lv_label_create(add_btn);
lv_label_set_text(add_label, "Add");
lv_obj_set_style_text_font(add_label, &lv_font_montserrat_16, 0);
lv_obj_center(add_label);
lv_obj_add_event_cb(add_btn, add_student_cb, LV_EVENT_CLICKED, NULL);
// 返回按钮
lv_obj_t *back_btn = lv_btn_create(btn_container);
lv_obj_set_size(back_btn, 180, 50);
lv_obj_t *back_label = lv_label_create(back_btn);
lv_label_set_text(back_label, "Back");
lv_obj_set_style_text_font(back_label, &lv_font_montserrat_16, 0);
lv_obj_center(back_label);
lv_obj_add_event_cb(back_btn, show_main_page, LV_EVENT_CLICKED, NULL);
}
// 创建列表页面
void create_list_page() {
list_page = lv_obj_create(NULL);
lv_obj_t *title = lv_label_create(list_page);
lv_label_set_text(title, "Student List");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 20);
lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
// 创建滚动容器
lv_obj_t *scroll = lv_obj_create(list_page);
lv_obj_set_size(scroll, 700, 350);
lv_obj_align(scroll, LV_ALIGN_CENTER, 0, 0);
student_list = lv_obj_create(scroll);
lv_obj_set_size(student_list, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_flex_flow(student_list, LV_FLEX_FLOW_COLUMN);
// 返回按钮
lv_obj_t *back_btn = lv_btn_create(list_page);
lv_obj_set_size(back_btn, 150, 50);
lv_obj_align(back_btn, LV_ALIGN_BOTTOM_MID, 0, -20);
lv_obj_t *back_label = lv_label_create(back_btn);
lv_label_set_text(back_label, "Back");
lv_obj_add_event_cb(back_btn, show_main_page, LV_EVENT_CLICKED, NULL);
}
// 创建编辑页面
void create_edit_page() {
edit_page = lv_obj_create(NULL);
lv_obj_t *title = lv_label_create(edit_page);
lv_label_set_text(title, "Edit Student Score");
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 20);
lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
// 表单容器
lv_obj_t *form = lv_obj_create(edit_page);
lv_obj_set_size(form, 500, 200);
lv_obj_align(form, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_flex_flow(form, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(form, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_all(form, 20, 0);
lv_obj_set_style_pad_row(form, 30, 0);
// 成绩输入
lv_obj_t *score_container = lv_obj_create(form);
lv_obj_set_size(score_container, LV_PCT(100), 60);
lv_obj_set_flex_flow(score_container, LV_FLEX_FLOW_ROW);
lv_obj_t *score_label = lv_label_create(score_container);
lv_label_set_text(score_label, "New Score:");
lv_obj_set_width(score_label, LV_PCT(40));
ta_edit_score = lv_textarea_create(score_container);
lv_textarea_set_one_line(ta_edit_score, true);
lv_textarea_set_max_length(ta_edit_score, 5);
lv_textarea_set_accepted_chars(ta_edit_score, "0123456789.");
lv_obj_set_width(ta_edit_score, LV_PCT(60));
lv_obj_add_event_cb(ta_edit_score, ta_event_cb, LV_EVENT_ALL, NULL);
// 按钮容器
lv_obj_t *btn_container = lv_obj_create(form);
lv_obj_set_size(btn_container, LV_PCT(100), 60);
lv_obj_set_flex_flow(btn_container, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(btn_container, LV_FLEX_ALIGN_SPACE_AROUND, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
// 更新按钮
lv_obj_t *update_btn = lv_btn_create(btn_container);
lv_obj_set_size(update_btn, 150, 50);
lv_obj_t *update_label = lv_label_create(update_btn);
lv_label_set_text(update_label, "Update");
lv_obj_add_event_cb(update_btn, update_student_cb, LV_EVENT_CLICKED, NULL);
// 取消按钮
lv_obj_t *cancel_btn = lv_btn_create(btn_container);
lv_obj_set_size(cancel_btn, 150, 50);
lv_obj_t *cancel_label = lv_label_create(cancel_btn);
lv_label_set_text(cancel_label, "Cancel");
lv_obj_add_event_cb(cancel_btn, show_list_page, LV_EVENT_CLICKED, NULL);
}
// 创建键盘 - 增强版
void create_keyboard() {
kb = lv_keyboard_create(lv_layer_top());
lv_obj_set_size(kb, LV_HOR_RES, LV_VER_RES / 2);
lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_event_cb(kb, kb_event_cb, LV_EVENT_ALL, NULL);
// 设置键盘模式
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_TEXT_LOWER);
// 添加关闭按钮到键盘
lv_obj_t *close_btn = lv_btn_create(kb);
lv_obj_set_size(close_btn, 80, 40);
lv_obj_align(close_btn, LV_ALIGN_TOP_RIGHT, -10, 10);
lv_obj_t *close_label = lv_label_create(close_btn);
lv_label_set_text(close_label, LV_SYMBOL_CLOSE);
lv_obj_set_style_text_font(close_label, &lv_font_montserrat_24, 0);
lv_obj_add_event_cb(close_btn, hide_keyboard, LV_EVENT_CLICKED, NULL);
}
// 退出系统回调
void exit_system_cb(lv_event_t *e) {
exit(0);
}
// 初始化UI
void ui_init() {
create_main_page();
create_add_page();
create_list_page();
create_edit_page();
create_keyboard();
show_main_page();
}