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