一 需求

基于Qt框架开发现代化学生信息管理系统,要求如下:
采用MVC架构+MySQL 8.0+ODBC,提供完整的学生信息管理功能。系统支持学生信息的增删改查、数据搜索、Excel导出、数据库备份与恢复等核心功能,适用于教育机构进行学生信息管理。
【核心模块】
MainWindow:主界面控制器,负责UI展示和用户交互
StudentPresenter:业务逻辑层,处理用户操作和数据流转
StudentModel:数据模型层,封装数据库操作
DatabaseHandler:数据库访问层,提供SQL操作接口
ExcelExporter:数据导出模块,支持CSV格式导出
【数据展示】
表格视图:清晰的数据表格展示,支持列宽自适应
分页显示:大量数据的分页处理
排序功能:按任意字段排序
选择操作:单行选择,支持快速编辑
【数据管理】
数据库备份:完整的数据库备份功能
数据恢复:从备份文件恢复数据
Excel导出:支持CSV格式导出,兼容Excel打开
数据完整性:事务处理确保数据一致性
【高级功能】
智能搜索:支持多条件组合搜索
数据统计:学生数量统计和院系分布
错误处理:完善的错误提示和异常处理
用户友好:直观的操作界面和状态提示

二 软件框架

在这里插入图片描述

三 软件代码实现

3.1 项目文件结构

StudentInfoSystem/
├── StudentInfoSystem.pro
├── main.cpp
├── MainWindow.h
├── MainWindow.cpp
├── MainWindow.ui
├── StudentPresenter.h
├── StudentPresenter.cpp
├── StudentModel.h
├── StudentModel.cpp
├── DatabaseHandler.h
├── DatabaseHandler.cpp
├── ExcelExporter.h
├── ExcelExporter.cpp

3.2 头文件实现

3.2.1 DatabaseHandler.h
#ifndef DATABASEHANDLER_H
#define DATABASEHANDLER_H


#include <QObject>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QVariantMap>
#include <QList>

class DatabaseHandler : public QObject
{
    Q_OBJECT

public:
    explicit DatabaseHandler(QObject *parent = nullptr);
    ~DatabaseHandler();

    bool connect();     //数据库连接,odbc方式
    void disconnect();
    bool isConnected() const;       //是否连接成功

    bool execute(const QString &query);     //
    QList<QVariantMap> executeQuery(const QString &query);

    bool insert(const QString &table, const QVariantMap &data);
    bool update(const QString &table, const QVariantMap &data, const QString &where);
    bool deleteRecord(const QString &table, const QString &where);
    QList<QVariantMap> select(const QString &table, const QStringList &columns,
                             const QString &where = "", const QString &orderBy = "");

    bool backupDatabase(const QString &fileName);   //备份数据库
    bool restoreDatabase(const QString &fileName);  //恢复数据库

    QString lastError() const;

private:
    QSqlDatabase m_database;
    QString m_lastError;

    QString buildInsertSQL(const QString &table, const QVariantMap &data);
    QString buildUpdateSQL(const QString &table, const QVariantMap &data, const QString &where);
    QString buildSelectSQL(const QString &table, const QStringList &columns,
                         const QString &where, const QString &orderBy);
};


#endif // DATABASEHANDLER_H
3.2.2 ExcelExporter.h
#ifndef EXCELEXPORTER_H
#define EXCELEXPORTER_H

#include <QObject>
#include <QList>
#include <QVariant>
struct Student;

class ExcelExporter : public QObject
{
    Q_OBJECT

public:
    explicit ExcelExporter(QObject *parent = nullptr);
    //以csv格式导出
    bool exportToCsv(const QString &fileName, const QList<Student> &students);

private:
    QString escapeCsvField(const QString &field);
};


#endif // EXCELEXPORTER_H
3.2.3 MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include "StudentPresenter.h"


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void onAddStudent();
    void onEditStudent();
    void onDeleteStudent();
    void onSearch();    //搜索
    void onClearSearch();   //清除搜索字段
    void onExportToExcel();
    void onBackupDatabase();
    void onRestoreDatabase();
    void onRefresh();
    void onStatistics();

    void onStudentAdded(bool success, const QString &message);
    void onStudentUpdated(bool success, const QString &message);
    void onStudentDeleted(bool success, const QString &message);
    void onDataLoaded(bool success, const QString &message);
    void onStatisticsLoaded(const QVariantMap &stats);

    void onTableDoubleClicked(const QModelIndex &index);

private:
    void setupUI();
    void setupConnections();
    void setupTable();
    void showStatusMessage(const QString &message, bool isError = false);
    void clearForm();
    void loadStudentToForm(const Student &student);

private:
    Ui::MainWindow *ui;
    StudentPresenter *m_presenter;
    QStandardItemModel *m_tableModel;
    QSortFilterProxyModel *m_proxyModel;
};

#endif // MAINWINDOW_H
3.2.4 StudentModel.h
#ifndef STUDENTMODEL_H
#define STUDENTMODEL_H

#include <QObject>
#include <QList>
#include <QVariantMap>
#include "DatabaseHandler.h"
#include "ExcelExporter.h"

struct Student;

//数据模型层,封装数据库操作

class StudentModel : public QObject
{
    Q_OBJECT

public:
    explicit StudentModel(QObject *parent = nullptr);
    ~StudentModel();

