QT开发(四)—— 项目实战:学生管理系统,QMessageBox,QTableView和QFile的使用

Hello,大家好,我们又开始来学习新的QT小项目了,这个项目就是学生管理系统,我也是在网易云的课堂上学习的哦,如果想看效果图的直接滑到文章的最下面即可

我们首先说一下,这个项目的组成是一个WindowView和两个Dialog,首先我们来看下主页的WindowView的UI效果

这里写图片描述

可以看到这里非常的简单,只是放了一个Label,主要的功能在于左上角的菜单栏,关于菜单栏如何创建,可以看下UI上

这里写图片描述

双击即可创建菜单栏了,至于他的信号怎么发送,需要点击下面的功能框

这里写图片描述

我们选中Action Editor,然后右键对应的对象即可,所以我们来看下主页的头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "addstuview.h"
#include "querystuview.h"
#include "aboutview.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_menu_add_stu_triggered();

    void on_menu_query_stu_triggered();

    void on_menu_about_triggered();

private:
    Ui::MainWindow *ui;
    AddStuView addView;
    QueryStuView queryView;
    AboutView aboutView;
};

#endif // MAINWINDOW_H

这里我只是定义了对应的添加和查询的两个功能View的对象以及三个菜单栏的槽函数

  • 查询学生
  • 添加学生
  • 关于

那么我们来看下我们的查询学生的View,我们先看头文件

#ifndef ADDSTUVIEW_H
#define ADDSTUVIEW_H

#include <QDialog>

namespace Ui {
class AddStuView;
}

class AddStuView : public QDialog
{
    Q_OBJECT

public:
    explicit AddStuView(QWidget *parent = 0);
    ~AddStuView();

public:
    //初始化
    void init();
    //获取学员信息
    void getStuViewData();
    //打印信息
    void print(const QString str);
    //弹出提示
    void showConfirmDialog(const QString str);
    //检查数据合法
    bool checkData(const QString name,const QString number);
    //保存数据
    void saveStuData();
    //清空当前数据
    void clearNowData();
    //获取性别
    QString getSex();
    //获取爱好
    QString getHobby();

private slots:
    void on_btn_confirm_clicked();

    void on_btn_cancel_clicked();

private:
    Ui::AddStuView *ui;
    bool isDebug = true;
    QString content;
};

#endif // ADDSTUVIEW_H

头文件里,我定义了一堆的公开函数以及两个槽函数,分别是确定和取消,那么我们跟随他的构造函数一起来看看流程吧

我在构造函数中首先初始化了一些状态

void AddStuView::init()
{
    //默认选中
    this->ui->ck_boy->setChecked(true);
    this->ui->cb_blue->setChecked(true);
}

对了,我们来看下UI吧

这里写图片描述

我们初始化的含义就是让性别和兴趣都有默认项

然后就要看下我们的确定按钮的槽函数了,因为一切的逻辑都是从这里开始的

//确定按钮
void AddStuView::on_btn_confirm_clicked()
{
    this->getStuViewData();
}

为了代码的可读性我封装了一个函数getStuViewData来获取用户输入的相关信息

//获取添加学生的信息
void AddStuView::getStuViewData()
{
    QString name = this->ui->et_name->text();
    QString number = this->ui->et_number->text();
    QString age = this->ui->cb_age->currentText();
    QString school = this->ui->cb_school->currentText();

    QString sex = this->getSex();
    QString hobby = this->getHobby();

    this -> content =
            "姓名:" + name + "\n" +
            "学号:" + number+ "\n" +
            "性别:" + sex + "\n" +
            "年龄:" + age + "\n" +
            "学院:" + school + "\n" +
            "爱好:" + hobby ;

    this->print(this -> content);

    //检测参数合法性
    bool isCheck = this->checkData(name,number);

    if(isCheck)
    {
        //弹框提示
        this->showConfirmDialog(this -> content);
    }
}

在这里我又创建了两个函数分别是getSex和getHobby来获取性别和兴趣,因为这些都是多选项所以不方便写一堆在一起

//获取性别
QString AddStuView::getSex()
{
    QString sex = "男";
    bool isCkBoy = this->ui->ck_boy->isChecked();
    bool isCkGirl = this->ui->ck_girl->isChecked();

    if(isCkBoy)
    {
        sex = "男";
    }

    if(isCkGirl)
    {
        sex = "女";
    }
    return sex;
}

