基于QT的学生信息管理系统软件开发

基于QT的学生信息管理系统软件开发

0-源码

先奉上源码地址: QT-Information-Management-System

1-写在前面

软件功能及开发环境:
1-1.实现对excel读取写入功能
1-2.完成从excel文件导入到数据库sqlite的功能
1-3.完成将sqlite数据显示在tableview的功能
1-4.实现对数据库数据查找的功能
1-5.实现截取控件保存为图片功能
1-6.实现自定义软件边框的功能
1-7.本软件是基于QT Creator 4.0.3在win10下开发

2-excel的读取与写入

在设计中主要的功能为写入数据,重点是对开源的excel操作库的运用。关于excel的读写库请参考:qtxlsx
这里还是简单说一下库的加入方法:
2-1.首先到github下载源码以备使用:QtXlsxWriter
2-2.将源码解压到QT工程目录下,可以新建一个文件夹3rdparty存放库文件:
|-- project. pro
|-- …
|-- 3rdparty\
| |-- qtxlsx\
| |
2-3.在完成以上的准备工作之后,将刚刚新建的文件夹路径添加到工程文件中:

include (3rdparty/src/xlsx/qtxlsx.pri)

2-4.添加完成之后就可以通过在文件中添加头文件#include "xlsxdocument.h" 来对excel进行操作
图1为导出excel模板的软件界面:
导出*.xlsx模板文件

图1 导出*.xlsx模板文件

2-5代码实现:
这里还做了一个按键下拉功能:

/***Function: export excel model*/
void MainWindow::btnExportExcelsetting(void){
    connect(exportMenu,SIGNAL(triggered(QAction *)),this,SLOT(onExportMenuTriggered(QAction *)));
    exportMenu->addAction(exportMenu_action_scholarship);
    exportMenu->addAction(exportMenu_action_stipend);
    exportMenu_action_scholarship->setText(QStringLiteral("Export Scholarship model"));
    exportMenu_action_stipend->setText(QStringLiteral("Export Stipend model"));
    exportMenu->setStyleSheet("font: 8pt ,'Microsoft YaHei'");
    ui->btnExportExcel->setMenu(exportMenu);
}  

以下是具体的excel写入操作函数

void MainWindow::onExportMenuTriggered(QAction *action){
    QXlsx::Document xlsx;
    xlsx.write("A1", QStringLiteral("StudentName"));
    xlsx.write("B1", QStringLiteral("IDNumber"));
    xlsx.write("C1", QStringLiteral("StudentID"));
    xlsx.write("D1", QStringLiteral("College"));
    xlsx.write("E1", QStringLiteral("Class"));
    xlsx.write("H1", QStringLiteral("IssueDate"));
    xlsx.write("I1", QStringLiteral("Issuer"));
    QString modelFileName;
    if (action == exportMenu_action_scholarship){
        xlsx.write("F1", QStringLiteral("ScholarshipName"));
        xlsx.write("G1", QStringLiteral("ScholarshipAmount"));
        QString strModelFile = QStringLiteral("\\ScholarshipModel") + ".xlsx";
        modelFileName = QFileDialog::getSaveFileName(this,QStringLiteral("ScholarshipModel"),strModelFile,"EXCEL (*.xlsx)");
    }
    else if (action == exportMenu_action_stipend){
        xlsx.write("F1", QStringLiteral("StipendName"));
        xlsx.write("G1", QStringLiteral("StipenAmount"));
        QString strModelFile = QStringLiteral("\\StipendModel") + ".xlsx";
        modelFileName = QFileDialog::getSaveFileName(this,QStringLiteral("StipendModel"),strModelFile,"EXCEL (*.xlsx)");
    }
    xlsx.setDocumentProperty("title", QStringLiteral("ExcelModel"));
    xlsx.setDocumentProperty("creator", QStringLiteral("https://github.com/pyuxing"));
    if (!modelFileName.isNull())
    {
        xlsx.saveAs(modelFileName);
    }
}

3-excel文件的导入到sqlite数据库

由于在实际操作中发现,并没有能够直接将excel的数据导入sqlite的函数,所以软件使用以下策略:
*.xlsx – *.CSV-- *.db 也就先把excel文件存为CSV文件,再将CSV文件存为sqlite数据库文件。
以下为具体代码实现:
3-1 excel文件存储为CSV文件:

/***Function: transfer excel file to CSV*/
bool connection::tranExcelToCSV(QString InputExcel,QString OutputCSV){

    //Using QAxObject in a background thread must be initialized first
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    QAxObject excel("Excel.Application");
    excel.setProperty("Visible", false); //NO show
    excel.setProperty("DisplayAlerts", false);//NO warning
    QAxObject * workBooks = excel.querySubObject("WorkBooks");

    workBooks->dynamicCall("Open(const QString&)", QString(InputExcel));
    QAxObject *workbook = excel.querySubObject("ActiveWorkBook");

    QAxObject * worksheet = workbook->querySubObject("Worksheets(int)", 1);
    QAxObject *first_sheet = worksheet->querySubObject("Rows(int)", 1);//delete the first row
    first_sheet->dynamicCall("delete");
    worksheet->dynamicCall("SaveAs(const QString&,int)",QDir::toNativeSeparators(OutputCSV),6);
    workbook->dynamicCall("Close (Boolean)", false); //close file
    excel.dynamicCall("Quit(void)");//close excel
    return true;
}

3-2 CSV文件导入sqlite数据库中
这里使用QTextStream进行文件流的读入:

/***s: import data of CSV file to sqlite*/
bool connection::createConnection(QString inputFilepath,QString outputFilepath,QString tableName)
{
    QFile file(inputFilepath);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
     {
          std::cerr << "Cannot open file for reading: "
                    << qPrintable(file.errorString()) << std::endl;
          return false;
     }

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(outputFilepath);
    if(!db.open())
    {
        QMessageBox::critical(0 , "Can not open database",
                                  "Unable to establish a database connection.",QMessageBox::Cancel);
        std::cerr<<"stop!";
        return false;
    }

    QSqlQuery query;
    query.exec("create table "+ tableName + "(stuName varchar(50),idNum varchar(50),"
                                         "stuID varchar(50),stuCollege varchar(50),"
                                         "stuClass varchar(50),projName varchar(50),"
                                         "projAmount varchar(50),projDate varchar(50),"
                                         "projIssuer varchar(50), primary key(projName,projDate,idNum))");
    QStringList list;
    list.clear();
    QTextStream in(&file);  //QTextStream reading data
    while(!in.atEnd())
    {
       QString fileLine = in.readLine();//from 1st line to next
       list = fileLine.split(",", QString::SkipEmptyParts);

       qDebug()<<list.at(0)<<list.at(1);

       query.prepare("INSERT INTO " + tableName + " (stuName,idNum,stuID,stuCollege,stuClass,projName,projAmount,projDate,projIssuer)"
                                 " VALUES (:stuName,:idNum,:stuID,:stuCollege,:stuClass,:projName,:projAmount,:projDate,:projIssuer)");

       query.bindValue(":stuName", list.at(0)); //bind data
       query.bindValue(":idNum", list.at(1));
       query.bindValue(":stuID", list.at(2));
       query.bindValue(":stuCollege", list.at(3));
       query.bindValue(":stuClass", list.at(4));
       query.bindValue(":projName", list.at(5));
       query.bindValue(":projAmount", list.at(6));
       query.bindValue(":projDate", list.at(7));
       query.bindValue(":projIssuer", list.at(8));

       query.exec();
    }
    if(!db.commit()){
        qDebug()<<"ERROR commit";
    }
    query.clear();
    db.close();
    return true;
}

4-sqlite数据显示在tableview中

这里主要用到QSqlTableModel类,具体实现如下(这里以导入助学金信息为例,奖学金类似):

void MainWindow::on_btnScholarship_clicked()
{
    connection con;
    if(!con.createConnection(scholarshipPath,"scholarship.db",scholarshipTable))
    {
        qDebug() << "Can not create connection";
        MyMessageBox::showMyMessageBox(this, QStringLiteral("Error Reminder"), QStringLiteral("Please make sure the scholarship data\n import is correct!"), MESSAGE_WARNNING, BUTTON_OK_AND_CANCEL, true);
    }

    QSqlTableModel *model;
    model = new QSqlTableModel(this);
    model->setTable(scholarshipTable);
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select(); //select the table
    ui->tableviewScholarshipInfo->setModel(model);
    setTableHead(model);
    ui->tableviewScholarshipInfo->setEditTriggers(QAbstractItemView::NoEditTriggers);//Make it uneditable
    ui->tableviewScholarshipInfo->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//Set the column width to automatically adjust according to the text
    ui->tableviewScholarshipInfo->setSelectionBehavior(QAbstractItemView::SelectRows); //Set the selected behavior to select the entire row
    ui->tableviewStipendInfo->setVisible(false);
}

图2为助学金信息显示界面:
助学金信息显示

图2 助学金信息显示

5-实现对数据库数据查找的功能

这里主要用到QSqlQueryModel类,具体实现如下:

/***Function:filter query data*/
bool MainWindow::searchData(QObject *ptrTableviewInfo,QString strHeadItem,QString strExactItem,QString strTableName){
    QSqlQueryModel *model = new QSqlQueryModel(ptrTableviewInfo);
    if((strHeadItem != "TABLE") && (strExactItem != "NO SEARCH")){
        model->setQuery(QString("select * from " + strTableName + " where %1 = '%2'").arg(strHeadItem).arg(strExactItem));
    }
    else{//Did not enter the query content
        MyMessageBox::showMyMessageBox(this, QStringLiteral("Query Reminder"), QStringLiteral("No data to be queried in the database!"), MESSAGE_WARNNING, BUTTON_OK_AND_CANCEL, true);
    }
    model->setHeaderData(0,Qt::Horizontal,"headstuName");
    setTableHead(model);
    QTableView *ptrTableview = qobject_cast<QTableView *>(ptrTableviewInfo);
    ptrTableview->setModel(model);
    if(!ptrTableview->verticalHeader()->count()){
        MyMessageBox::showMyMessageBox(this, QStringLiteral("Query Reminder"), QStringLiteral("No data to be queried in the database!"), MESSAGE_WARNNING, BUTTON_OK_AND_CANCEL, true);
    }
    return true;
}

查询姓名为李雷2的同学的结果显示界面如图3:
数据查询功能

图3 数据查询功能

6-保存学生信息卡为图片

这里实现的功能是截取控件区域为图片,并将其另存为,代码实现如下:

/***Function: save cars as images*/
void MainWindow::on_btn_SaveScreenShot_clicked()
{
    QString strDir = QCoreApplication::applicationDirPath() + QStringLiteral("\\StuInfoCard\\");
    QDir dir(strDir);
    if(!dir.exists()){
        dir.mkdir(strDir);
    }
    QString strFile = strDir + fileStuName + QDateTime::currentDateTime().toString("_yyyyMMddHHmmss") + ".png";
    ui->btn_confirmCloseInfoCard->setVisible(false);
    ui->btn_SaveScreenShot->setVisible(false);
    ui->line_btwSaveConfirm->setVisible(false);
    QPixmap pix = QPixmap::grabWidget(ui->frameInfoDetail);
    ui->btn_confirmCloseInfoCard->setVisible(true);
    ui->btn_SaveScreenShot->setVisible(true);
    ui->line_btwSaveConfirm->setVisible(true);
    QString fileName = QFileDialog::getSaveFileName(this,QStringLiteral("SaveAsImages"),strFile,"PNG (*.png);;BMP (*.bmp);;JPEG (*.jpg *.jpeg)");
    if(!fileName.isNull()){
        pix.save(fileName);
    }
}

保存信息卡界面如图4,保存的卡片信息文件如图5:
保存信息卡功能

图4 保存信息卡功能

保存的卡片信息
图5 保存的卡片信息

7-自定义软件边框

在实现自定义边框的方法上主要参考了Jorgen-VikingGod的 Qt-Frameless-Window-DarkStyle(有具体的实现方法,这里不展开)
前文的软件截图都是在修改过边框下实现的,现在看一下没有自定义边框的时候什么样子的,如图6:
在这里插入图片描述

图5 原始边框界面
自定义边框具体调用方法:

a)将源代码放到自己工程的目录下,并在工程文件下添加路径,比如 INCLUDEPATH +="framelesswindow"
b)在main函数包含头文件#include "framelesswindow.h",具体如下代码所示:

#include "mainwindow.h"
#include "DarkStyle.h"
#include "framelesswindow.h"
int main(int argc, char *argv[]){
    QApplication a(argc, argv);
    a.setStyle(new DarkStyle);
    FramelessWindow framelessWindow;
    MainWindow *mainWindow = new MainWindow;
    framelessWindow.setContent(mainWindow);
    framelessWindow.show();
    return a.exec();
}

8-总结

在功能的实现上将excel数据存入数据库花费了比较多的精力,最后也没实现excel直接存入数据库的方法,而是将其存为CSV文件,再将CSV转存入数据库。这里使用的数据库是QT自带的sqlite数据库,尝试过mysql,但涉及到要为电脑安装数据库,最后没有继续往下做。(ps:采用英文是因为原始版本里有一些真实数据,所以公开版本做此修改) 源码传送门
总之还有很多需要学习的地方,继续加油吧!

PS:公众号上线啦,技术干货分享,欢迎关注。

扫码关注

猜你喜欢

转载自blog.csdn.net/pyuxing/article/details/82903767