    void addStudent(const Student &student);
    void updateStudent(const Student &student);
    void deleteStudent(int id);
    QList<Student> loadAllStudents();
    QList<Student> searchStudents(const QString &keyword);  //搜索关键字
    void exportToExcel(const QString &fileName, const QList<Student> &students);    //导出Excel
    void backupDatabase(const QString &fileName);
    void restoreDatabase(const QString &fileName);
    QVariantMap getStatistics();

signals:
    void studentAdded(bool success, const QString &message);
    void studentUpdated(bool success, const QString &message);
    void studentDeleted(bool success, const QString &message);
    void dataLoaded(bool success, const QString &message);
    void exportFinished(bool success, const QString &message);
    void backupFinished(bool success, const QString &message);
    void restoreFinished(bool success, const QString &message);

private:
    DatabaseHandler *m_dbHandler;
    ExcelExporter *m_excelExporter;

    bool initializeDatabase();
    Student studentFromMap(const QVariantMap &map);
    QVariantMap studentToMap(const Student &student);
};


#endif // STUDENTMODEL_H
3.2.5 StudentPresenter.h
#ifndef STUDENTPRESENTER_H
#define STUDENTPRESENTER_H
#include <QObject>
#include <QList>
#include <QVariantMap>
#include "StudentModel.h"


struct Student {
    int id;
    QString studentId;
    QString name;
    QString gender;
    int age;
    QString department;
    QString major;
    QString phone;
    QString email;
    QString enrollmentDate;

    Student() : id(0), age(18) {}
};


class StudentPresenter : public QObject
{
    Q_OBJECT

public:
    explicit StudentPresenter(QObject *parent = nullptr);
    ~StudentPresenter();

    void addStudent(const Student &student);
    void updateStudent(const Student &student);
    void deleteStudent(int id);
    void loadAllStudents();
    void searchStudents(const QString &keyword);
    void exportToExcel(const QString &fileName);
    void backupDatabase(const QString &fileName);
    void restoreDatabase(const QString &fileName);
    void loadStatistics();

    QList<Student> getStudents() const { return m_students; }

signals:
    void studentAdded(bool success, const QString &message);
    void studentUpdated(bool success, const QString &message);
    void studentDeleted(bool success, const QString &message);
    void dataLoaded(bool success, const QString &message);
    void statisticsLoaded(const QVariantMap &stats);
    void exportFinished(bool success, const QString &message);
    void backupFinished(bool success, const QString &message);
    void restoreFinished(bool success, const QString &message);

private:
    StudentModel *m_model;
    QList<Student> m_students;
};

#endif // STUDENTPRESENTER_H

3.3 CPP实现

整理不易,可从下载

四 运行视频

学生信息管理系统 2025-10-29 16-31-26

五 源码链接

源码链接

六 其他

6.1 QSortFilterProxyModel简介

QSortFilterProxyModel是Qt框架中用于数据排序和过滤的代理模型类。它作为源模型和视图之间的中间层,能够在不修改源数据的情况下对数据进行重组和筛选。
基本使用流程
使用QSortFilterProxyModel需要三个步骤:首先创建源模型并加载数据,然后实例化代理模型并通过setSourceModel()方法设置源模型,最后在视图组件中使用setModel()方法设置代理模型。这种设计使得同一个源模型可以在多个视图中以不同的方式显示
自定义排序实现
要实现自定义排序逻辑,需要子类化QSortFilterProxyModel并重写lessThan()方法17。在该方法中,可以通过sourceModel()->data()获取源模型的实际数据,然后根据不同的列数据类型实现相应的比较逻辑7。
高级过滤功能
代理模型支持多种过滤模式,包括正则表达式、通配符和固定字符串匹配。通过setFilterKeyColumn()可以指定过滤应用的具体列3。

Odbc安装详细步骤参考https://blog.csdn.net/wenxuankeji/article/details/146351177

6.2 StudentPresenter在代码中的角色和作用?

MVP中的p角色,相比于mvc的c角色,具有以下好处:p只需要专注业务逻辑协调,而c既要处理用户交互,又要处理业务逻辑,容易造成胖控制器的问题。
View:专注UI展示与交互
Model:专注数据处理
具体好处分析:
1, 测试友好性,方便单元测试
2, 业务逻辑集中管理。
3, 解耦view和model:view不需要知道model的实现细节,view只关心UI和数据收集,presenter处理所有协调工作,协调多个model操作。
// View不需要知道Model的实现细节
void MainWindow::onAddStudent() {
// View只关心UI和数据收集
Student student = collectFormData();
m_presenter->addStudent(student); // 不关心具体实现
}

// Presenter处理所有协调工作
void StudentPresenter::addStudent(const Student &student) {
// 协调多个Model操作
m_model->beginTransaction();
try {
m_model->addStudent(student);
m_model->updateStatistics();
m_model->commitTransaction();
emit studentAdded(true, “添加成功”);
} catch (const DatabaseException &e) {
m_model->rollbackTransaction();
emit studentAdded(false, e.message());
}
}
4, 前端和后端可以并行开发
Presenter层作为"业务协调者",将原本分散在UI中的业务逻辑抽取出来,形成一个清晰的服务层,让每个组件都专注于自己的核心职责。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