关闭

学生管理系统

154人阅读 评论(1) 收藏 举报
分类:
首先这个程序使用本地文件存放数据,在第一次运行的时候会在程序目录内生成一个info的目录,里面生成一些文件,这些文件即为程序所用的数据,千万不要 改文件内容或者文件名之类的,如果改了,就会导致程序崩溃(linux下为段错误,win7下为程序未响应,另外如果你装360的话,360可能会在次刻 跳出来直接把你的程序干掉,原因未知。。。学生管理系统 - 板烧鱿鱼 - 我只是个路人甲,别在意我


如果发送这种情况,直接删掉info目录即可,程序再次启动时会重新创建,但你以前的数据也就木有了,于是你可以在正常的时候把./info目录以及目录里的文件拷贝一份,下次出问题的时候就可以用备份恢复数据了学生管理系统 - 板烧鱿鱼 - 我只是个路人甲,别在意我


程序启动后是个登陆框,很简单


这个系统我做了2种权限,一个是唯一的超级账户
账号 teacher
密码 123456
这个账户拥有这个程序的所有权限,另外的就是无数个学生账户了
登陆老师账户后


 这里是2张表,其实这样的表模型有现成的QTableWidget,但一方面为了“练手”,另一方面由于要数据同步,所以这2张表我都是使用的自定义模型学生管理系统 - 板烧鱿鱼 - 我只是个路人甲,别在意我,均派生QAbstractModel


这2张表数据是同步的,把成绩表中的末位学生名字改后,信息表中名字也会随之改变
删除:用于删除一整行(即一个学生)删除焦点所在的行,如果视图丢失焦点(比如你鼠 标点了别的地方,他会删除第一行,所以小心使用
添加: 在表最下方添加一行空行,用于增加学生

由于2张表(模型)数据同步,所以上面2个对某张表(模型)的操作都会同步到另一张表上

写入:在视图上修改后的数据不会立刻写进数据文件(info目录),只有点击写入后才会写入文件,这类似于一个保存的作用

然后就是自定义委托了
2个模型info和exam我各做了一个


首先是exam模型,这个主要存放学生的考试成绩,其成绩在模型内使用QString操作,所以你不用担心数据的存放问题,也不用担心往成绩栏(要求输入整数)栏里误输了个字幕而导致程序出现问题,随之而来的问题是在成绩栏你也可以输入字符。。。学生管理系统 - 板烧鱿鱼 - 我只是个路人甲,别在意我


exam模型的自定义委托的作用是提示,如果你再成绩栏里输入的不是数字或者输入的数字不知0-100的整数,那字体就会显示为红色,用于提醒用户(老师),你的输入可能有误


 info模型的自定义委托主要用于输入,性别一栏只有2个选择,学院一栏选项也不多(我假设一个学校的学院不是灰常多。。)遇到这种情况,用一个下拉菜单提供选项比让用户(老师)直接输入更为便(an)捷(quan);

info模型的自定义委托就是实现这个功能



 ~~~~~华丽的分割线~~~~~
此时你可能注意到了,在信息 表中,有密码 这一列,
程序设定是学生利用他的学号和密码登陆,老师可以看到/更改学生的密码,就是我开始说道的权限

然后(老师)关闭程序后,再次登陆,某位学生输入了他的账号(学号),(老师告诉他的)密码,
然后学生的登陆界面就比较简答了,既能查看自己的考试成绩(话说学生没必要查看自己性别,年龄之类的信息了吧学生管理系统 - 板烧鱿鱼 - 我只是个路人甲,别在意我

学生登陆框的标题会提示登陆的是那位学生,学生唯一可以做的就是修改登陆密码


 
当然,如果你忘了密码,可以去找老师,他可以帮你改密码学生管理系统 - 板烧鱿鱼 - 我只是个路人甲,别在意我

~~~~
http://pan.baidu.com/s/1nt2y9gl
注意这里文件是我在linux(ubuntu14.04)下写的文件,在win系统下编译没问题,但打开可能会出现乱码.如果有这里问题,下面有源代码(PS:源代码里没有.pro文件的源代码)
这里pro文件写好了,编译的时候记得打开编译器的c++11选择(如果你没开的话)

~~~~~以下是源代码~~~~~
buildFile.h
#ifndef BUILDFILE_H_
#define BUILDFILE_H_
#include<QDir>
#include<QFile>
void buildFile();
#endif


buildFile.cxx
#include"buildFile.h"
#include<QTextStream>
void buildFile()
{
  QString infoPath = QDir::currentPath();
  infoPath = infoPath + "/info";
  QDir dirs;
  dirs.mkpath(infoPath);  //创建目录
  QString name = infoPath + "/name.txt";
  QString chinese = infoPath + "/chinese.txt";
  QString match = infoPath + "/match.txt";
  QString english = infoPath + "/english.txt";
  QString history = infoPath + "/history.txt";
  QString cplusplus = infoPath + "/c++.txt";
  QString number = infoPath + "/number.txt";
  QString passWD = infoPath + "/passWD.txt";
  QString sex = infoPath + "/sex.txt";
  QString age = infoPath + "/age.txt";
  QString college = infoPath + "/college.txt";
  QFile file;
  if(!file.exists(name))
   {
    QFile newFile(name);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(chinese))
   {
    QFile newFile(chinese);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(match))
   {
    QFile newFile(match);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(english))
   {
    QFile newFile(english);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(history))
   {
    QFile newFile(history);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(cplusplus))
   {
    QFile newFile(cplusplus);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(number))
   {
    QFile newFile(number);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(passWD))
   {
    QFile newFile(passWD);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(sex))
   {
    QFile newFile(sex);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(age))
   {
    QFile newFile(age);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  if(!file.exists(college))
   {
    QFile newFile(college);
    newFile.open(QIODevice::WriteOnly);
    newFile.close();
   }
  //建立存放数据的文件
  //程序第一次运行是的初始数据
  QFile nameFile(name);
  nameFile.open(QIODevice::ReadWrite);
  QTextStream rn(&nameFile);
  if(rn.readAll().isEmpty())
  {
   for(int i = 0 ; i < 5 ; ++i)
    {
     QString ex("模板");
     ex = ex + QString::number(i);
     ex = ex + "\n";
     rn<<ex;
    }
  }
  nameFile.close();
}


examDelegate.h
#ifndef EXAMDELEGATE_H_
#define EXAMDELEGATE_H_
#include<QItemDelegate>
#include<QModelIndex>
#include<QPainter>
class examDelegate:public QItemDelegate
{
 public:
  examDelegate(QObject* parent = 0);  //用于examModel的委托,用于输入成绩时,输入的大于100或小于0的数字,或者输入不为数字是提供(红字)提醒
  void paint(QPainter* , const QStyleOptionViewItem& , const QModelIndex&)const;
  QWidget* createEditor(QWidget* , const QStyleOptionViewItem& ,const QModelIndex&)const;
  void setEditorData(QWidget* , const QModelIndex&)const;
  void setModelData(QWidget* , QAbstractItemModel* , const QModelIndex&)const;
};
#endif


examDelegate.cxx
 
#include"examDelegate.h"
#include<QDebug>
examDelegate::examDelegate(QObject* parent):QItemDelegate(parent)
{
}
void examDelegate::paint(QPainter* painter , const QStyleOptionViewItem& option , const QModelIndex& index)const
{
  QPen keepPen = painter->pen();  //保存画笔
  if(index.column() != 0)  //examModel第一列为姓名,不需要此委托
   {
    bool nu = true;
    QString value = index.model()->data(index,Qt::DisplayRole).toString(); 
    int realValue = value.toInt(&nu); 
    if(nu == false or realValue < 0 or realValue > 100)  //委托条件 输入不为整数,或者整数不在0-100区间
      painter->setPen(QPen(Qt::red));    //设置字体红色
    painter->drawText(option.rect,Qt::AlignRight|Qt::AlignVCenter,value);
    painter->setPen(keepPen);  //画笔保持原因,用于别的item
   }
  else 
    QItemDelegate::paint(painter,option,index);
}
QWidget* examDelegate::createEditor(QWidget* widget, const QStyleOptionViewItem& option , const QModelIndex& index)const
{
 return  QItemDelegate::createEditor(widget,option,index);
}
void examDelegate::setEditorData(QWidget* widget , const QModelIndex& index)const
{
  QItemDelegate::setEditorData(widget,index);
}
void examDelegate::setModelData(QWidget* widget , QAbstractItemModel* model, const QModelIndex& index)const
{
  QItemDelegate::setModelData(widget,model,index);
}


examModel.h
#ifndef EXAMMODEL_H_
#define EXAMMODEL_H_
#include<QAbstractTableModel>
#include<QModelIndex>
#include<QVariant>
#include<QList>
#include<QVector>
class examModel:public QAbstractTableModel
{
  Q_OBJECT
 private:
  QList<QString> names;
  QVector<QString> classes;
  QList<QString> chinese;  //存放5门课的成绩
  QList<QString> match;
  QList<QString> english;
  QList<QString> history;
  QList<QString> cplusplus;
 public:
  examModel(QObject* parent = 0);
  int rowCount(const QModelIndex&)const;
  int columnCount(const QModelIndex&)const;
  QVariant data(const QModelIndex& , int)const;
  bool setData(const QModelIndex& , const QVariant& , int);
  QVariant headerData(int , Qt::Orientation , int)const;
  Qt::ItemFlags flags(const QModelIndex&)const;
  void test(const QList<QString>&);
  QList<QString> realName();  //向父窗体返回修改后的姓名 
 signals:
  void updateName(const QModelIndex& , const QVariant&);
 public slots:
  void writeData();  //用于将数据写入硬盘文件./info/..
  void deleteData(int);  //删除一个学生信息(即删除一行)
  void addNewData();  //添加一个空白行
  void nameChanged(const QModelIndex& , const QVariant&);
};
#endif


examModel.cxx

#include<QFile>
#include<QDir>
#include<QTextStream>
#include"examModel.h"
examModel::examModel(QObject* parent):QAbstractTableModel(parent)
{
  classes.push_back("姓名");
  classes.push_back("中文");
  classes.push_back("数学");
  classes.push_back("英语");
  classes.push_back("历史");
  classes.push_back("C++");
}
int examModel::rowCount(const QModelIndex&)const
{
  return names.size();
}
int examModel::columnCount(const QModelIndex&)const
{
  return classes.size();
}
QVariant examModel::data(const QModelIndex& index , int role)const
{
  if(!index.isValid())  //索引不可用
   return QVariant();
  if(role == Qt::TextAlignmentRole)
   return QVariant(Qt::AlignRight|Qt::AlignVCenter);
  if(role == Qt::DisplayRole)
   {
    if(index.column() == 0)
     return names.at(index.row());
    if(index.column() == 1)
     return chinese.at(index.row());
    if(index.column() == 2)
     return match.at(index.row());
    if(index.column() == 3)
     return english.at(index.row());
    if(index.column() == 4)
     return history.at(index.row());
    if(index.column() == 5)
     return cplusplus.at(index.row());
   }
  return QVariant();
}
bool examModel::setData(const QModelIndex& index , const QVariant& value , int role)
{
  if(index.isValid() and role == Qt::EditRole)
   {
    if(index.column() == 0)
    {
     emit updateName(index,value);  //发射信号,通知info模型,数据已经改变
     *(names.begin() + index.row()) = value.toString();
    }
    if(index.column() == 1)
    *(chinese.begin() + index.row()) = value.toString();
    if(index.column() == 2)
    *(match.begin() + index.row()) = value.toString();
    if(index.column() == 3)
    *(english.begin() + index.row()) = value.toString();
    if(index.column() == 4)
    *(history.begin() + index.row()) = value.toString();
    if(index.column() == 5)
    *(cplusplus.begin() + index.row()) = value.toString();
    emit dataChanged(index,index);
    return true;
   } 
  return false;
}
QVariant examModel::headerData(int sec , Qt::Orientation ct, int role)const
{
  if(ct == Qt::Horizontal and role == Qt::DisplayRole)
   return classes.at(sec);
  if(ct == Qt::Vertical and role == Qt::DisplayRole)
   return QVariant(sec+1);
 return QVariant();
}
Qt::ItemFlags examModel::flags(const QModelIndex& index)const
{
  Qt::ItemFlags fg = QAbstractItemModel::flags(index);
  fg |= Qt::ItemIsEditable;
  return fg;
}
void examModel::test(const QList<QString>& nm)  //该函数用于设置模型的(初始)数据
{
  beginResetModel();
  names = nm;
  QString paths = QDir::currentPath();
  paths = paths + "/info";
  QString chinesePath = paths + "/chinese.txt";
  QString matchPath = paths + "/match.txt";
  QString englishPath = paths + "/english.txt";
  QString historyPath = paths + "/history.txt";
  QString cplusplusPath = paths +"/c++.txt";  //获取数据存放文件的文件路 径

  QFile chineseFile(chinesePath);
  QFile matchFile(matchPath);
  QFile englishFile(englishPath);
  QFile historyFile(historyPath);
  QFile cplusplusFile(cplusplusPath);
  
  chineseFile.open(QIODevice::ReadOnly);
  matchFile.open(QIODevice::ReadOnly);
  englishFile.open(QIODevice::ReadOnly);
  historyFile.open(QIODevice::ReadOnly);
  cplusplusFile.open(QIODevice::ReadOnly);

  QTextStream chineseIO(&chineseFile);
  QTextStream matchIO(&matchFile);
  QTextStream englishIO(&englishFile);
  QTextStream historyIO(&historyFile);
  QTextStream cplusplusIO(&cplusplusFile);
  
  QString de = QString::number(0);
  for(int i = 0 ; i < names.size() ; ++i)
  {
    if(!chineseIO.atEnd())
     chinese.push_back(chineseIO.readLine());
    else if(chineseIO.atEnd())
     chinese.push_back(de);    //使用默认数据,一方面方便显示,另一方面,防止写入数据时的越界问题
    if(!matchIO.atEnd())
     match.push_back(matchIO.readLine());
    else if(matchIO.atEnd())
     match.push_back(de);
    if(!englishIO.atEnd())
     english.push_back(englishIO.readLine());
    else if(englishIO.atEnd())
     english.push_back(de);
    if(!historyIO.atEnd())
     history.push_back(historyIO.readLine());
    else if(historyIO.atEnd())
     history.push_back(de);
    if(!cplusplusIO.atEnd())
     cplusplus.push_back(cplusplusIO.readLine());
    else if(cplusplusIO.atEnd())
     cplusplus.push_back(de);
   }
  endResetModel();
}
QList<QString> examModel::realName()
{
  return names;
}
void examModel::writeData()
{
  QString paths = QDir::currentPath();
  paths = paths + "/info";
  QString chinesePath = paths + "/chinese.txt";
  QString matchPath = paths + "/match.txt";
  QString englishPath = paths + "/english.txt";
  QString historyPath = paths + "/history.txt";
  QString cplusplusPath = paths +"/c++.txt";  //获取数据存放文件的文件路 径

  QFile chineseFile(chinesePath);
  QFile matchFile(matchPath);
  QFile englishFile(englishPath);
  QFile historyFile(historyPath);
  QFile cplusplusFile(cplusplusPath);
  
  chineseFile.open(QIODevice::WriteOnly);
  matchFile.open(QIODevice::WriteOnly);
  englishFile.open(QIODevice::WriteOnly);
  historyFile.open(QIODevice::WriteOnly);
  cplusplusFile.open(QIODevice::WriteOnly);

  QTextStream chineseIO(&chineseFile);
  QTextStream matchIO(&matchFile);
  QTextStream englishIO(&englishFile);
  QTextStream historyIO(&historyFile);
  QTextStream cplusplusIO(&cplusplusFile);
  
  for(int i = 0 ; i < names.size() ; ++i)
  {
    chineseIO<<chinese.at(i)<<"\n";  //换行符号用于下次读取文件的判断
    matchIO<<match.at(i)<<"\n";      //由于读取是使用了默认值,所以不必单项at()越界的问题
    englishIO<<english.at(i)<<"\n"; 
    historyIO<<history.at(i)<<"\n";
    cplusplusIO<<cplusplus.at(i)<<"\n";
  }
}
void examModel::deleteData(int row)
{
  beginResetModel();
  names.erase(names.begin() + row);  //删除一行,把改行所有数据均删除
  chinese.erase(chinese.begin() + row);
  match.erase(match.begin() + row);
  english.erase(english.begin() + row);
  history.erase(history.begin() + row);
  cplusplus.erase(cplusplus.begin() + row);
  endResetModel();
}
void examModel::addNewData()
{
  beginResetModel();
  QString de = QString::number(0);
  names.push_back("模板");   //增加的空行均为默认数据
  chinese.push_back(de);
  match.push_back(de);
  english.push_back(de);
  history.push_back(de);
  cplusplus.push_back(de);
  endResetModel();
}
void examModel::nameChanged(const QModelIndex& index, const QVariant& value)
{
  beginResetModel();
  *(names.begin() + index.row()) = value.toString();
  endResetModel();
}


infoDelegate.h

#ifndef INFODELEGATE_H_
#define INFODELGATE_H_
#include<QStyledItemDelegate>
#include<QModelIndex>
#include<QPainter>
#include<QComboBox>
class infoDelegate:public QStyledItemDelegate
{
 public:
  infoDelegate(QObject* parent = 0);
  QWidget* createEditor(QWidget* parent , const QStyleOptionViewItem& , const QModelIndex&)const;
  void setEditorData(QWidget* , const QModelIndex&)const;
  void setModelData(QWidget* , QAbstractItemModel* , const QModelIndex&)const;
};
#endif



infoDelegate.cxx

#include"infoDelegate.h"
infoDelegate::infoDelegate(QObject* parent):QStyledItemDelegate(parent)
{
}
QWidget* infoDelegate::createEditor(QWidget* parent , const QStyleOptionViewItem& option, const QModelIndex& index)const
{
  if(index.column() == 3)  //第三行为infoModel的性别行,这里直接采用硬编码
   {
    QComboBox* sexBox = new QComboBox(parent);
    sexBox->addItem(tr("男"));
    sexBox->addItem(tr("女"));
    return sexBox;
   }
  else if(index.column() == 5)  //第五列为info的学院列,同样直接采取硬编码
    {
     QComboBox* collegeBox = new QComboBox(parent);
     QStringList colleges;
     colleges<<tr("机电学院")<<tr("外语学院")<<tr("政法学院")<<tr("体育学院")<<tr("能源学院")<<tr("艺术学院")<<tr("计算机学院")<<tr("地理学院");
     collegeBox->addItems(colleges);
     return collegeBox;
    }
  else return QStyledItemDelegate::createEditor(parent,option,index);
}
void infoDelegate::setEditorData(QWidget* editor , const QModelIndex& index)const
{
 QStyledItemDelegate::setEditorData(editor,index);
}
void infoDelegate::setModelData(QWidget* editor , QAbstractItemModel* model , const QModelIndex& index)const
{
  if(index.column() == 3)
   {
    QComboBox* sexEdit = qobject_cast<QComboBox*>(editor);
    QString sex = sexEdit->currentText();
    model->setData(index,sex);
   }
  if(index.column() == 5)
  {
   QComboBox* collegeEdit = qobject_cast<QComboBox*>(editor);
   QString college = collegeEdit->currentText();
   model->setData(index,college);
  } 
  else QStyledItemDelegate::setModelData(editor,model,index);
}


infoModel.h

#ifndef INFOMODEL_H_
#define INFOMODEL_H_
#include<QAbstractTableModel>
#include<QList>
#include<QVector>
#include<QVariant>
#include<QModelIndex>
#include<QTextStream>
class infoModel:public QAbstractTableModel
{
  Q_OBJECT
 private:
  QList<QString> names;
  QVector<QString> info;
  QList<QString> number;  //这里学号即为学生登陆的账号
  QList<QString> sex;
  QList<int> age;
  QList<QString> college;
 public:
  infoModel(QObject* parent = 0);
  int rowCount(const QModelIndex&)const;
  int columnCount(const QModelIndex&)const;
  QVariant data(const QModelIndex& , int)const;
  bool setData(const QModelIndex& , const QVariant& , int);
  QVariant headerData(int , Qt::Orientation , int)const;
  Qt::ItemFlags flags(const QModelIndex&)const;
  void test(const QList<QString>&);
 signals:
  void updateName(const QModelIndex& , const QVariant&);
 public slots:
  void writeData();  //把数据写入硬盘文件,功能与infoModel的writeData()槽完全相同
  void deleteData(int);
  void addNewData();
  void nameChanged(const QModelIndex& , const QVariant&);
};
#endif


infoModel.cxx

#include<QDir>
#include<QTextStream>
#include<QFile>
#include"infoModel.h"
QList<QString> passWD;
infoModel::infoModel(QObject* parent):QAbstractTableModel(parent)
{
  info.push_back("姓名");
  info.push_back("学号");
  info.push_back("密码");
  info.push_back("性别");
  info.push_back("年龄");
  info.push_back("学院");
}
int infoModel::rowCount(const QModelIndex&)const
{
  return names.size();
}
int infoModel::columnCount(const QModelIndex&)const
{
  return info.size();
}
QVariant infoModel::data(const QModelIndex& index , int role)const
{
  if(!index.isValid())
   return QVariant();
  if(role == Qt::TextAlignmentRole)
   return QVariant(Qt::AlignRight|Qt::AlignVCenter);
  if(role == Qt::DisplayRole)
   {
    if(index.column() == 0)
     return names.at(index.row());
    if(index.column() == 1)
     return number.at(index.row());
    if(index.column() == 2)
     return passWD.at(index.row());
    if(index.column() == 3)
     return sex.at(index.row());
    if(index.column() == 4)
     return age.at(index.row());
    if(index.column() == 5)
     return college.at(index.row());
   }
  return QVariant();
}
bool infoModel::setData(const QModelIndex& index , const QVariant& value , int role)
{
  if(index.isValid() and role == Qt::EditRole)
  {
   if(index.column() == 0)
    {
     emit updateName(index,value);  //通知exam模型,姓名数据已经更改
     *(names.begin() + index.row()) = value.toString();
    }
   if(index.column() == 1)
    *(number.begin() + index.row()) = value.toString();
   if(index.column() == 2)
    *(passWD.begin() + index.row()) = value.toString();
   if(index.column() == 3)
    *(sex.begin() + index.row()) = value.toString();
   if(index.column() == 4)
    *(age.begin() + index.row()) = value.toInt();
   if(index.column() == 5)
    *(college.begin() + index.row()) = value.toString();
   emit dataChanged(index,index);
   return true;
   }
  return false;
}
QVariant infoModel::headerData(int sec , Qt::Orientation ns, int role)const
{
  if(role == Qt::DisplayRole and ns == Qt::Horizontal)
   return info.at(sec);
  if(role == Qt::DisplayRole and ns == Qt::Vertical)
   return sec+1;
  return QVariant();
}
Qt::ItemFlags infoModel::flags(const QModelIndex& index)const
{
  Qt::ItemFlags fg = QAbstractItemModel::flags(index);
   fg |= Qt::ItemIsEditable;
  return fg;
}
void infoModel::test(const QList<QString>& nm)
{
  beginResetModel();
  names = nm;
  QString paths = QDir::currentPath();
  paths = paths +"/info";
  QString numberPath = paths + "/number.txt";
  QString passWDPath = paths + "/passWD.txt";
  QString sexPath = paths + "/sex.txt";
  QString agePath = paths + "/age.txt";
  QString collegePath = paths + "/college.txt";  //获得数据存放文件路径

  QFile numberFile(numberPath);
  QFile passWDFile(passWDPath);
  QFile sexFile(sexPath);
  QFile ageFile(agePath);
  QFile collegeFile(collegePath);

  numberFile.open(QIODevice::ReadOnly);
  passWDFile.open(QIODevice::ReadOnly);
  sexFile.open(QIODevice::ReadOnly);
  ageFile.open(QIODevice::ReadOnly);
  collegeFile.open(QIODevice::ReadOnly);

  QTextStream numberIO(&numberFile);
  QTextStream passWDIO(&passWDFile);
  QTextStream sexIO(&sexFile);
  QTextStream ageIO(&ageFile);
  QTextStream collegeIO(&collegeFile);

  for(int i = 0 ; i < names.size() ; ++i)
  {
   if(!numberIO.atEnd())
     number.push_back(numberIO.readLine());
   else if(numberIO.atEnd())
     number.push_back("000000");
   if(!passWDIO.atEnd())
    passWD.push_back(passWDIO.readLine());
   else if(passWDIO.atEnd())
    passWD.push_back("12345");
   if(!sexIO.atEnd())
    sex.push_back(sexIO.readLine());
   else if(sexIO.atEnd())
    sex.push_back("男");
   if(!ageIO.atEnd())
    age.push_back(ageIO.readLine().toInt());
   else if(ageIO.atEnd())
    age.push_back(20);
   if(!collegeIO.atEnd())
    college.push_back(collegeIO.readLine());
   else if(collegeIO.atEnd())
    college.push_back("机电学院");
   }
  endResetModel();
}
void infoModel::writeData()
{
  QString paths = QDir::currentPath();
  paths = paths +"/info";
  QString numberPath = paths + "/number.txt";
  QString passWDPath = paths + "/passWD.txt";
  QString sexPath = paths + "/sex.txt";
  QString agePath = paths + "/age.txt";
  QString collegePath = paths + "/college.txt";  //获得数据存放文件路径

  QFile numberFile(numberPath);
  QFile passWDFile(passWDPath);
  QFile sexFile(sexPath);
  QFile ageFile(agePath);
  QFile collegeFile(collegePath);

  numberFile.open(QIODevice::WriteOnly);
  passWDFile.open(QIODevice::WriteOnly);
  sexFile.open(QIODevice::WriteOnly);
  ageFile.open(QIODevice::WriteOnly);
  collegeFile.open(QIODevice::WriteOnly);

  QTextStream numberIO(&numberFile);
  QTextStream passWDIO(&passWDFile);
  QTextStream sexIO(&sexFile);
  QTextStream ageIO(&ageFile);
  QTextStream collegeIO(&collegeFile);

  for(int i = 0 ; i < names.size() ; ++i)
   {
    numberIO<<number.at(i)<<"\n";
    passWDIO<<passWD.at(i)<<"\n";
    sexIO<<sex.at(i)<<"\n";
    ageIO<<age.at(i)<<"\n";
    collegeIO<<college.at(i)<<"\n";
   }
}
void infoModel::deleteData(int i)
{
  beginResetModel();
  names.erase(names.begin()+i);
  number.erase(number.begin()+i);
  passWD.erase(passWD.begin()+i);
  sex.erase(sex.begin()+i);
  age.erase(age.begin()+i);
  college.erase(college.begin()+i);
  endResetModel();
}
void infoModel::addNewData()
{
  beginResetModel();
  names.push_back("模板");
  number.push_back("111111");
  passWD.push_back("000000");
  sex.push_back("男");
  age.push_back(20);
  college.push_back("机电学院");
  endResetModel();
}
void infoModel::nameChanged(const QModelIndex& index , const QVariant& value)
{
  beginResetModel();
  *(names.begin() + index.row()) = value.toString();
  endResetModel();
}


loginBox.h

#ifndef LOGINBOX_H_
#define LOGINBOX_H_
#include<QDialog>
#include<QPushButton>
#include<QLabel>
#include<QGroupBox>
#include<QLineEdit>
#include"teacherDialog.h"
#include"lookDialog.h"
class loginBox:public QDialog
{
  Q_OBJECT
 private:
  QList<QString> number;
  QList<QString> passWD;
  teacherDialog* teacher;
  lookDialog* looker;  //  :)
  QGroupBox* login_group;
  QLabel* account_label;
  QLabel* passWD_label;
  QLineEdit* account_edit;
  QLineEdit* passWD_edit;
  QPushButton* login_button;
  QPushButton* close_button;
  void getInfo();  //读取姓名和密码
 public:
  loginBox(QWidget* parent = 0);
 signals:
  void findStudent(int);
 private slots:
  void login();
  void reLoad();
};
#endif


loginBox.cxx

#include<QHBoxLayout>
#include<QVBoxLayout>
#include<QList>
#include<QDir>
#include<QFile>
#include<QTextStream>
#include<QMessageBox>
#include"loginBox.h"
loginBox::loginBox(QWidget* parent):QDialog(parent)
{
  getInfo();  //获得姓名和密码

  teacher = new teacherDialog(this);
  looker = new lookDialog(this);

  login_group = new QGroupBox(tr("登陆"));
  account_label = new QLabel(tr("账号"));
  passWD_label = new QLabel(tr("密码"));
  account_edit = new QLineEdit;
  passWD_edit = new QLineEdit;
  passWD_edit->setEchoMode(QLineEdit::Password);  //确保出入密码都显示****
  login_button = new QPushButton(tr("登陆"));
  close_button = new QPushButton(tr("退出"));
  //布局
  QHBoxLayout* account_layout = new QHBoxLayout;
  account_layout->addWidget(account_label);
  account_layout->addWidget(account_edit);
  QHBoxLayout* passWD_layout = new QHBoxLayout;
  passWD_layout->addWidget(passWD_label);
  passWD_layout->addWidget(passWD_edit);
  QVBoxLayout* login_layout = new QVBoxLayout;
  login_layout->addLayout(account_layout);
  login_layout->addLayout(passWD_layout);
  login_group->setLayout(login_layout);
  QHBoxLayout* button_layout = new QHBoxLayout;
  button_layout->addStretch();
  button_layout->addWidget(login_button);
  button_layout->addWidget(close_button);
  QVBoxLayout* main_layout = new QVBoxLayout;
  main_layout->addWidget(login_group);
  main_layout->addLayout(button_layout);
  //安装布局,设置标题等
  setLayout(main_layout);
  setWindowIcon(QIcon(tr(":/images/read.png")));
  main_layout->setSizeConstraint(QLayout::SetFixedSize);
  setWindowTitle(tr("欢迎来到学生管理系统"));
  //信号与槽
  connect(login_button,SIGNAL(clicked()),this,SLOT(login()));
  connect(close_button,SIGNAL(clicked()),this,SLOT(close()));
  connect(teacher,SIGNAL(hasLeave()),this,SLOT(close()));
  connect(looker,SIGNAL(hasleave()),this,SLOT(close()));
  connect(this,SIGNAL(findStudent(int)),looker,SLOT(looking(int)));
}
void loginBox::getInfo()
{
  QString paths = QDir::currentPath();
  QString numberPath = paths + "/info/number.txt";
  QString passWDPath = paths + "/info/passWD.txt";
  
  QFile numberFile(numberPath);
  QFile passWDFile(passWDPath);

  QTextStream numberIO(&numberFile);
  QTextStream passWDIO(&passWDFile);

  numberFile.open(QIODevice::ReadOnly);
  passWDFile.open(QIODevice::ReadOnly);
  
  while(!numberIO.atEnd())
   {
    number.push_back(numberIO.readLine());
    passWD.push_back(passWDIO.readLine());
   }
}
void loginBox::login()
{
  QString teachAccount("teacher");
  QString teachpassWD("123456");   //先判断登陆的是不是老师
  if(account_edit->text() ==  teachAccount and passWD_edit->text() == teachpassWD)
   {
     teacher->show();
     hide();
     return;
   }
  QString acc = account_edit->text();
  QString pd = passWD_edit->text();
  for(int i = 0 ; i < number.size() ; ++i)  //学生登陆
    {
     if(acc == number.at(i) and pd == passWD.at(i))
       {
        looker->show();
        hide();
        emit findStudent(i);
        return;
       }
   }
  reLoad();
}
void loginBox::reLoad()
{
  account_edit->clear();
  passWD_edit->clear();
  QMessageBox::warning(this,tr("warning"),tr("账号或密码错误"),QMessageBox::Yes);
}


lookDialog.h
#ifndef LOOKDIALOG_H_
#define LOOKDIALOG_H_
#include<QDialog>
#include<QGroupBox>
#include<QLineEdit>
#include<QPushButton>
#include<QTableWidget>
#include<QLabel>
#include<QCloseEvent>
class lookDialog:public QDialog
{
  Q_OBJECT
 private:
  int t;  //标记显示的是第几个学生
  bool pd;  //确定更换密码框是影藏还是显示状态
  QList<QString> names;
  QList<QString> passWD;  //这2个用于从文件读取姓名和密码信息
  QTableWidget* showInfo;
  QPushButton* code_button;
  QPushButton* finish_button;
  QPushButton* close_button;
  QGroupBox* passWD_group;
  QLabel* old_label;
  QLabel* new_label;
  QLabel* config_label;
  QLineEdit* old_edit;
  QLineEdit* new_edit;
  QLineEdit* config_edit;
  void getInfo();  //用于读取姓名和密码
 public:
  lookDialog(QWidget* parent);
 protected:
  void closeEvent(QCloseEvent*);
 signals:
  void hasleave();  //关闭是发射该信号,由父窗体来关闭整个程序
 private slots:
  void changeCode();  //更换密码函数
  void newPassWD();
  void looking(int);  //显示某位学生信息
};
#endif


lookDialog.cxx

#include<QHBoxLayout>
#include<QVBoxLayout>
#include<QTableWidgetItem>
#include<QStringList>
#include<QList>
#include<QDir>
#include<QFile>
#include<QTextStream>
#include<QMessageBox>
#include"lookDialog.h"
lookDialog::lookDialog(QWidget* parent):QDialog(parent),t(-1),pd(true)
{
  QStringList heads;
  heads<<tr("语文")<<tr("数学")<<tr("英语")<<tr("历史")<<tr("C++");
  showInfo = new QTableWidget;
  showInfo->setRowCount(1);
  showInfo->setColumnCount(5);
  showInfo->setHorizontalHeaderLabels(heads);
  showInfo->setEditTriggers(QAbstractItemView::NoEditTriggers);  //禁止编辑
  for(int i = 0 ; i < 5 ; ++i)
   showInfo->setItem(0,i,new QTableWidgetItem);  //这里使用硬编码直接获得显示课目的数量,名称等
  showInfo->setFixedSize(520,100);

  code_button = new QPushButton(tr("更换密码"));
  finish_button = new QPushButton(tr("完成"));
  close_button = new QPushButton(tr("关闭"));
  passWD_group = new QGroupBox(tr("更换密码"));
  old_label = new QLabel(tr("原密码"));
  new_label = new QLabel(tr("新密码"));
  config_label = new QLabel(tr("确认新密码"));
  old_edit = new QLineEdit;
  old_edit->setEchoMode(QLineEdit::Password);
  new_edit = new QLineEdit;
  new_edit->setEchoMode(QLineEdit::Password);
  config_edit = new QLineEdit;
  config_edit->setEchoMode(QLineEdit::Password);
  //布局
  QHBoxLayout* new_layout = new QHBoxLayout;  //下部密码更换框布局
  new_layout->addWidget(new_label);
  new_layout->addStretch();
  new_layout->addWidget(new_edit);
  QHBoxLayout* old_layout = new QHBoxLayout;
  old_layout->addWidget(old_label);
  old_layout->addStretch();
  old_layout->addWidget(old_edit);
  QHBoxLayout* config_layout = new QHBoxLayout;
  config_layout->addWidget(config_label);
  config_layout->addStretch();
  config_layout->addWidget(config_edit);
  
  QVBoxLayout* finish_layout = new QVBoxLayout;
  finish_layout->addStretch();
  finish_layout->addWidget(finish_button);

  QVBoxLayout* group_layout = new QVBoxLayout;
  group_layout->addLayout(old_layout);
  group_layout->addLayout(new_layout);
  group_layout->addLayout(config_layout);

  QHBoxLayout* passWD_layout = new QHBoxLayout;
  passWD_layout->addLayout(group_layout);
  passWD_layout->addLayout(finish_layout);
  passWD_group->setLayout(passWD_layout);

  QHBoxLayout* button_layout = new QHBoxLayout;
  button_layout->addStretch();
  button_layout->addWidget(code_button);
  button_layout->addWidget(close_button);

  QVBoxLayout* main_layout = new QVBoxLayout;
  main_layout->addWidget(showInfo);
  main_layout->addLayout(button_layout);
  main_layout->addWidget(passWD_group);
  passWD_group->hide();
  //信号与槽
  connect(code_button,SIGNAL(clicked()),this,SLOT(changeCode()));
  connect(close_button,SIGNAL(clicked()),this,SLOT(close()));
  connect(finish_button,SIGNAL(clicked()),this,SLOT(newPassWD()));
  //安装布局,设置标题
  setLayout(main_layout);
  main_layout->setSizeConstraint(QLayout::SetFixedSize);

  getInfo();  //从文件读取姓名,密码
}
void lookDialog::getInfo()
{
  QString paths = QDir::currentPath();
  QString namePath = paths + "/info/name.txt";
  QString passWDPath = paths + "/info/passWD.txt";
  
  QFile nameFile(namePath);
  QFile passWDFile(passWDPath);

  QTextStream nameIO(&nameFile);
  QTextStream passWDIO(&passWDFile);
  
  nameFile.open(QIODevice::ReadOnly);
  passWDFile.open(QIODevice::ReadOnly);
  
  while(!nameIO.atEnd())
   {
    names.push_back(nameIO.readLine());
    passWD.push_back(passWDIO.readLine());
   }
}
void lookDialog::closeEvent(QCloseEvent*)
{
  emit hasleave();
}
void lookDialog::changeCode()
{
  if(pd == true)
  {
   code_button->setText(tr("取消更改"));
   passWD_group->show();
   pd = false;
  }
  else if(pd == false)
   {
    code_button->setText(tr("修改密码"));
    passWD_group->hide();
    old_edit->clear();
    new_edit->clear();
    config_edit->clear();
    pd = true;
   }
}
void lookDialog::newPassWD()
{
  if(passWD.at(t) != old_edit->text())
   {
    QMessageBox::warning(this,tr("warning"),tr("原密码错误"),QMessageBox::Yes);
    return;
   }
  if(new_edit->text() != config_edit->text())
   {
    QMessageBox::warning(this,tr("warning"),tr("两次密码输入不一样"),QMessageBox::Yes);
    return;
   }
  //确认密码更换正确后把密码写入文件
  *(passWD.begin() + t) = new_edit->text();
  QString paths = QDir::currentPath() + "/info/passWD.txt";
  QFile newCode(paths);
  newCode.open(QIODevice::WriteOnly);
  QTextStream newCodeIO(&newCode);
  for(int i = 0 ; i < names.size() ; ++i)
   newCodeIO<<passWD.at(i)<<"\n";
  //完成后清空密码输入框
  old_edit->clear();
  new_edit->clear();
  config_edit->clear();
  QMessageBox::information(this,tr("info"),tr("密码重置完成"),QMessageBox::Yes);
}  
void lookDialog::looking(int pi)
{
  t = pi;  //这是第pi个学生
  QString titles = "亲爱的";
  titles +=names.at(pi);
  titles += "同学";
  setWindowTitle(titles);
  QString paths = QDir::currentPath();
  
  QString chinese = paths + "/info/chinese.txt";  //获取存放成绩数据 的文件路径
  QString match = paths + "/info/match.txt";
  QString english = paths + "/info/english.txt";
  QString history = paths + "/info/history.txt";
  QString cplusplus = paths + "/info/c++.txt";

  QFile chineseFile(chinese);
  QFile matchFile(match);
  QFile englishFile(english);
  QFile historyFile(history);
  QFile cplusplusFile(cplusplus);

  chineseFile.open(QIODevice::ReadOnly);
  matchFile.open(QIODevice::ReadOnly);
  englishFile.open(QIODevice::ReadOnly);
  historyFile.open(QIODevice::ReadOnly);
  cplusplusFile.open(QIODevice::ReadOnly);

  QTextStream chineseIO(&chineseFile);
  QTextStream matchIO(&matchFile);
  QTextStream englishIO(&englishFile);
  QTextStream historyIO(&historyFile);
  QTextStream cplusplusIO(&cplusplusFile);

  QString chi = "";
  QString mat = "";
  QString eng = "";
  QString his = "";
  QString cpl = "";
  int i = 0;
  while(1)
  {
   chi = chineseIO.readLine();
   mat = matchIO.readLine();
   eng = englishIO.readLine();
   his = historyIO.readLine();
   cpl = cplusplusIO.readLine();
   if(i == pi)
    break;
   ++i;
   }
  showInfo->item(0,0)->setText(chi);
  showInfo->item(0,1)->setText(mat);
  showInfo->item(0,2)->setText(eng);
  showInfo->item(0,3)->setText(his);
  showInfo->item(0,4)->setText(cpl);
}


teacherDialog.h

#ifndef TEACHERDIALOG_H_
#define TEACHERDIALOG_H_
#include<QDialog>
#include<QTabWidget>
#include<QPushButton>
#include<QTableView>
#include<QList>
#include<QCloseEvent>
#include"examModel.h"
#include"infoModel.h"
class teacherDialog:public QDialog
{
  Q_OBJECT
 private:
  QList<QString> names;  //存放2个模型的公用数据 姓名
  QTabWidget* show_widget;
  examModel* exam_model;
  infoModel* info_model;
  QTableView* exam_view;
  QTableView* info_view;
  QPushButton* add_button;
  QPushButton* delete_button;
  QPushButton* write_button;
  QPushButton* close_button;
  void getName();  //从本地文件中读取学生姓名
 public:
  teacherDialog(QWidget* parent = 0);
 protected:
  void closeEvent(QCloseEvent*);
 signals:
  void hasLeave();
  void deleteExamData(int);
  void deleteInfoData(int);
 private slots:
  void writeData();
  void getDeleteData();  //获得当前选定的item的index
};
#endif


teacherDialog.cxx
#include<QHBoxLayout>
#include<QVBoxLayout>
#include<QDir>
#include<QFile>
#include<QTextStream>
#include<QHeaderView>
#include"teacherDialog.h"
#include"examDelegate.h"
#include"infoDelegate.h"
teacherDialog::teacherDialog(QWidget* parent):QDialog(parent)
{
  getName();  //优先读取学生名字
  show_widget = new QTabWidget;
  
  exam_view = new QTableView;
  exam_model = new examModel;
  exam_view->setModel(exam_model);
  exam_view->setItemDelegate(new examDelegate);  //设置委托
  exam_model->test(names);

  info_view = new QTableView;
  info_model = new infoModel;
  info_view->setModel(info_model);
  info_view->setItemDelegate(new infoDelegate);  //设置委托
  info_model->test(names);
  //把2个视图装到QTabWidget上
  QString exam("学生成绩");
  QString info("学生信息");
  show_widget->addTab(exam_view,exam);
  show_widget->addTab(info_view,info);
  show_widget->setCurrentWidget(info_view);

  add_button = new QPushButton(tr("添加"));
  delete_button = new QPushButton(tr("删除"));
  write_button = new QPushButton(tr("写入"));
  close_button = new QPushButton(tr("关闭"));

  delete_button->setIcon(QIcon(tr(":/images/delete.png")));
  write_button->setIcon(QIcon(tr(":/images/write.png")));
  //这2个相互的信号用于同步2个模型中的姓名数据
  connect(info_model,SIGNAL(updateName(const QModelIndex& , const QVariant&)),exam_model,SLOT(nameChanged(const QModelIndex& , const QVariant&)));
  connect(exam_model,SIGNAL(updateName(const QModelIndex& , const QVariant&)),info_model,SLOT(nameChanged(const QModelIndex& , const QVariant&)));

  connect(add_button,SIGNAL(clicked()),exam_model,SLOT(addNewData()));
  connect(add_button,SIGNAL(clicked()),info_model,SLOT(addNewData()));
  connect(delete_button,SIGNAL(clicked()),this,SLOT(getDeleteData()));
  connect(write_button,SIGNAL(clicked()),this,SLOT(writeData()));
  connect(write_button,SIGNAL(clicked()),info_model,SLOT(writeData()));
  connect(write_button,SIGNAL(clicked()),exam_model,SLOT(writeData()));
  connect(close_button,SIGNAL(clicked()),this,SLOT(close()));

  connect(this,SIGNAL(deleteExamData(int)),exam_model,SLOT(deleteData(int)));
  connect(this,SIGNAL(deleteInfoData(int)),info_model,SLOT(deleteData(int)));
  //布局安装
  QHBoxLayout* button_layout = new QHBoxLayout;
  button_layout->addWidget(delete_button);
  button_layout->addStretch();
  button_layout->addWidget(add_button);
  button_layout->addWidget(write_button);
  button_layout->addWidget(close_button);

  QVBoxLayout* main_layout = new QVBoxLayout;
  main_layout->addWidget(show_widget);
  main_layout->addLayout(button_layout);

  setLayout(main_layout);
  setFixedSize(650,600);
  setWindowTitle(tr("学生详情"));
}
void teacherDialog::closeEvent(QCloseEvent*)
{
  emit hasLeave();
  hide();
}
void teacherDialog::getName()
{
  QString paths = QDir::currentPath();
  paths = paths + "/info/name.txt";
  QFile nameFile(paths);
  nameFile.open(QIODevice::ReadOnly);
  QTextStream nameIO(&nameFile);
  while(!nameIO.atEnd())
   names.push_back(nameIO.readLine());
}
void teacherDialog::writeData()
{
  names = exam_model->realName();  //从模型获得修改后的姓名信息
  QString paths = QDir::currentPath();
  paths = paths + "/info/name.txt";
  QFile nameFile(paths);
  nameFile.open(QIODevice::WriteOnly);
  QTextStream nameIO(&nameFile);
  for(int i = 0 ; i < names.size() ; ++i)
   nameIO<<names.at(i)<<"\n";
}
void teacherDialog::getDeleteData()
{
  int e = 0;
  if(show_widget->currentIndex() == 0 and exam_view->currentIndex().isValid())
     e = exam_view->currentIndex().row();
  else if(show_widget->currentIndex() == 1 and info_view->currentIndex().isValid())
     e = info_view->currentIndex().row();
    emit deleteExamData(e);
    emit deleteInfoData(e);
}


main.cxx

#include<QApplication>
#include"buildFile.h"
#include"loginBox.h"
int main(int argc , char** argv)
{
  QApplication app(argc,argv);
  buildFile();
  loginBox A;
  A.show();
  return app.exec();
}


pix.qrc

<RCC>
<qresource>
<file>images/read.png</file>
<file>images/delete.png</file>
<file>images/write.png</file>
</qresource>
</RCC>


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7463次
    • 积分:36
    • 等级:
    • 排名:千里之外
    • 原创:76篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    文章分类
    文章存档
    最新评论
  • 学生管理系统

    qq_20553613: 不错,用txt方式模拟数据库。可以改用MySQL实现,加入搜索等功能;代码量和逻辑容易实现多了。另外...