柚子快報(bào)邀請(qǐng)碼778899分享:Qt教程—學(xué)生管理系統(tǒng)(文件)
柚子快報(bào)邀請(qǐng)碼778899分享:Qt教程—學(xué)生管理系統(tǒng)(文件)
一、項(xiàng)目設(shè)計(jì)
1、需求分析
記錄并處理學(xué)生成績(jī)信息。
1)添加新的學(xué)生數(shù)據(jù);
2)根據(jù)學(xué)號(hào)對(duì)已有的學(xué)生數(shù)據(jù)進(jìn)行修改;
3)根據(jù)學(xué)號(hào)刪除已存在的學(xué)生信息;
4)根據(jù)學(xué)號(hào)查詢(xún)學(xué)生信息;
5)根據(jù)各門(mén)成績(jī)與平均成績(jī)進(jìn)行排序。
2、窗口設(shè)計(jì)
1)菜單窗口;
2)添加學(xué)生窗口;
3)修改信息窗口(包括刪除信息);
4)查詢(xún)學(xué)生窗口
5)排序窗口;
3、數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
以一個(gè)類(lèi)StudentInfo儲(chǔ)存單個(gè)學(xué)生信息,學(xué)生類(lèi)中包括:
姓名(字符串)
學(xué)號(hào)(整型)
數(shù)學(xué)成績(jī)(整型)
英語(yǔ)成績(jī)(整型)
C語(yǔ)言程序設(shè)計(jì)成績(jī)(整型)
平均成績(jī)(雙浮點(diǎn)數(shù))
二、項(xiàng)目制作
1、建立項(xiàng)目
打開(kāi)Qt Creator 文件->新建文件或項(xiàng)目(Ctrl+N)->其他項(xiàng)目->空的Qt項(xiàng)目(Empty qmacke Project)
?
2、添加窗口
將其命名為StudentManagementSystem_Qt一路下一步到結(jié)束。
右擊項(xiàng)目名稱(chēng)->Add New->Qt -> Qt設(shè)計(jì)師界面模板選擇Widget下一步,我們當(dāng)前建立的是菜單窗口,所以將其類(lèi)名命名為MenuWidget一路下一步到結(jié)束。
以同樣的方式建立添加學(xué)生窗口:AddStudentWidget、修改信息窗口:ModifyWidget、查詢(xún)窗口:SelectWidget、排序窗口:SortWidget。
完成后的項(xiàng)目資源管理器頁(yè)面中應(yīng)該有如下文件
?
我們可以看到Qt中建立模板為widget的設(shè)計(jì)師界面就是建立了一個(gè)c++類(lèi)(繼承自QWidget)與其對(duì)應(yīng)的ui文件 ,這個(gè)ui文件便是Qt Designer設(shè)計(jì)文件,它會(huì)在編譯時(shí)生成一個(gè)ui_*.h文件,這樣我們便可以用c++的方式對(duì)其進(jìn)行調(diào)用。
Qt Designer的詳細(xì)使用方法可以看官方的手冊(cè):https://doc.qt.io/archives/qt-4.8/designer-manual.html
之后打開(kāi)我們的menuwidget.h,會(huì)發(fā)現(xiàn)其中存在錯(cuò)誤。
?
這是因?yàn)槲覀兊捻?xiàng)目中沒(méi)有連接Qt Widgets庫(kù),在StudentManagementSystem_Qt.pro中添加
QT += widgets
可解決問(wèn)題。
3、實(shí)現(xiàn)窗口之間的切換
現(xiàn)在,就是實(shí)現(xiàn)我們新建立的幾個(gè)窗口之間的窗口切換問(wèn)題的時(shí)候了,這里我打算使用QStackedLayout實(shí)現(xiàn)窗口切換。
QStackedLayout繼承自QLayout,提供了多頁(yè)面切換的布局,一次只能看到一個(gè)界面,在我的Qt5——從零開(kāi)始的Hello World教程(Qt Creator) 中提到過(guò),大部分控件都繼承自QFrame,而QFrame又繼承自QWidget,所以QStackedLayout完全可以實(shí)現(xiàn)窗口之間的切換。
現(xiàn)在我們用與上一步相同的方法建立一個(gè)窗口MainWidget。并添加一個(gè)main.cpp來(lái)寫(xiě)main函數(shù)
?
?
在mainwidget.h中修改MainWidget的定義,為其添加成員
MenuWidget *menuwidget; //菜單窗口
AddStudentWidget *addstudentwidget; //添加學(xué)生窗口
SelectWidget *selectwidget; //查詢(xún)窗口
ModifyWidget *modifywidget; //修改窗口
SortWidget *sortwidget; //排序窗口
QStackedLayout *stackLayout; //QStackedLayout布局
當(dāng)然,也需要引用其對(duì)應(yīng)的頭文件。
#include
#include "menuwidget.h"
#include "addstudentwidget.h"
#include "selectwidget.h"
#include "modifywidget.h"
#include "sortwidget.h"
在MainWidget.cpp中將MainWidget設(shè)為stackLayout布局,聲明我們需要的窗口,并將其加入stackLayout布局中去。
在MainWidget.cpp中顯示調(diào)用MainWidget構(gòu)造函數(shù)。
MainWidget::MainWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainWidget)
{
ui->setupUi(this);
}
處添加。
menuwidget = new MenuWidget;
addstudentwidget = new AddStudentWidget;
selectwidget = new SelectWidget;
modifywidget = new ModifyWidget;
sortwidget = new SortWidget;
stackLayout = new QStackedLayout;
stackLayout->addWidget(menuwidget);
stackLayout->addWidget(addstudentwidget);
stackLayout->addWidget(selectwidget);
stackLayout->addWidget(modifywidget);
stackLayout->addWidget(sortwidget);
setLayout(stackLayout);
之后就需要使用Qt designer 設(shè)計(jì)頁(yè)面了(當(dāng)然在對(duì)應(yīng)類(lèi)中手動(dòng)添加成員控件也沒(méi)有任何問(wèn)題)。
雙擊menuwidget.ui就打開(kāi)了設(shè)計(jì)頁(yè)面
在menuwidget中添加如下按鈕(push button)
?
以同樣的方法在addstudentwidget,selectwidget,modifywidget,sortwidget中都添加一個(gè)返回按鈕returnButton。
?
為這些按鈕設(shè)計(jì)點(diǎn)擊槽函數(shù)
menuwidget.h:
private slots:
void on_addButton_clicked();
void on_selectButton_clicked();
void on_modifyButton_clicked();
void on_sortButton_clicked();
void on_exitButton_clicked();
還需要一個(gè)方法作為stackLayout切換頁(yè)面的信號(hào)
signals:
void display(int number);
在menuwidget.cpp中給出函數(shù)定義
void MenuWidget::on_addButton_clicked(){
emit display(1);
}
void MenuWidget::on_selectButton_clicked(){
emit display(2);
}
void MenuWidget::on_modifyButton_clicked(){
emit display(3);
}
void MenuWidget::on_sortButton_clicked(){
emit display(4);
}
void MenuWidget::on_exitButton_clicked(){
QApplication::exit();
}
emit 把connect把信號(hào)和槽進(jìn)行關(guān)聯(lián),emit某個(gè)信號(hào),就相當(dāng)于調(diào)用這個(gè)信號(hào)connect時(shí)所關(guān)聯(lián)的槽函數(shù)。至于更多關(guān)于 emit信息諸位可以搜索或者看幫助文檔。
之后為addstudentwidget,selectwidget,modifywidget,sortwidget窗口中的按鈕設(shè)計(jì)信號(hào)與槽函數(shù)
在(類(lèi)名).h中添加
signals:
void display(int number);
private slots:
void on_returnButton_clicked();
在(類(lèi)名).cpp中添加
void (類(lèi)名)::on_returnButton_clicked(){
emit display(0);
}
現(xiàn)在可以使用的只有退出按鈕,跳轉(zhuǎn)按鈕還需要在mainwidget.cpp中用connect函數(shù)連接。
到此為止便完成了頁(yè)面切換功能。
到次為止的源碼:
https://github.com/suvvm/StudentManagementSystem_Qt/tree/master/StudentManagementSystem_Qt
4、完善窗口設(shè)計(jì)
1:AddStudentWidget
我們需要提示標(biāo)簽來(lái)指明輸入的數(shù)據(jù),也需要輸入框來(lái)接收用戶(hù)的輸入,QLabel與QLineEdit可以滿(mǎn)足我們的要求。
QLabel,QLineEdit有方法setText(“內(nèi)容”)來(lái)改變其顯示的文字,有方法setGeometry (起始橫坐標(biāo),起始縱坐標(biāo),寬, 高)來(lái)設(shè)置左上角起始位置與大小。
當(dāng)然這些都可以在Qt Designer中直接設(shè)置。打開(kāi)addstudentwidget.ui。
根據(jù)之前設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu),需要nameLineEdit、idLineEdit、mathLineEdit、enLineEdit、cLineEdit五個(gè)QLineEdit接收學(xué)生的姓名、學(xué)號(hào)、數(shù)學(xué)成績(jī)、英語(yǔ)成績(jī)、C語(yǔ)言成績(jī)(平均成績(jī)由計(jì)算得出),需要nameLabel、idLabel、mathLabel、enLabel、cLabel五個(gè)QLabel提醒用戶(hù)輸入數(shù)據(jù),需要addButton 一個(gè)QPushButton來(lái)添加學(xué)生。
最終將addstudentwidget頁(yè)面設(shè)計(jì)為。
?
2:modifyWidget
我們需要nameLineEdit、idLineEdit、mathLineEdit、enLineEdit、cLineEdit五個(gè)QLineEdit接收學(xué)生的姓名、學(xué)號(hào)、數(shù)學(xué)成績(jī)、英語(yǔ)成績(jī)、C語(yǔ)言成績(jī)(平均成績(jī)由計(jì)算得出),需要nameLabel、idLabel、mathLabel、enLabel、cLabel五個(gè)QLabel提醒用戶(hù)輸入數(shù)據(jù),需要deleteButton、modifyButton 兩個(gè)QPushButton來(lái)根據(jù)學(xué)號(hào)刪除學(xué)生,和根據(jù)學(xué)號(hào)修改學(xué)生信息。
?
3:selectwidget
我們需要idLabel一個(gè)QLabel提醒用戶(hù)輸入數(shù)據(jù),需要idLineEdit一個(gè)QLineEdit接收學(xué)生的學(xué)號(hào),之后需要nameLabel、avgLabel、mathLabel、enLabel、cLabel五個(gè)QLabel提醒用戶(hù)顯示的數(shù)據(jù),需要showNameLabel、showMathLabel、showEnLabel、showCLabel、showAvgLabel五個(gè)QLabel來(lái)接收查詢(xún)到的數(shù)據(jù),需要selectButton一個(gè)QPushButton來(lái)提交查詢(xún)。
?
4:sortwidget
QRadioButton單選框可以解決我們的排序根據(jù)選擇問(wèn)題
(當(dāng)然,許多方法都可以,這里只演示QRadioButton)
QTableWidget表格可以用來(lái)顯示排序后的信息。
我們需要mathRadioButton、enRadioButton、cRadioButton、avgRadioButton四個(gè)QRadioButton來(lái)選擇排序的根據(jù),需要sortButton一個(gè)QPushButton來(lái)提交排序,需要tableWidget一個(gè) QTableWidget來(lái)顯示排序結(jié)果。
?
到此為止的源碼:
https://github.com/suvvm/StudentManagementSystem_Qt/tree/master/StudentManagementSystem_Qt_1(uiOnly)
5、完成學(xué)生類(lèi)的設(shè)計(jì)
之前在數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)中我們已經(jīng)設(shè)計(jì)好了,以一個(gè)類(lèi)StudentInfo儲(chǔ)存單個(gè)學(xué)生信息,學(xué)生類(lèi)中包括:
姓名(字符串)
學(xué)號(hào)(整型)
數(shù)學(xué)成績(jī)(整型)
英語(yǔ)成績(jī)(整型)
C語(yǔ)言程序設(shè)計(jì)成績(jī)(整型)
平均成績(jī)(雙浮點(diǎn)數(shù))
現(xiàn)在著手去實(shí)現(xiàn)它
右擊項(xiàng)目Add New選擇C++ C++Class 為它起名叫StudentInfo之后下一步到完成,在studentinfo.h中為其創(chuàng)建對(duì)應(yīng)的私有變量,及其對(duì)應(yīng)的get與set函數(shù)。
studentinfo.h
class StudentInfo
{
private:
QString name;
int id, math, english, languageC;
double avg;
public:
StudentInfo();
StudentInfo(QString tname, int tid, int tmath, int tenglish, int tlanguageC){
name = tname;
id = tid;
math = tmath;
english = tenglish;
languageC = tlanguageC;
avg = (tmath + tenglish + tlanguageC) / 3.0;
}
int getId(){
return id;
}
QString getName(){
return name;
}
int getMath(){
return math;
}
int getEnglish(){
return english;
}
int getLanguageC(){
return languageC;
}
double getAvg(){
return avg;
}
void setId(int tid){
id = tid;
}
void setName(QString tname){
name = tname;
}
void setMath(int tmath){
math = tmath;
avg = (math + english + languageC) / 3.0;
}
void setEnglish(int tenglish){
english = tenglish;
avg = (math + english + languageC) / 3.0;
}
void setLanguageC(int tlanguageC){
languageC = tlanguageC;
avg = (math + english + languageC) / 3.0;
}
};
6、完善添加學(xué)生信息
打開(kāi)addstudentwidget.h為”添加”按鈕設(shè)計(jì)點(diǎn)擊槽函數(shù),由于我們?cè)O(shè)計(jì)用文件對(duì)學(xué)生信息進(jìn)行儲(chǔ)存,所以需要引用QFile,這里我使用對(duì)話(huà)框來(lái)提示用戶(hù)操作中的各種問(wèn)題,所以需要引入QMessageBox。
QMessageBox中有很多類(lèi)型的對(duì)話(huà)框,各對(duì)話(huà)框的用法這里就不詳細(xì)介紹了,這里我們只介紹我們即將用到的QMessageBox::about
QMessageBox::about(NULL, "About", "About this application");
其中三個(gè)參數(shù)分別對(duì)應(yīng),父窗口對(duì)象, 對(duì)話(huà)框標(biāo)題, 對(duì)話(huà)框內(nèi)容。
在addstudentwidget.cpp中給出函數(shù)定義:
在lineEdit中取出用戶(hù)輸入的數(shù)據(jù),lineEdit擁有text()方法,會(huì)返回一個(gè)QString,而QString中又擁有入toInt() toDouble()等各種類(lèi)型轉(zhuǎn)換函數(shù),可以適應(yīng)我們的大多數(shù)要求。
打開(kāi)數(shù)據(jù)文件將我們剛剛獲取的數(shù)據(jù)追加在文件結(jié)尾。
addstudentwidget.h
#ifndef ADDSTUDENTWIDGET_H
#define ADDSTUDENTWIDGET_H
#include
#include
#include
#include
namespace Ui {
class AddStudentWidget;
}
class AddStudentWidget : public QWidget
{
Q_OBJECT
public:
explicit AddStudentWidget(QWidget *parent = nullptr);
~AddStudentWidget();
private:
Ui::AddStudentWidget *ui;
signals:
void display(int number);
private slots:
void on_returnButton_clicked();
void on_addButton_clicked();
};
#endif // ADDSTUDENTWIDGET_H
addstudentwidget.cpp
#include "addstudentwidget.h"
#include "ui_addstudentwidget.h"
AddStudentWidget::AddStudentWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::AddStudentWidget)
{
ui->setupUi(this);
}
AddStudentWidget::~AddStudentWidget()
{
delete ui;
}
void AddStudentWidget::on_returnButton_clicked(){ //"主菜單"按鈕點(diǎn)擊
emit display(0);
}
void AddStudentWidget::on_addButton_clicked(){ //"添加"按鈕點(diǎn)擊
QString name = ui->nameLineEdit->text();
//將用戶(hù)輸入的姓名由nameLineEdit取出
int id = ui->idLineEdit->text().toInt();
//將用戶(hù)輸入的學(xué)號(hào)由idLineEdit取出,并轉(zhuǎn)換為整型
int math = ui->mathLineEdit->text().toInt();
//將用戶(hù)輸入的學(xué)號(hào)由mathLineEdit取出,并轉(zhuǎn)換為整型
int english = ui->enLineEdit->text().toInt();
//將用戶(hù)輸入的學(xué)號(hào)由enLineEdit取出,并轉(zhuǎn)化為整型
int languageC = ui->cLineEdit->text().toInt();
//將用戶(hù)輸入的學(xué)號(hào)由cLineEdit取出,并轉(zhuǎn)化為整型
if(ui->nameLineEdit->text() == "" || ui->idLineEdit->text() == "" || ui->mathLineEdit->text() == "" || ui->enLineEdit->text() == "" || ui->cLineEdit->text() == ""){
//插入的五項(xiàng)數(shù)據(jù)都不能為空,否則在讀取文件時(shí)會(huì)出現(xiàn)問(wèn)題。
QMessageBox::about(NULL, "反饋", "存在空項(xiàng)");
}
QFile file("student.txt");
//實(shí)例化一個(gè)QFile file為我們的數(shù)據(jù)文件student.txt
file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Append);
//open()可以用來(lái)打開(kāi)文件這里QIODevice::WriteOnly代表將文件以只寫(xiě)的方式打開(kāi)
//QIODevice::Text代表我們打開(kāi)的是文本文件,QIODevice::Text會(huì)對(duì)end-of-line結(jié)束符進(jìn)行轉(zhuǎn)譯
//QIODevice::Append以追加的方式打開(kāi),新增加的內(nèi)容將被追加到文件末尾
if(!file.isOpen()){ //如果數(shù)據(jù)文件沒(méi)有打開(kāi),彈出對(duì)話(huà)框提示用戶(hù)
QMessageBox::about(NULL, "反饋", "數(shù)據(jù)文件打開(kāi)失敗");
return;
}
QTextStream out(&file);
//QTextStream可以進(jìn)行一些基本的文本讀寫(xiě),比如QString int char之類(lèi)的數(shù)據(jù)QDataStream可以進(jìn)行一個(gè)如QMap QPoint之類(lèi)數(shù)據(jù)的讀寫(xiě)。
out << name << " " << id << " " << math << " " << english << " " << languageC;
//將我們剛剛獲取的數(shù)據(jù)寫(xiě)入文件
file.close();
QMessageBox::about(NULL, "反饋", "插入成功");
ui->nameLineEdit->clear();
ui->idLineEdit->clear();
ui->mathLineEdit->clear();
ui->enLineEdit->clear();
ui->cLineEdit->clear();
//將用戶(hù)輸入的數(shù)據(jù)清空
}
運(yùn)行一下
?
?
?
顯示插入成功,打開(kāi)項(xiàng)目文件夾所在目錄build-StudentManagementSystem開(kāi)頭的文件夾,我們的數(shù)據(jù)文件student就會(huì)出現(xiàn)在此處
?
打開(kāi)看一看
?
這樣,我們的添加信息模塊就完成了。
以上源代碼:
https://github.com/suvvm/StudentManagementSystem_Qt/tree/master/StudentManagementSystem_Qt_2(add)
7、完善修改信息
打開(kāi)modifywidget.h為”刪除”與”修改”按鈕設(shè)計(jì)點(diǎn)擊槽函數(shù),在modifywidget.cpp中給出函數(shù)定義。
對(duì)于刪除和修改操作這里我打算以文件中的數(shù)據(jù)建立一個(gè)數(shù)據(jù)類(lèi)型為StudentInfo的QVector容器,容器中盛放全體學(xué)生信息。對(duì)容器進(jìn)行刪改操作,最后以容器內(nèi)的數(shù)據(jù)覆蓋原有的數(shù)據(jù)即可。
modifywidget.h
#ifndef MODIFYWIDGET_H
#define MODIFYWIDGET_H
#include
#include
#include
#include
#include
#include "studentinfo.h"
namespace Ui {
class ModifyWidget;
}
class ModifyWidget : public QWidget
{
Q_OBJECT
public:
explicit ModifyWidget(QWidget *parent = nullptr);
~ModifyWidget();
private:
Ui::ModifyWidget *ui;
signals:
void display(int number);
private slots:
void on_returnButton_clicked(); //點(diǎn)擊主菜單按鈕
void on_deleteButton_clicked(); //點(diǎn)擊刪除按鈕
void on_modifyButton_clicked(); //點(diǎn)擊修改按鈕
};
#endif // MODIFYWIDGET_H
modifywidget.cpp
#include "modifywidget.h"
#include "ui_modifywidget.h"
ModifyWidget::ModifyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::ModifyWidget)
{
ui->setupUi(this);
}
ModifyWidget::~ModifyWidget()
{
delete ui;
}
void ModifyWidget::on_returnButton_clicked(){
emit display(0);
}
void ModifyWidget::on_deleteButton_clicked(){
QVector
if(ui->idLineEdit->text() == ""){ //如果id輸入欄為空則輸出錯(cuò)誤提示并返回
QMessageBox::about(NULL, "反饋", "id不得為空!");
return;
}
QFile file("student.txt");
file.open(QIODevice::ReadOnly|QIODevice::Text);
//以只讀 的方式打開(kāi)文本文件
if(!file.isOpen()){ //如果數(shù)據(jù)文件沒(méi)有打開(kāi),彈出對(duì)話(huà)框提示用戶(hù)
QMessageBox::about(NULL, "反饋", "數(shù)據(jù)文件打開(kāi)失敗");
return;
}
//QIODevice::Truncate在寫(xiě)入時(shí)會(huì)從文件開(kāi)始處寫(xiě)入,覆蓋原有內(nèi)容
QTextStream inp(&file);
//以file建立一個(gè)QT的文本流
while(!inp.atEnd()){
QString name;
int id, math, english, languageC;
inp >> name >> id >> math >> english >> languageC;
//讀入姓名 學(xué)號(hào) 數(shù)學(xué)成績(jī) 英語(yǔ)成績(jī) C語(yǔ)言成績(jī)
allStudentInfo.push_back(StudentInfo(name, id, math, english, languageC));
//調(diào)用之前建立的構(gòu)造函數(shù)實(shí)例化一個(gè)StudentInfo對(duì)象并將其加入allStudentInfo
}
allStudentInfo.pop_back(); //文件最后會(huì)多讀一個(gè)無(wú)用數(shù)據(jù),將其拿出
file.close();
int id = ui->idLineEdit->text().toInt();
//獲取用戶(hù)輸入的id
bool flag = false;
//記錄是否進(jìn)行過(guò)刪除
for(QVector
//用迭代器遍歷allStudentInfo
if(it->getId() == id){ //如果找到有id與該id相同的學(xué)生,就進(jìn)行刪除
allStudentInfo.erase(it);
flag = true;
}
}
if(flag){ //如果進(jìn)行過(guò)刪除,彈出對(duì)話(huà)框并更新文件
QMessageBox::about(NULL, "反饋", "刪除成功");
file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate);
//以只寫(xiě)覆蓋的方式打開(kāi)文本文件
if(!file.isOpen()){ //如果數(shù)據(jù)文件沒(méi)有打開(kāi),彈出對(duì)話(huà)框提示用戶(hù)
QMessageBox::about(NULL, "反饋", "數(shù)據(jù)文件打開(kāi)失敗");
return;
}
QTextStream out(&file);
for(auto i : allStudentInfo){
out << i.getName() << " " << i.getId() << " " << i.getMath() << " " << i.getEnglish() << " " << i.getLanguageC() << endl;
}
file.close();
}else{
//如果沒(méi)有進(jìn)行刪除,彈出不存在對(duì)話(huà)框
QMessageBox::about(NULL, "反饋", "id不存在!");
}
//關(guān)閉文件
ui->idLineEdit->clear();
//清空id輸入框
}
void ModifyWidget::on_modifyButton_clicked(){
if(ui->nameLineEdit->text() == "" || ui->idLineEdit->text() == "" || ui->mathLineEdit->text() == "" || ui->enLineEdit->text() == "" || ui->cLineEdit->text() == ""){
QMessageBox::about(NULL, "反饋", "存在空項(xiàng)");
return;
}
QVector
QFile file("student.txt");
file.open(QIODevice::ReadOnly|QIODevice::Text);
//以只讀 的方式打開(kāi)文本文件
if(!file.isOpen()){ //如果數(shù)據(jù)文件沒(méi)有打開(kāi),彈出對(duì)話(huà)框提示用戶(hù)
QMessageBox::about(NULL, "反饋", "數(shù)據(jù)文件打開(kāi)失敗");
return;
}
//QIODevice::Truncate在寫(xiě)入時(shí)會(huì)從文件開(kāi)始處寫(xiě)入,覆蓋原有內(nèi)容
QTextStream inp(&file);
//以file建立一個(gè)QT的文本流
while(!inp.atEnd()){
QString name;
int id, math, english, languageC;
inp >> name >> id >> math >> english >> languageC;
//讀入姓名 學(xué)號(hào) 數(shù)學(xué)成績(jī) 英語(yǔ)成績(jī) C語(yǔ)言成績(jī)
allStudentInfo.push_back(StudentInfo(name, id, math, english, languageC));
//調(diào)用之前建立的構(gòu)造函數(shù)實(shí)例化一個(gè)StudentInfo對(duì)象并將其加入allStudentInfo
}
allStudentInfo.pop_back(); //文件最后會(huì)多讀一個(gè)無(wú)用數(shù)據(jù),將其拿出
file.close();
int id = ui->idLineEdit->text().toInt();
QString name = ui->nameLineEdit->text();
int math = ui->mathLineEdit->text().toInt();
int english = ui->enLineEdit->text().toInt();
int languageC = ui->cLineEdit->text().toInt();
bool flag = false;
for(QVector
if(it->getId() == id){
it->setName(name);
it->setMath(math);
it->setEnglish(english);
it->setLanguageC(languageC);
flag = true;
}
}
if(flag){ //如果進(jìn)行過(guò)修改,彈出對(duì)話(huà)框并更新文件
QMessageBox::about(NULL, "反饋", "修改成功");
file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate);
//以只寫(xiě)覆蓋的方式打開(kāi)文本文件
if(!file.isOpen()){ //如果數(shù)據(jù)文件沒(méi)有打開(kāi),彈出對(duì)話(huà)框提示用戶(hù)
QMessageBox::about(NULL, "反饋", "數(shù)據(jù)文件打開(kāi)失敗");
return;
}
QTextStream out(&file);
for(auto i : allStudentInfo){
out << i.getName() << " " << i.getId() << " " << i.getMath() << " " << i.getEnglish() << " " << i.getLanguageC() << endl;
}
file.close();
}else{
//如果沒(méi)有進(jìn)行修改,彈出不存在對(duì)話(huà)框
QMessageBox::about(NULL, "反饋", "id不存在!");
}
//關(guān)閉文件
ui->idLineEdit->clear();
ui->nameLineEdit->clear();
ui->mathLineEdit->clear();
ui->enLineEdit->clear();
ui->cLineEdit->clear();
//清空所有輸入框
}
這樣,修改模塊就完成了
以上源代碼:
https://github.com/suvvm/StudentManagementSystem_Qt/tree/master/StudentManagementSystem_Qt%20_3(add%2Cmodify)
8、查詢(xún)模塊
打開(kāi)selectwidget.h為”刪除”與”修改”按鈕設(shè)計(jì)點(diǎn)擊槽函數(shù),在selectwidget.cpp中給出函數(shù)定義。
查詢(xún)可以在從文件讀取時(shí)判斷是否會(huì)讀取到id為輸入id的學(xué)生,也可以向修改一樣江所有學(xué)生信息先讀入到數(shù)據(jù)類(lèi)型為StudentInfo的QVector容器中,在從容器中查詢(xún)數(shù)據(jù),這里我選擇讀入到容器的方法。
selectwidget.h
#ifndef SELECTWIDGET_H
#define SELECTWIDGET_H
#include
#include
#include
#include
#include
#include "studentinfo.h"
namespace Ui {
class SelectWidget;
}
class SelectWidget : public QWidget
{
Q_OBJECT
public:
explicit SelectWidget(QWidget *parent = nullptr);
~SelectWidget();
private:
Ui::SelectWidget *ui;
signals:
void display(int number);
private slots:
void on_returnButton_clicked();
void on_selectButton_clicked();
};
#endif // SELECTWIDGET_H
selectwidget.cpp
#include "selectwidget.h"
#include "ui_selectwidget.h"
SelectWidget::SelectWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::SelectWidget)
{
ui->setupUi(this);
}
SelectWidget::~SelectWidget()
{
delete ui;
}
void SelectWidget::on_returnButton_clicked(){
emit display(0);
}
void SelectWidget::on_selectButton_clicked(){
if(ui->idLineEdit->text() == ""){
QMessageBox::about(NULL, "反饋", "id不能為空");
return;
}
QFile file("student.txt");
file.open(QIODevice::ReadOnly|QIODevice::Text);
//以只讀的方式打開(kāi)文本文件
if(!file.isOpen()){ //文件打開(kāi)失敗
QMessageBox::about(NULL, "反饋", "文件打開(kāi)失敗");
return;
}
QTextStream inp(&file);
//以file作為Qt文本流
QVector
//數(shù)據(jù)類(lèi)型為StudentInfo的QVector容器
while(!inp.atEnd()){ //讀到文件結(jié)尾
QString name;
int id, math, english, languageC;
inp >> name >> id >> math >> english >> languageC;
allStudentInfo.push_back(StudentInfo(name, id, math, english, languageC));
//調(diào)用之前建立的構(gòu)造函數(shù)實(shí)例化一個(gè)StudentInfo對(duì)象并將其加入allStudentInfo
}
allStudentInfo.pop_back();
//扔掉最后的無(wú)用數(shù)據(jù)
file.close();
//關(guān)閉文件
int id = ui->idLineEdit->text().toInt();
bool flag = false;
for(auto i : allStudentInfo){
if(i.getId() == id){
ui->showNameLabel->setText(i.getName());
ui->showMathLabel->setText(QString::number(i.getMath()));
ui->showEnLabel->setText(QString::number(i.getEnglish()));
ui->showCLabel->setText(QString::number(i.getLanguageC()));
ui->showAvgLabel->setText(QString::number(i.getAvg()));
flag = true;
break;
}
}
if(!flag){
QMessageBox::about(NULL, "反饋", "id不存在!");
}
ui->idLineEdit->clear();
}
以上源代碼
https://github.com/suvvm/StudentManagementSystem_Qt/tree/master/StudentManagementSystem_Qt_4(add%2Cmodify%2Cselect)
9、排序模塊
老樣子,將數(shù)據(jù)從文件中讀入數(shù)據(jù)類(lèi)型為StudentInfo的QVector容器后進(jìn)行排序就容易很多了。
我們需要排序時(shí)只能根據(jù)數(shù)學(xué)、英語(yǔ)、C語(yǔ)言、平均成績(jī)中的一種進(jìn)行排序,所以我們要做到代表這四種排序方式的QRedioButton有且只有一個(gè)能被選中,我們可以將其加入一個(gè)QButtonGroup,這樣便可以實(shí)現(xiàn)這個(gè)需求,至于顯示排序后的數(shù)據(jù)我們可以顯示在表格控件QTableWidget中。
QButtonGroup直接繼承自QObject,他有一個(gè)屬性exclusive當(dāng)這個(gè)屬性為真時(shí),所有在QButtonGroup內(nèi)的按鈕同一時(shí)間只有一個(gè)可以被選擇。
QButtonGroup我們用到了addButton添加按鈕 與checkedId獲取選中按鈕的id兩個(gè)方法,其他方法諸位可以自己去搜索。
QTableWidget繼承自QTableView,QTableView可以自定義的數(shù)據(jù)模型顯示內(nèi)容(setModel)但是QTableWidget不行,QTableWidget有固定的數(shù)據(jù)模型,在像其中填入數(shù)據(jù)時(shí)只需要一個(gè)單元格一個(gè)單元格的填好就可以了(setItem)
QTableWidget我們用到了setHorizontalHeaderLabels設(shè)置水平表頭標(biāo)簽horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); 設(shè)置根據(jù)總寬度調(diào)整列寬;setRowCount設(shè)置行數(shù);setItem設(shè)置單元格,其他方法諸位可以自己去搜索。
sortwidget.h
#ifndef SORTWIDGET_H
#define SORTWIDGET_H
#include
#include
#include
#include
#include
#include
#include "studentinfo.h"
namespace Ui {
class SortWidget;
}
class SortWidget : public QWidget
{
Q_OBJECT
public:
explicit SortWidget(QWidget *parent = nullptr);
~SortWidget();
private:
Ui::SortWidget *ui;
QButtonGroup *sortButtonGroup;
signals:
void display(int number);
private slots:
void on_returnButton_clicked(); //返回菜單
void on_sortButton_clicked(); //排序
};
#endif // SORTWIDGET_H
sortwidget.cpp
#include "sortwidget.h"
#include "ui_sortwidget.h"
#include
SortWidget::SortWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::SortWidget)
{
ui->setupUi(this);
sortButtonGroup = new QButtonGroup();
//實(shí)例化sortButtonGroup
sortButtonGroup->addButton(ui->mathRadioButton, 0);
//將代表數(shù)學(xué)的單選框加入sortButtonGroup并將其id設(shè)為0
//不建議使用默認(rèn)id,默認(rèn)id是由-2開(kāi)始依次遞減的
sortButtonGroup->addButton(ui->enRadioButton, 1);
//將代表英語(yǔ)的單選框加入sortButtonGroup并將其id設(shè)為1
sortButtonGroup->addButton(ui->cRadioButton, 2);
//將代表C語(yǔ)言的單選框加入sortButtonGroup并將其id設(shè)為2
sortButtonGroup->addButton(ui->avgRadioButton, 3);
//將代表平均的單選框加入sortButtonGroup并將其id設(shè)為3
ui->avgRadioButton->setChecked(true);
//平均成績(jī)默認(rèn)選中
ui->tableWidget->setColumnCount(6);
QStringList headerLabels;
//QStringList headerLabels用來(lái)記錄表格表頭數(shù)據(jù)
headerLabels << tr("姓名") << tr("學(xué)號(hào)") << tr("數(shù)學(xué)") << tr("英語(yǔ)") << tr("C語(yǔ)言") << tr("平均");
ui->tableWidget->setHorizontalHeaderLabels(headerLabels);
// void setHorizontalHeaderLabels(const QStringList &labels);設(shè)置水平表頭標(biāo)簽
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
//設(shè)置根據(jù)總寬度調(diào)整列寬
ui->tableWidget->setRowCount(1);
//初始行數(shù)設(shè)為一行
}
SortWidget::~SortWidget()
{
delete ui;
}
void SortWidget::on_returnButton_clicked(){
emit display(0);
}
bool getStudentInfo(QVector
QFile file("student.txt");
file.open(QIODevice::ReadOnly|QIODevice::Text);
//以只讀方式打開(kāi)文本文件student.txt
QTextStream inp(&file);
if(!file.isOpen()){ //文件打開(kāi)失敗
QMessageBox::about(NULL, "反饋", "數(shù)據(jù)文件打開(kāi)失敗");
return false;
}
while(!inp.atEnd()){ //讀到文件結(jié)尾
QString name;
int id, math, english, languageC;
inp >> name >> id >> math >> english >> languageC;
allStudentInfo.push_back(StudentInfo(name, id, math, english, languageC));
//調(diào)用之前聲明的構(gòu)造函數(shù)實(shí)例化一個(gè)StudentInfo對(duì)象并將其加入allStudentInfo
}
allStudentInfo.pop_back();
//扔掉最后的無(wú)用數(shù)據(jù)
file.close();
//關(guān)閉文件
return true;
}
bool cmp_math(StudentInfo a, StudentInfo b){ //數(shù)學(xué)排序
return a.getMath() > b.getMath();
}
bool cmp_English(StudentInfo a, StudentInfo b){ //英語(yǔ)排序
return a.getEnglish() > b.getEnglish();
}
bool cmp_languageC(StudentInfo a, StudentInfo b){ //C語(yǔ)言排序
return a.getLanguageC() > b.getLanguageC();
}
bool cmp_avg(StudentInfo a, StudentInfo b){ //平均成績(jī)排序
return a.getAvg() > b.getAvg();
}
void SortWidget::on_sortButton_clicked(){
ui->tableWidget->clearContents();
//清空除表頭外的所有數(shù)據(jù)
//若想清除表頭可使用clear()
int sortTag = sortButtonGroup->checkedId();
//取得當(dāng)前選中的單選框的id
QVector
//數(shù)據(jù)類(lèi)型為StudentInfo的QVector容器
if(!getStudentInfo(allStudentInfo)) //從文件讀取數(shù)據(jù)到allStudentInfo
return; //讀取失敗直接返回
if(allStudentInfo.empty()){ //allStudentInfo中沒(méi)有數(shù)據(jù)
QMessageBox::about(NULL, "反饋", "沒(méi)有學(xué)生信息");
return;
}
switch (sortTag) {
case 0: //sortTag==0根據(jù)數(shù)學(xué)進(jìn)行排序
std::sort(allStudentInfo.begin(), allStudentInfo.end(), cmp_math);
break;
case 1: //sortTag==1根據(jù)英語(yǔ)進(jìn)行排序
std::sort(allStudentInfo.begin(), allStudentInfo.end(), cmp_English);
break;
case 2: //sortTag==2根據(jù)C語(yǔ)言進(jìn)行排序
std::sort(allStudentInfo.begin(), allStudentInfo.end(), cmp_languageC);
break;
case 3: //sortTag==3根據(jù)平均成績(jī)進(jìn)行排序
std::sort(allStudentInfo.begin(), allStudentInfo.end(), cmp_avg);
break;
}
ui->tableWidget->setRowCount(allStudentInfo.size());
//將表格的行數(shù)設(shè)為與學(xué)生數(shù)量相同
//否則setItem添加單元格不會(huì)生效
for(int i = 0; i < allStudentInfo.size(); i++){
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(allStudentInfo[i].getName()));
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(QString::number(allStudentInfo[i].getId())));
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(QString::number(allStudentInfo[i].getMath())));
ui->tableWidget->setItem(i, 3, new QTableWidgetItem(QString::number(allStudentInfo[i].getEnglish())));
ui->tableWidget->setItem(i, 4, new QTableWidgetItem(QString::number(allStudentInfo[i].getLanguageC())));
ui->tableWidget->setItem(i, 5, new QTableWidgetItem(QString::number(allStudentInfo[i].getAvg())));
//設(shè)置各單元格的數(shù)據(jù),非QString類(lèi)型的數(shù)據(jù)需要轉(zhuǎn)換為QString
}
}
到此為止我們整個(gè)項(xiàng)目便完成。
Qt開(kāi)發(fā)資料點(diǎn)擊下面群號(hào)領(lǐng)取
柚子快報(bào)邀請(qǐng)碼778899分享:Qt教程—學(xué)生管理系統(tǒng)(文件)
好文鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。