//获取爱好
QString AddStuView::getHobby()
{
    QList<QString> list;
    if(this->ui->cb_blue->isChecked())
    {
        list.append("篮球");
    }
    if(this->ui->cb_voll->isChecked())
    {
        list.append("排球");
    }
    if(this->ui->cb_foot->isChecked())
    {
        list.append("足球");
    }
    if(this->ui->cb_bod->isChecked())
    {
        list.append("羽毛球");
    }

    QString hobby;
    for (int i = 0; i < list.length(); ++i) {
        hobby.append(list[i]);
        if(i != (list.length()-1)){
            hobby.append( ",");
        }
    }
    return hobby;
}

当我们获取到相关的信息并且拼接在content变量中的时候我这里检测了一下参数的合法性,预防用户不输入导致我们程序的异常

//检查数据合法
bool AddStuView::checkData(const QString name, const QString number)
{
    if(name.length() == 0)
    {
        //错误提示
        QMessageBox::critical(this,"错误","输入框不能为空","确定");
        return false;
    }
    if(number.length() == 0)
    {
        //错误提示
        QMessageBox::critical(this,"错误","输入框不能为空","确定");
        return false;
    }
    if(number.length() < 10)
    {
        //错误提示
        QMessageBox::critical(this,"错误","学号必须大于等于十位","确定");
        return false;
    }
    return true;
}

这里会弹出QMessageBox的提示框,这是他自带的简洁实现方法,我们在下面还有具体的实现方法,检测完合法性,我们就弹出窗口让用户去确定信息了

//显示Dialog
void AddStuView::showConfirmDialog(const QString str)
{
    QMessageBox box;
    box.setWindowTitle("请确定信息");
    box.setText(str);
    QPushButton* btnConfirm = box.addButton("确定",QMessageBox::AcceptRole);
    QPushButton* btnCancel = box.addButton("取消",QMessageBox::RejectRole);
    box.setDefaultButton(btnConfirm);
    int ret = box.exec();

    switch(ret)
    {
    case QMessageBox::AcceptRole:
        //保存数据
        this->saveStuData();
        //清空当前数据
        this->clearNowData();
        break;
    case QMessageBox::RejectRole:
        box.close();
        break;
    }

}

这里对应的UI是这个效果

这里写图片描述

如果用户点击了确定也就触发了我们的槽,我们在这里做了两件事情

  • 保存数据
  • 清空UI数据

先看清空UI数据,实际上就是还原一下用户的输入,让用户可以继续录入学生信息

//清除当前数据
void AddStuView::clearNowData()
{
    this->ui->et_name->setText("");
    this->ui->et_number->setText("");
    this->ui->ck_boy->setChecked(true);
    this->ui->cb_age->setCurrentIndex(0);
    this->ui->cb_school->setCurrentIndex(0);

    this->ui->cb_blue->setChecked(true);
    this->ui->cb_voll->setChecked(false);
    this->ui->cb_foot->setChecked(false);
    this->ui->cb_bod->setChecked(false);

    //获取焦点
    this->ui->et_name->setFocus();
}

紧接着,我们要保存数据,用到的是QFile

//保存数据
void AddStuView::saveStuData()
{
    QFile file("stu.txt");

    if (!file.open(QIODevice::Append | QIODevice::Text))
    {
        QMessageBox::critical(this,"错误","无法保存文件","确定");
        return;
    }

    QTextStream out(&file);

    //重新拼接数据,便于存储
    QString cnt = this->content
            .replace("\n"," ")
            .remove("姓名:")
            .remove("学号:")
            .remove("性别:")
            .remove("年龄:")
            .remove("学院:")
            .remove("爱好:");

    this->print(cnt);

    //写入
    out << cnt + "\n";
}

这里我们保存数据做了很多的处理

  • 首先是判断下文件是否可以操作
  • 紧接着对content进行过滤去除换行和标题
  • 然后写入

写入之后可以在我们的build工程目录里看下相关信息

这里写图片描述

到这里我们的全部添加数据算是写完了,来看下完整代码

#include "addstuview.h"
#include "ui_addstuview.h"
#include <QString>
#include <QDebug>
#include <QMessageBox>
#include <QPushButton>
#include <QFile>
#include <QTextStream>
#include <QIODevice>

