Qt实战—从零构建学生成绩管理系统(文件存储与UI交互)

Qt实战—从零构建学生成绩管理系统(文件存储与UI交互)
1. 项目需求分析与设计思路第一次用Qt做学生成绩管理系统时我对着空白的Qt Creator界面发了半小时呆。后来发现与其直接写代码不如先拿张纸把需求理清楚。这个系统最核心的功能其实就五个增删改查排。数据结构设计是项目的骨架。我建议用一个StudentInfo类来封装学生信息包含以下字段姓名QString类型学号int类型数学成绩int类型英语成绩int类型C语言成绩int类型平均分double类型自动计算class StudentInfo { public: QString name; int id; int math; int english; int languageC; double avg; StudentInfo(QString n, int i, int m, int e, int c) { name n; id i; math m; english e; languageC c; avg (m e c) / 3.0; } };UI界面规划我走了不少弯路。最初把所有功能堆在一个窗口结果代码乱得像毛线团。后来改用多窗口设计主菜单窗口导航中心添加学生窗口带5个输入框修改/删除窗口学号检索数据修改查询窗口学号搜索结果展示排序窗口单选按钮表格展示经验之谈修改和删除功能可以合并因为它们都需要先通过学号定位学生记录。这样能减少窗口数量降低代码复杂度。2. 项目搭建与基础配置在Qt Creator中新建项目时新手常会踩两个坑一是选错项目类型二是漏掉关键库。这里给出详细步骤创建空项目文件 → 新建文件或项目 → 其他项目 → 空的Qt项目命名规范建议用StudentManagementSystem这样的驼峰命名添加Qt Widgets库在.pro文件中追加QT widgets多窗口创建技巧右键项目 → Add New → Qt → Qt设计师界面类依次创建MenuWidget主菜单AddStudentWidget添加ModifyWidget修改/删除SelectWidget查询SortWidget排序我遇到过窗口切换卡顿的问题后来发现用QStackedLayout比单纯show/hide更流畅。在MainWidget中初始化布局// mainwidget.h QStackedLayout *stackLayout; MenuWidget *menu; AddStudentWidget *addWin; //...其他窗口指针 // mainwidget.cpp stackLayout new QStackedLayout; stackLayout-addWidget(menu); stackLayout-addWidget(addWin); //...添加其他窗口 setLayout(stackLayout);3. 核心功能实现详解3.1 数据持久化存储用QFile和QTextStream读写文本文件时要注意三个关键点文件打开模式QIODevice::WriteOnly只写覆盖QIODevice::Append追加QIODevice::Text处理换行符数据格式建议用空格分隔字段例如张三 1001 85 90 78 李四 1002 92 88 95完整示例// 写入数据 QFile file(students.txt); if(file.open(QIODevice::Append | QIODevice::Text)){ QTextStream out(file); out name id math english languageC \n; file.close(); } // 读取数据 if(file.open(QIODevice::ReadOnly | QIODevice::Text)){ QTextStream in(file); while(!in.atEnd()){ QString line in.readLine(); QStringList data line.split( ); // 解析到StudentInfo对象 } }踩坑提醒一定要检查文件是否成功打开我早期版本没做判断导致数据丢失还不报错。3.2 窗口交互与信号槽主菜单到子窗口的切换推荐使用信号槽机制// menuwidget.h signals: void changeWindow(int index); // 0主菜单,1添加窗口... // menuwidget.cpp void MenuWidget::on_addButton_clicked(){ emit changeWindow(1); } // mainwidget.cpp connect(menu, MenuWidget::changeWindow, [](int index){ stackLayout-setCurrentIndex(index); });返回按钮的实现更简单void AddStudentWidget::on_returnButton_clicked(){ emit changeWindow(0); // 返回主菜单 }4. 功能模块优化技巧4.1 输入验证在添加/修改学生信息时必须验证学号是否重复遍历现有数据成绩是否在0-100范围内必填字段是否为空// 示例学号查重 bool isDuplicate(int id){ QFile file(students.txt); // ...打开文件 while(!in.atEnd()){ QStringList data in.readLine().split( ); if(data[1].toInt() id) return true; } return false; }4.2 排序算法实现四种排序方式数学/英语/C语言/平均分可以共用一套逻辑// sortwidget.cpp void SortWidget::sortData(int subject){ QVectorStudentInfo students; // ...读取数据到students std::sort(students.begin(), students.end(), [](const StudentInfo a, const StudentInfo b){ switch(subject){ case 0: return a.math b.math; case 1: return a.english b.english; case 2: return a.languageC b.languageC; default: return a.avg b.avg; } }); // 更新表格显示... }4.3 表格展示优化QTableWidget的实用设置// 设置表头 QStringList headers; headers 姓名 学号 数学 英语 C语言 平均分; ui-tableWidget-setHorizontalHeaderLabels(headers); // 自动调整列宽 ui-tableWidget-horizontalHeader()-setSectionResizeMode(QHeaderView::Stretch); // 填充数据 for(int i0; istudents.size(); i){ ui-tableWidget-setItem(i, 0, new QTableWidgetItem(students[i].name)); // ...其他列 }5. 常见问题解决方案中文乱码问题 在main.cpp中添加QTextCodec::setCodecForLocale(QTextCodec::codecForName(UTF-8));数据文件路径问题 建议使用绝对路径或者将数据文件放在可执行文件同级目录QString path QCoreApplication::applicationDirPath() /students.txt;内存泄漏检查 在pro文件中添加CONFIG debug DEFINES QT_DEBUG这个项目最让我头疼的是文件读写时的异常处理。后来总结出三板斧每次操作前检查文件是否存在读写操作放在try-catch块中重要操作前备份数据文件