AddStuView::AddStuView(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AddStuView)
{
    ui->setupUi(this);
    this->init();
}

AddStuView::~AddStuView()
{
    delete ui;
}

void AddStuView::init()
{
    //默认选中
    this->ui->ck_boy->setChecked(true);
    this->ui->cb_blue->setChecked(true);
}

//确定按钮
void AddStuView::on_btn_confirm_clicked()
{
    this->getStuViewData();
}
//取消按钮
void AddStuView::on_btn_cancel_clicked()
{
    this->close();
}

//获取添加学生的信息
void AddStuView::getStuViewData()
{
    QString name = this->ui->et_name->text();
    QString number = this->ui->et_number->text();
    QString age = this->ui->cb_age->currentText();
    QString school = this->ui->cb_school->currentText();

    QString sex = this->getSex();
    QString hobby = this->getHobby();

    this -> content =
            "姓名:" + name + "\n" +
            "学号:" + number+ "\n" +
            "性别:" + sex + "\n" +
            "年龄:" + age + "\n" +
            "学院:" + school + "\n" +
            "爱好:" + hobby ;

    this->print(this -> content);

    //检测参数合法性
    bool isCheck = this->checkData(name,number);

    if(isCheck)
    {
        //弹框提示
        this->showConfirmDialog(this -> content);
    }
}

//打印
void AddStuView::print(const QString str)
{
    if(this->isDebug)
    {
        qDebug() << str;
    }
}

//显示Dialog
void AddStuView::showConfirmDialog(const QString str)
{
    QMessageBox box;
    box.setWindowTitle("请确定信息");
    box.setText(str);
    QPushButton* btnConfirm = box.addButton("确定",QMessageBox::AcceptRole);
    QPushButton* btnCancel = box.addButton("取消",QMessageBox::RejectRole);
    box.setDefaultButton(btnConfirm);
    int ret = box.exec();

    switch(ret)
    {
    case QMessageBox::AcceptRole:
        //保存数据
        this->saveStuData();
        //清空当前数据
        this->clearNowData();
        break;
    case QMessageBox::RejectRole:
        box.close();
        break;
    }

}

//检查数据合法
bool AddStuView::checkData(const QString name, const QString number)
{
    if(name.length() == 0)
    {
        //错误提示
        QMessageBox::critical(this,"错误","输入框不能为空","确定");
        return false;
    }
    if(number.length() == 0)
    {
        //错误提示
        QMessageBox::critical(this,"错误","输入框不能为空","确定");
        return false;
    }
    if(number.length() < 10)
    {
        //错误提示
        QMessageBox::critical(this,"错误","学号必须大于等于十位","确定");
        return false;
    }
    return true;
}

//保存数据
void AddStuView::saveStuData()
{
    QFile file("stu.txt");

    if (!file.open(QIODevice::Append | QIODevice::Text))
    {
        QMessageBox::critical(this,"错误","无法保存文件","确定");
        return;
    }

    QTextStream out(&file);

    //重新拼接数据,便于存储
    QString cnt = this->content
            .replace("\n"," ")
            .remove("姓名:")
            .remove("学号:")
            .remove("性别:")
            .remove("年龄:")
            .remove("学院:")
            .remove("爱好:");

    this->print(cnt);

    //写入
    out << cnt + "\n";
}

//清除当前数据
void AddStuView::clearNowData()
{
    this->ui->et_name->setText("");
    this->ui->et_number->setText("");
    this->ui->ck_boy->setChecked(true);
    this->ui->cb_age->setCurrentIndex(0);
    this->ui->cb_school->setCurrentIndex(0);

    this->ui->cb_blue->setChecked(true);
    this->ui->cb_voll->setChecked(false);
    this->ui->cb_foot->setChecked(false);
    this->ui->cb_bod->setChecked(false);

    //获取焦点
    this->ui->et_name->setFocus();
}

//获取性别
QString AddStuView::getSex()
{
    QString sex = "男";
    bool isCkBoy = this->ui->ck_boy->isChecked();
    bool isCkGirl = this->ui->ck_girl->isChecked();

    if(isCkBoy)
    {
        sex = "男";
    }

    if(isCkGirl)
    {
        sex = "女";
    }
    return sex;
}

//获取爱好
QString AddStuView::getHobby()
{
    QList<QString> list;
    if(this->ui->cb_blue->isChecked())
    {
        list.append("篮球");
    }
    if(this->ui->cb_voll->isChecked())
    {
        list.append("排球");
    }
    if(this->ui->cb_foot->isChecked())
    {
        list.append("足球");
    }
    if(this->ui->cb_bod->isChecked())
    {
        list.append("羽毛球");
    }

    QString hobby;
    for (int i = 0; i < list.length(); ++i) {
        hobby.append(list[i]);
        if(i != (list.length()-1)){
            hobby.append( ",");
        }
    }
    return hobby;
}

我们现在开始看下查询的代码,现在看下头文件

#ifndef QUERYSTUVIEW_H
#define QUERYSTUVIEW_H

#include <QDialog>
#include <QString>
#include <QList>
#include <QStandardItem>
#include <QStandardItemModel>
#include <QStringList>

namespace Ui {
class QueryStuView;
}

class QueryStuView : public QDialog
{
    Q_OBJECT

public:
    explicit QueryStuView(QWidget *parent = 0);
    ~QueryStuView();

private:
    //初始化
    void init();
    //获取输入框数据
    bool getQueryText();
    //获取文件数据
    void getFileData();
    //解析文件数据
    void parsingFileData();
    //显示UI
    void showUI(int row,QStringList list);

private slots:
    void on_btn_query_stu_clicked();

private:
    Ui::QueryStuView *ui;
    QString queryText;
    int index = 0;
    QList<QString> list_line;
    QStandardItemModel* model;

};

#endif // QUERYSTUVIEW_H

头文件里,我们注意到有一个对象QStandardItemModel,这个就是实现QTableView的重要部分了,我们先看下UI

这里写图片描述

那么我们怎么实现呢?还是按照逻辑去跟代码

void QueryStuView::init()
{
    //实例化
    this->model = new QStandardItemModel;

    //设置表头
    this->model->setHorizontalHeaderItem(0,new QStandardItem("姓名"));
    this->model->setHorizontalHeaderItem(1,new QStandardItem("学号"));
    this->model->setHorizontalHeaderItem(2,new QStandardItem("性别"));
    this->model->setHorizontalHeaderItem(3,new QStandardItem("年龄"));
    this->model->setHorizontalHeaderItem(4,new QStandardItem("院系"));
    this->model->setHorizontalHeaderItem(5,new QStandardItem("爱好"));

    //设置视图
    this->ui->tab_stu_view->setModel(model);

    //设置列宽
    this->ui->tab_stu_view->setColumnWidth(1,500);
}

可以看到,我们初始化的时候,就把QStandardItemModel的对象new出来了,然后设置了一下头部的标题

然后要看触发的槽,也就是搜索按钮了

//点击搜索
void QueryStuView::on_btn_query_stu_clicked()
{
    qDebug() << "点击搜索";
    this->index = this->ui->cb_conditions->currentIndex();
    bool isHave = this->getQueryText();

    if(isHave)
    {
        //开始查询文件
        this->getFileData();
    }
}

我们点击搜索后,获取了当前的筛选条件以及输入框内的文字

//获取输入框数据
bool QueryStuView::getQueryText()
{
    //获取输入框
    this-> queryText = this->ui->et_query->text();
    if(this->queryText.length() == 0)
    {
        QMessageBox::critical(this,"错误","输入框不能为空","确定");
        return false;
    }
    return true;

}

如果你输入有内容,我们就开始查询下我们的文件

//获取文件数据
void QueryStuView::getFileData()
{
    qDebug() << "获取文件";

    //清理数据
    this->list_line.clear();
    this->model->clear();

    QFile file("stu.txt");
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QMessageBox::critical(this,"错误","无法打开文件","确定");
        return;
    }
    QTextStream in(&file);

    while (!in.atEnd()) {
        QString line = in.readLine();
        this->list_line.append(line);
    }
    file.close();

    //解析文件数据
    this->parsingFileData();
}

这里我们获取到文件数据list_line后开始去解析

//解析文件数据
void QueryStuView::parsingFileData()
{
    qDebug() << "解析文件";
    int row = 0;
    //遍历数据
    for (int i = 0; i < this->list_line.length(); ++i) {
        QString str = this->list_line.at(i);
        //分割
        QStringList list = (str.split(" "));
        qDebug() << index;
        //按照条件
        switch(this->index)
        {
        //姓名
        case 0:
            if(this->queryText == list.at(0)){
                this->showUI(row++,list);
            }
            break;
            //学号
        case 1:
            if(this->queryText == list.at(1)){
                this->showUI(row++,list);
            }
            break;
            //院系
        case 2:
            if(this->queryText == list.at(4)){
                this->showUI(row++,list);
            }
            break;
        }

    }

}

遍历后根据筛选条件来显示具体的数据

//显示UI
void QueryStuView::showUI(int row,QStringList list)
{
    qDebug() << "显示UI:" << list.length();
    for (int i = 0; i < list.length(); ++i) {
        this->model ->setItem(row,i,new QStandardItem(list.at(i)));
    }
}

嗯 ,到这里也就完成了我们的查询功能了,来看下完整的代码

#include "querystuview.h"
#include "ui_querystuview.h"
#include <QMessageBox>
#include <QFile>
#include <QIODevice>
#include <QTextStream>
#include <QDebug>

QueryStuView::QueryStuView(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::QueryStuView)
{
    ui->setupUi(this);

    this->init();
}

QueryStuView::~QueryStuView()
{
    delete ui;
}

void QueryStuView::init()
{
    //实例化
    this->model = new QStandardItemModel;

    //设置表头
    this->model->setHorizontalHeaderItem(0,new QStandardItem("姓名"));
    this->model->setHorizontalHeaderItem(1,new QStandardItem("学号"));
    this->model->setHorizontalHeaderItem(2,new QStandardItem("性别"));
    this->model->setHorizontalHeaderItem(3,new QStandardItem("年龄"));
    this->model->setHorizontalHeaderItem(4,new QStandardItem("院系"));
    this->model->setHorizontalHeaderItem(5,new QStandardItem("爱好"));

    //设置视图
    this->ui->tab_stu_view->setModel(model);

    //设置列宽
    this->ui->tab_stu_view->setColumnWidth(1,500);
}

//点击搜索
void QueryStuView::on_btn_query_stu_clicked()
{
    qDebug() << "点击搜索";
    this->index = this->ui->cb_conditions->currentIndex();
    bool isHave = this->getQueryText();

    if(isHave)
    {
        //开始查询文件
        this->getFileData();
    }
}

//获取输入框数据
bool QueryStuView::getQueryText()
{
    //获取输入框
    this-> queryText = this->ui->et_query->text();
    if(this->queryText.length() == 0)
    {
        QMessageBox::critical(this,"错误","输入框不能为空","确定");
        return false;
    }
    return true;

}
//获取文件数据
void QueryStuView::getFileData()
{
    qDebug() << "获取文件";

    //清理数据
    this->list_line.clear();
    this->model->clear();

    QFile file("stu.txt");
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QMessageBox::critical(this,"错误","无法打开文件","确定");
        return;
    }
    QTextStream in(&file);

    while (!in.atEnd()) {
        QString line = in.readLine();
        this->list_line.append(line);
    }
    file.close();

    //解析文件数据
    this->parsingFileData();
}

//解析文件数据
void QueryStuView::parsingFileData()
{
    qDebug() << "解析文件";
    int row = 0;
    //遍历数据
    for (int i = 0; i < this->list_line.length(); ++i) {
        QString str = this->list_line.at(i);
        //分割
        QStringList list = (str.split(" "));
        qDebug() << index;
        //按照条件
        switch(this->index)
        {
        //姓名
        case 0:
            if(this->queryText == list.at(0)){
                this->showUI(row++,list);
            }
            break;
            //学号
        case 1:
            if(this->queryText == list.at(1)){
                this->showUI(row++,list);
            }
            break;
            //院系
        case 2:
            if(this->queryText == list.at(4)){
                this->showUI(row++,list);
            }
            break;
        }

    }

}

//显示UI
void QueryStuView::showUI(int row,QStringList list)
{
    qDebug() << "显示UI:" << list.length();
    for (int i = 0; i < list.length(); ++i) {
        this->model ->setItem(row,i,new QStandardItem(list.at(i)));
    }
}

好,最后一个关于,其实就是个UI

这里写图片描述

有兴趣的可以关注下我的公众号和加群,我就不过多打广告了

来看下实际的效果吧

这里写图片描述

源码下载:点击下载

猜你喜欢

转载自blog.csdn.net/qq_26787115/article/details/79911632
今日推荐