QT安装
任务要求
-
题目要求如下:
- 学生信息:学号、姓名、班级、电话、生日、住址、选课数据集。
- 选课信息:课程编号、课程名称、学分、学期、教室、成绩。
- 创建和管理学生信息的对象;
- 创建和管理选课信息的对象;
- 增加和删除学生;
- 针对特定学生增加和删除选课信息 ;
- 基本查询功能;
- 数据文件读写:文件中包含所有学生信息、每个学生的选课信息等数据;
- 基本信息显示:1)所有学生的信息显示;2)特定学生的选课信息;
- 可选功能提升:特定课程的选课学生显示、成绩排名等。
项目分析
系统设计
分析设计任务可以知道, 每个学生要包括复数个课程信息,同时复数个学生组成学生表 进行统一管理。
- 创建四个类,分别是课程类、课程表类、学生类、学生表类,课程表类中为课程类的列表类,学生类的成员包括课程表类,学生表类为学生类的列表;
- 因为要针对特定学生或特定课程进行操作,所以要针对不同的信息显示界面进行选择索引的储存;
- 作为一个界面程序,要注意因为一些操作失误或对程序不熟悉而产生的程序崩溃,尽量避免bug的出现。
功能分析
根据题目要求,程序要完成以下功能:
- 添加/删除学生信息;
- 对特定的学生添加/删除课程信息;
- 对学生信息/课程信息进行查询,并在查询后可进行修改或删除操作;
- 数据读写:可直接读取/保存到数据库中,也可打开其他文件并另存为;
- 可查找特定课程的选课学生的信息,并可对成绩进行排序;
- 在操作错误时可以弹出对话框提醒。
设计思路
-
完成课程类、课程队列类、学生类、学生队列类四个类的创建:课程表类中为课程类的列表类,学生类的成员包括课程表类,学生表类为学生类的列表,数据结构如下图: -
界面设计,尽量简洁美观: 通过对界面进行不同层次的布局操作让界面控件大小可以随窗口大小改变而改变,同时添加对话框中有label控件提醒,避免空文本的出现; -
四个类与界面进行对接,通过界面可对创建类进行操作: 调用四个类中的成员函数,获取或修改类信息,同时用m_View_kind记录目前视图类型:0显示学生信息,1显示选课信息,2显示从0表查询,3显示从1表中查询,4显示特定课程的选课学生,在不同视图下可以进行相应的操作,而不能进行的操作,程序会进行提醒,避免bug的出现; -
不同视图的显示要及时对视图种类和选中列表的索引进行刷新: 学生信息视图作为最底层视图,在这层视图时所用选中索引要进行刷新,学生信息视图作为主视图,课程信息视图作为副主视图,索引的刷新在这两个视图中进行,结构如下图; -
在查询时要将查询结果的索引及时储存: 方便直接对查询结果进行操作,并注意推出查询要及时刷新,其中学生信息查询结果中的索引放入indexlist中,课程信息查询结果中的索引放入indexlist1中,可直接在查询结果视图中对成员对象进行操作; -
特定课程进行学生信息显示: 通过对所有学生进行遍历操作进行查找,将结果索引进行储存显示,成绩排序运用QList中的qSort()函数直接对结构体中的某个属性进行排序; -
在操作失误时会有提醒对话框: 创建一个提醒对话框,在进行可能会导致程序崩溃的操作时弹出制止;
文件与对象描述(代码)
课程类
文件:course.h\ .cpp//课程类: c_ID//课程编号;c_Name//课程名称;credit//学分;term//学期;c_room//教室;grade//成绩
#include<QTextStream>
#include<qstring.h>
#include<qdatetime.h>
#include<qlist.h>
#include<QFile>
#include <QMessageBox>
#include<QFileDialog>
#include<QTextCodec>
#include <QAbstractItemDelegate>
#include<QAbstractItemView>
class Course
{
public:
Course();
virtual ~Course();
Course& operator= (const Course & course);
void SaveCourse(QTextStream &aStream);
void ReadCourse(QTextStream &aStream);
QString c_ID;
QString c_Name;
float credit;
QString term;
QString c_room;
float grade;
};
#include "course.h"
Course::Course()
{
c_ID="";
c_Name="";
credit=0;
term="";
c_room="";
grade=0;
}
Course::~Course()
{
}
Course& Course::operator=(const Course &course)
{
c_ID=course.c_ID;
c_Name=course.c_Name;
credit=course.credit;
term=course.term;
c_room=course.c_room;
grade=course.grade;
return *this;
}
void Course::SaveCourse(QTextStream &aStream)
{
aStream<<c_ID<<"\t"<<c_Name<<"\t"<<credit<<"\t"<<term<<"\t"<<c_room<<"\t"<<grade<<"\n";
}
void Course::ReadCourse(QTextStream &aStream)
{
aStream>>c_ID;
aStream>>c_Name;
aStream>>credit;
aStream>>term;
aStream>>c_room;
aStream>>grade;
}
课程表类
这里课程表和后面的学生表用QT5中的Qlist< Data >数据类型; 文件:courseinfotable.h\ .cpp//课程队列类: m_course//课程类列表Qlist<Course>;c_num//课程数
#include"course.h"
class CourseInfoTable
{
public:
CourseInfoTable();
CourseInfoTable& operator= (const CourseInfoTable & course);
void SaveCourseInfoTable(QTextStream &aStream);
void ReadCourseInfoTable(QTextStream &aStream);
void AddCourse(Course& course);
void DelCourse(int index);
Course& GetCourse(int index);
int CourseNum();
QList<Course> m_course;
int c_num;
};
#include "courseinfotable.h"
CourseInfoTable::CourseInfoTable()
{
m_course={};
c_num=0;
}
CourseInfoTable& CourseInfoTable::operator=(const CourseInfoTable &course)
{
m_course=course.m_course;
c_num=course.c_num;
return *this;
}
int CourseInfoTable::CourseNum()
{
c_num=m_course.size();
return this->c_num;
}
void CourseInfoTable::SaveCourseInfoTable(QTextStream &aStream)
{
int num=CourseNum();
aStream<<num<<"\n";
for(int i=0;i<num;i++)
{
Course temp = m_course[i];
temp.SaveCourse(aStream);
}
}
void CourseInfoTable::ReadCourseInfoTable(QTextStream &aStream)
{
aStream>>c_num;
for(int i=0;i<c_num;i++)
{
Course temp;
temp.ReadCourse(aStream);
m_course.append(temp);
}
}
void CourseInfoTable::AddCourse(Course &course)
{
m_course.append(course);
}
void CourseInfoTable::DelCourse(int index)
{
m_course.removeAt(index);
c_num-=1;
}
Course& CourseInfoTable::GetCourse(int index)
{
return m_course[index];
}
学生类
文件:student.h\ .cpp//学生类: s_ID//学号;s_Name//姓名;s_class//班级;ph_number//电话;birthday//生日;adress//地址;s_courses//课程队列类CourseInfoTable
class Student
{
public:
Student();
Student& operator= (const Student& man);
virtual ~Student();
void SaveStudent(QTextStream &aStream);
void ReadStudent(QTextStream &aStream);
bool is_courses();
QString s_ID;
QString s_Name;
QString s_class;
QString ph_number;
QDate birthday;
QString adress;
CourseInfoTable s_courses;
};
#include "student.h"
Student::Student()
{
s_ID="";
s_Name="";
s_class="";
ph_number="";
birthday=QDate();
adress="";
s_courses=CourseInfoTable();
}
Student::~Student()
{
}
Student& Student::operator=(const Student &man)
{
s_ID=man.s_ID;
s_Name=man.s_Name;
s_class=man.s_class;
ph_number=man.ph_number;
birthday=man.birthday;
adress=man.adress;
s_courses=man.s_courses;
return *this;
}
void Student::SaveStudent(QTextStream &aStream)
{
aStream<<s_ID<<"\t";
aStream<<s_Name<<"\t";
aStream<<s_class<<"\n";
aStream<<ph_number<<"\n";
aStream<<birthday.year()<<"\t"<<birthday.month()<<"\t"<<birthday.day()<<"\n";
aStream<<adress<<"\n";
s_courses.CourseInfoTable::SaveCourseInfoTable(aStream);
}
void Student::ReadStudent(QTextStream &aStream)
{
int year,month,day;
aStream>>s_ID;
aStream>>s_Name;
aStream>>s_class;
aStream>>ph_number;
aStream>>year;
aStream>>month;
aStream>>day;
aStream>>adress;
birthday.setDate(year,month,day);
s_courses.ReadCourseInfoTable(aStream);
}
bool Student::is_courses()
{
return s_courses.CourseNum()==0;
}
学生表类
文件:studentinfotable.h.cpp//学生队列类: m_student//学生队列类QList<Student>;s_num//学生数量
class StudentInfoTable
{
public:
StudentInfoTable();
StudentInfoTable& operator= (const StudentInfoTable & student);
void SaveStudentInfoTable(QTextStream &aStream);
void ReadCourseInfoTable(QTextStream &aStream);
void AddStudent(Student& student);
void DelStudent(int index);
Student& GetStudent(int index);
int StudentNum();
QList<Student> m_student;
int s_num;
};
#include "studentinfotable.h"
StudentInfoTable::StudentInfoTable()
{
m_student=QList<Student>();
s_num=0;
}
StudentInfoTable& StudentInfoTable::operator=(const StudentInfoTable &student)
{
m_student=student.m_student;
s_num=student.s_num;
return *this;
}
void StudentInfoTable::SaveStudentInfoTable(QTextStream &aStream)
{
int num=StudentNum();
aStream<<num<<"\n";
for(int i=0;i<num;i++)
{
m_student[i].SaveStudent(aStream);
aStream<<"\n";
}
}
void StudentInfoTable::ReadCourseInfoTable(QTextStream &aStream)
{
aStream>>s_num;
for(int i=0;i<s_num;i++)
{
Student temp_s;
temp_s.ReadStudent(aStream);
m_student.append(temp_s);
}
}
void StudentInfoTable::AddStudent(Student &student)
{
m_student.append(student);
s_num+=1;
}
void StudentInfoTable::DelStudent(int index)
{
m_student.removeAt(index);
s_num-=1;
}
Student& StudentInfoTable::GetStudent(int index)
{
return m_student[index];
}
int StudentInfoTable::StudentNum()
{
s_num=m_student.size();
return s_num;
}
UI设计
创建方法:
- 右击项目>>Add new>>Qt>>Qt设计师界面类
- 可以选择各种不同类别的对话框和主界面
- 创建成功后会自动生成.h .cpp和.ui文件,双击.ui文件即可对界面进行设计布局。
添加学生信息对话框
文件:inputdialog_s.h\ .cpp\ .ui//添加学生对话框类: 返回对话框中textEdit中的文本
- inputdialog_s.ui界面设计
注意:
- 在界面设计完后要对项目进行构建(点那个小锤子),这样在编辑.h和.cpp文件时在才会有我们添加的控件对象。
- 选择任意一个控件右键会有转到槽的选项,比如在这个对话框中选择textEdit控件:
#include <QDialog>
#include<QTextEdit>
namespace Ui {
class InputDialog_s;
}
class InputDialog_s : public QDialog
{
Q_OBJECT
public:
explicit InputDialog_s(QWidget *parent = nullptr);
~InputDialog_s();
QString is_Error();
void Show_error(const QString&tempstr);
QString Get_ID();
QString Get_Name();
QString Get_Class();
QString Get_number();
QDate Get_bir();
QString Get_adress();
void Label_Show();
private slots:
void on_textEdit_selectionChanged();
void on_textEdit_6_selectionChanged();
void on_textEdit_2_selectionChanged();
void on_textEdit_3_selectionChanged();
void on_textEdit_4_selectionChanged();
void on_dateEdit_editingFinished();
void on_textEdit_textChanged();
void on_textEdit_2_textChanged();
void on_textEdit_3_textChanged();
void on_textEdit_4_textChanged();
void on_textEdit_6_textChanged();
private:
Ui::InputDialog_s *ui;
};
#include "inputdialog_s.h"
#include "ui_inputdialog_s.h"
InputDialog_s::InputDialog_s(QWidget *parent) :
QDialog(parent),
ui(new Ui::InputDialog_s)
{
ui->setupUi(this);
}
InputDialog_s::~InputDialog_s()
{
delete ui;
}
QString InputDialog_s::Get_ID()
{
return ui->textEdit->toPlainText();
}
QString InputDialog_s::Get_Name()
{
return ui->textEdit_2->toPlainText();
}
QString InputDialog_s::Get_Class()
{
return ui->textEdit_3->toPlainText();
}
QString InputDialog_s::Get_number()
{
return ui->textEdit_4->toPlainText();
}
QDate InputDialog_s::Get_bir()
{
return ui->dateEdit->date();
}
QString InputDialog_s::Get_adress()
{
return ui->textEdit_6->toPlainText();
}
QString InputDialog_s::is_Error()
{
QString error;
if(Get_ID().isEmpty())
{
error="学号";
return error;
}
else if(Get_Name().isEmpty())
{
error="姓名";
return error;
}
else if(Get_Class().isEmpty())
{
error="班级";
return error;
}
else if(Get_number().isEmpty())
{
error="电话";
return error;
}
else if(Get_adress().isEmpty())
{
error="地址";
return error;
}
else
{
error="OK";
return error;
}
}
void InputDialog_s::Show_error(const QString &tempstr)
{
ui->label_7->setText(tempstr);
ui->label_7->setAlignment(Qt::AlignRight);
}
void InputDialog_s::Label_Show()
{
QString error=is_Error();
if(error=="OK")Show_error("点击OK即可添加!");
else Show_error(QString("%1为空!请输入!!").arg(error));
}
void InputDialog_s::on_textEdit_selectionChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_6_selectionChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_2_selectionChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_3_selectionChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_4_selectionChanged()
{
Label_Show();
}
void InputDialog_s::on_dateEdit_editingFinished()
{
Label_Show();
}
void InputDialog_s::on_textEdit_textChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_2_textChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_3_textChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_4_textChanged()
{
Label_Show();
}
void InputDialog_s::on_textEdit_6_textChanged()
{
Label_Show();
}
- 运行效果如下:
添加选课信息对话框
#include <QDialog>
namespace Ui {
class InputDialog_c;
}
class InputDialog_c : public QDialog
{
Q_OBJECT
public:
explicit InputDialog_c(QWidget *parent = nullptr);
~InputDialog_c();
QString is_Error();
void Show_error(const QString&tempstr);
void Show_Label();
QString Get_ID();
QString Get_Name();
float Get_Credit();
QString Get_term();
QString Get_room();
float Get_grade();
private slots:
void on_textEdit_selectionChanged();
void on_textEdit_textChanged();
void on_textEdit_2_selectionChanged();
void on_textEdit_2_textChanged();
void on_textEdit_3_selectionChanged();
void on_textEdit_3_textChanged();
void on_textEdit_4_selectionChanged();
void on_textEdit_4_textChanged();
void on_textEdit_5_selectionChanged();
void on_textEdit_5_textChanged();
void on_textEdit_6_textChanged();
void on_textEdit_6_selectionChanged();
private:
Ui::InputDialog_c *ui;
};
#include "inputdialog_c.h"
#include "ui_inputdialog_c.h"
InputDialog_c::InputDialog_c(QWidget *parent) :
QDialog(parent),
ui(new Ui::InputDialog_c)
{
ui->setupUi(this);
}
InputDialog_c::~InputDialog_c()
{
delete ui;
}
QString InputDialog_c::Get_ID()
{
return ui->textEdit->toPlainText();
}
QString InputDialog_c::Get_Name()
{
return ui->textEdit_2->toPlainText();
}
float InputDialog_c::Get_Credit()
{
return ui->textEdit_3->toPlainText().toFloat();
}
QString InputDialog_c::Get_term()
{
return ui->textEdit_4->toPlainText();
}
QString InputDialog_c::Get_room()
{
return ui->textEdit_5->toPlainText();
}
float InputDialog_c::Get_grade()
{
return ui->textEdit_6->toPlainText().toFloat();
}
QString InputDialog_c::is_Error()
{
QString error;
if(Get_ID().isEmpty())
{
error="课程编号";
return error;
}
else if(Get_Name().isEmpty())
{
error="课程名称";
return error;
}
else if(ui->textEdit_3->toPlainText().isEmpty())
{
error="学分";
return error;
}
else if(Get_term().isEmpty())
{
error="学期";
return error;
}
else if(Get_room().isEmpty())
{
error="教室";
return error;
}
else if(ui->textEdit_6->toPlainText().isEmpty())
{
error="成绩";
return error;
}
else
{
error="OK";
return error;
}
}
void InputDialog_c::Show_error(const QString &tempstr)
{
ui->label_7->setText(tempstr);
ui->label_7->setAlignment(Qt::AlignRight);
}
void InputDialog_c::Show_Label()
{
QString error=is_Error();
if(error=="OK")Show_error("点击OK即可添加!");
else Show_error(QString("%1为空!请输入!!").arg(error));
}
void InputDialog_c::on_textEdit_selectionChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_textChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_2_selectionChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_2_textChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_3_selectionChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_3_textChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_4_selectionChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_4_textChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_5_selectionChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_5_textChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_6_textChanged()
{
Show_Label();
}
void InputDialog_c::on_textEdit_6_selectionChanged()
{
Show_Label();
}
- 运行效果如下:
信息查询对话框
注意:这里的查询对话框只是得到查询信息的关键词,真正的查询的运行是在主窗口(MainWindow)中。
学生信息查询
文件:selectdialog.h\ .cpp\ .ui//学生查询对话框: 可通过学号、姓名、班级三个特征进行查询
- selectdialog.ui设计
- selectdialog.h
#include <QDialog>
namespace Ui {
class SelectDialog;
}
class SelectDialog : public QDialog
{
Q_OBJECT
public:
explicit SelectDialog(QWidget *parent = nullptr);
~SelectDialog();
QString Get_Value();
int Get_Comboboxindex();
QString Get_Comboboxtext();
private slots:
void on_comboBox_currentIndexChanged(const QString &arg1);
private:
Ui::SelectDialog *ui;
int m_index;
};
#include "selectdialog.h"
#include "ui_selectdialog.h"
SelectDialog::SelectDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SelectDialog)
{
ui->setupUi(this);
m_index=0;
}
SelectDialog::~SelectDialog()
{
delete ui;
}
QString SelectDialog::Get_Value()
{
return ui->textEdit->toPlainText();
}
int SelectDialog::Get_Comboboxindex()
{
return m_index;
}
void SelectDialog::on_comboBox_currentIndexChanged(const QString &arg1)
{
if(arg1=="学号")
m_index=0;
else if(arg1=="姓名")
m_index=1;
else m_index=2;
}
QString SelectDialog::Get_Comboboxtext()
{
if(m_index==0)return QString("学号");
else if(m_index==1)return QString("姓名");
else return QString("班级");
}
选课信息查询
与学生信息查询相似
文件:selectdialog1.h\ .cpp\ .ui//课程查询对话框: 可通过课程编号、课程名称两个特征进行查询
- selectdialog1.ui设计
- selectdialog1.h
#include <QDialog>
namespace Ui {
class SelectDialog1;
}
class SelectDialog1 : public QDialog
{
Q_OBJECT
public:
explicit SelectDialog1(QWidget *parent = nullptr);
~SelectDialog1();
QString Get_Value();
int Get_Comboboxindex();
QString Get_Comboboxtext();
private slots:
void on_comboBox_currentIndexChanged(const QString &arg1);
private:
Ui::SelectDialog1 *ui;
int m_index;
};
#include "selectdialog1.h"
#include "ui_selectdialog1.h"
SelectDialog1::SelectDialog1(QWidget *parent) :
QDialog(parent),
ui(new Ui::SelectDialog1)
{
ui->setupUi(this);
m_index=0;
}
SelectDialog1::~SelectDialog1()
{
delete ui;
}
QString SelectDialog1::Get_Value()
{
return ui->textEdit->toPlainText();
}
int SelectDialog1::Get_Comboboxindex()
{
return m_index;
}
QString SelectDialog1::Get_Comboboxtext()
{
if(m_index==0)return QString("课程编号");
else return QString("课程名称");
}
void SelectDialog1::on_comboBox_currentIndexChanged(const QString &arg1)
{
if(arg1=="课程编号")
m_index=0;
else m_index=1;
}
提示对话框
文件:tipsdialog.h\ .cpp\ .ui//提醒对话框: 避免一些禁止操作,并提醒
-
tipsdialog.ui -
tipsdialog.h
#include <QDialog>
namespace Ui {
class TipsDialog;
}
class TipsDialog : public QDialog
{
Q_OBJECT
public:
explicit TipsDialog(QWidget *parent = nullptr);
~TipsDialog();
void Tips_Show(const QString&tempstr);
private:
Ui::TipsDialog *ui;
};
#include "tipsdialog.h"
#include "ui_tipsdialog.h"
TipsDialog::TipsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::TipsDialog)
{
ui->setupUi(this);
setWindowTitle("提示");
}
TipsDialog::~TipsDialog()
{
delete ui;
}
void TipsDialog::Tips_Show(const QString &tempstr)
{
ui->label->setText(tempstr);
}
主窗口设计?
概览
文件:mainwindow.h\ .cpp\ .ui//主窗口: *ui//主窗口对象; *studentTableView//表格视图对象; m_students//学生队列类; m_View_kind//目前视图类型0显示学生信息,1显示选课信息,2显示从0表查询,3显示从1表中查询,4显示特定课程的选课学生; m_row//学生视图0选中索引; indexlist//记录学生信息0中查询结果索引,在查询视图可以进行删除、修改操作QList<int>; m_row1//课程信息视图1选中索引; indexlist1//记录课程信息1中查询结果索引,在查询视图可以进行删除、修改操作QList<int>;
#include <QMainWindow>
#include<QStandardItemModel>
#include"studentinfotable.h"
#include <QAbstractItemDelegate>
#include <QModelIndex>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void Show_Label1(const QString&tempstr);
void Show_Label2(const QString&tempstr);
void Show_Label(const QString&tempstr);
void Show_StudentTable();
void Show_Table_s_changed();
void Show_CourseTable();
void Show_Table_c_changed();
void Show_SelectTable();
void Show_Table_sc_changed();
void Show_CtoSTable();
private slots:
void on_actionOpen_triggered();
void on_actionSave_triggered();
void on_actionLoading_triggered();
void on_actionSaveto_triggered();
void on_actionAdd_s_triggered();
void on_actionShow_s_triggered();
void on_tableView_clicked(const QModelIndex &index);
void on_actionDel_s_triggered();
void on_actionAdd_c_triggered();
void on_actionShow_c_triggered();
void on_actionDel_c_triggered();
void on_actionSelect_triggered();
void on_ShowInfotableView_changed();
void on_actionChange_triggered();
void on_actionChangedSave_triggered();
void on_actionCtoS_Show_triggered();
void on_actionAscending_triggered();
void on_actionDescending_triggered();
void on_tableView_doubleClicked(const QModelIndex &index);
private:
Ui::MainWindow *ui;
QStandardItemModel *studentTableView;
StudentInfoTable m_students;
int m_View_kind;
int m_row;
QList<int> indexlist;
int m_row1;
QList<int> indexlist1;
bool can_change;
};
界面UI设计
直接利用添加菜单栏功能,大体设计如下: 注意:在添加完菜单功能时,会自动生成该Action Editor,如下图:
右键选择转到槽后会在mainwindow.h中自动生成该对应的槽函数,如下图: 因为该cpp文件不少于1000行,这里就详细解释几个重要的操作,其他的可以举一反三。
构造函数
#include"readonlydelegate.h"
#include"tipsdialog.h"
#include"inputdialog_c.h"
#include"selectdialog.h"
#include"selectdialog1.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
studentTableView=new QStandardItemModel();
ui->tableView->setModel(studentTableView);
connect(ui->tableView->itemDelegate(),&QAbstractItemDelegate::closeEditor,this,&MainWindow::on_ShowInfotableView_changed);
m_View_kind=0;
m_row=-1;
indexlist=QList<int>();
m_row1=-1;
indexlist1=QList<int>();
can_change=false;
}
打开保存文件
- 在学生表类中我们已经写好了文件读取和文件保存,这里直接调用就好
void MainWindow::on_actionOpen_triggered()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "选择一个文件";
QString filter = "文本文件(*.txt);;所有文件(*.*)";
QString aFileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);
if(aFileName.isEmpty())
{
Show_Label2("打开文件失败!");
return;
}
Show_Label2("正在打开文件。。。");
QFile aFile(aFileName);
if(!aFile.exists())
{
Show_Label2("打开文件失败!");
return;
}
if(!aFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
Show_Label2("打开文件失败!");
return;
}
m_students=StudentInfoTable();
QTextStream aStream(&aFile);
aStream.setCodec(QTextCodec::codecForName("system"));
m_students.ReadCourseInfoTable(aStream);
aFile.close();
Show_Label2("文件读取成功!");
Show_StudentTable();
}
void MainWindow::on_actionSaveto_triggered()
{
QString curPath = QDir::currentPath();
QString dlgTitle = "另存为一个文件";
QString filter = "文本文件(*.txt);;所有文件(*.*)";
QString aFileName = QFileDialog::getSaveFileName(this, dlgTitle, curPath, filter);
if(aFileName.isEmpty())
{
Show_Label2("保存文件失败!");
return;
}
QFile aFile(aFileName);
if(!aFile.open(QIODevice::WriteOnly| QIODevice::Text))
{
Show_Label2("保存文件失败!");
return;
}
QTextStream aStream(&aFile);
aStream.setCodec(QTextCodec::codecForName("system"));
m_students.SaveStudentInfoTable(aStream);
aFile.close();
Show_Label2("文件保存成功!");
}
表格视图控件(tableView)使用?
- 上面贴的头文件和构造函数里我们已经构造了表格视图对象
QStandardItemModel *studentTableView; //表格视图 - 下面我将介绍以下如何填充这个表格(以学生信息为例),代码如下:
void MainWindow::Show_StudentTable()
{
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
can_change=false;
m_View_kind=0;
m_row=-1;
m_row1=-1;
Show_Label("学生信息视图");
studentTableView->clear();
studentTableView->setColumnCount(7);
QStringList templist;
templist<<"学号"<<"姓名"<<"班级"<<"电话"<<"生日"<<"地址"<<"是否选课";
studentTableView->setHorizontalHeaderLabels(templist);
int RowCnt=m_students.StudentNum();
studentTableView->setRowCount(RowCnt);
QStandardItem *aTempItem;
QString tempstr;
for(int i=0;i<RowCnt;++i)
{
Student temp_s=m_students.GetStudent(i);
tempstr=temp_s.s_ID;
aTempItem=new QStandardItem(tempstr);
studentTableView->setItem(i,0,aTempItem);
tempstr=temp_s.s_Name;
aTempItem=new QStandardItem(tempstr);
studentTableView->setItem(i,1,aTempItem);
tempstr=temp_s.s_class;
aTempItem=new QStandardItem(tempstr);
studentTableView->setItem(i,2,aTempItem);
tempstr=temp_s.ph_number;
aTempItem=new QStandardItem(tempstr);
studentTableView->setItem(i,3,aTempItem);
tempstr=temp_s.birthday.toString("yyyy/MM/dd");
aTempItem=new QStandardItem(tempstr);
studentTableView->setItem(i,4,aTempItem);
tempstr=temp_s.adress;
aTempItem=new QStandardItem(tempstr);
studentTableView->setItem(i,5,aTempItem);
if(temp_s.is_courses())tempstr="否";
else tempstr="是";
aTempItem=new QStandardItem(tempstr);
studentTableView->setItem(i,6,aTempItem);
}
Show_Label1(QString("学生人数:%1人").arg(m_students.StudentNum()));
}
- 不管是选课信息的显示还是查询信息的显示都与上面的相似。
得到鼠标选中的信息索引
- 因为我们要对特定的学生或者特定的课程进行相关操作,所以我们在不同视图下要得到我们鼠标选中的索引,代码如下:
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
if(m_View_kind==0)
{
m_row=index.row();
Show_Label2(QString("已选中学号为%1 姓名为%2的学生").arg(m_students.GetStudent(m_row).s_ID).arg(m_students.GetStudent(m_row).s_Name));
}
else if(m_View_kind==1)
{
m_row1=index.row();
Show_Label2(QString("已选中课程编号为%1 名称为%2的课程信息").arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_ID).arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_Name));
}
else if(m_View_kind==2)
{
if(indexlist.isEmpty())m_row=-1;
else
{
m_row=indexlist[index.row()];
Show_Label2(QString("已选中学号为%1 姓名为%2的学生").arg(m_students.GetStudent(m_row).s_ID).arg(m_students.GetStudent(m_row).s_Name));
}
}
else if(m_View_kind==3)
{
if(indexlist1.isEmpty())m_row1=-1;
else
{
m_row1=indexlist1[index.row()];
Show_Label2(QString("已选中课程编号为%1 名称为%2的课程信息").arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_ID).arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_Name));
}
}
}
- 既然得到了特定索引就可以实现对特定学生或对特定课程的操作,这里就不再赘述和贴代码啦。
信息查询
void MainWindow::on_actionSelect_triggered()
{
Show_Label2("正在进行查询。。。");
indexlist.clear();
indexlist1.clear();
if(m_View_kind==0 || m_View_kind==2)
{
SelectDialog sg1;
sg1.setWindowTitle("学生信息查询");
int ret=sg1.exec();
if(ret==QDialog::Accepted)
{
int index=sg1.Get_Comboboxindex();
QString tempstr=sg1.Get_Value();
for(int i=0;i<m_students.StudentNum();i++)
{
if(index==0)
{
if(m_students.GetStudent(i).s_ID==tempstr)
indexlist.append(i);
}
if(index==1)
{
if(m_students.GetStudent(i).s_Name==tempstr)
indexlist.append(i);
}
if(index==2)
{
if(m_students.GetStudent(i).s_class==tempstr)
indexlist.append(i);
}
}
if(indexlist.isEmpty())
Show_Label2(QString("未找到%1为%2的学生信息").arg(sg1.Get_Comboboxtext()).arg(tempstr));
else Show_Label2(QString("成功找到%1为%2的学生信息!").arg(sg1.Get_Comboboxtext()).arg(tempstr));
Show_SelectTable();
}
else Show_Label2("查询操作已取消!");
}
else if(m_View_kind==1 || m_View_kind==3)
{
SelectDialog1 sg1;
sg1.setWindowTitle("课程信息查询");
int ret=sg1.exec();
if(ret==QDialog::Accepted)
{
int index=sg1.Get_Comboboxindex();
QString tempstr=sg1.Get_Value();
for(int i=0;i<m_students.GetStudent(m_row).s_courses.CourseNum();i++)
{
Course temp_c=m_students.GetStudent(m_row).s_courses.GetCourse(i);
if(index==0)
{
if(temp_c.c_ID==tempstr)
indexlist1.append(i);
}
if(index==1)
{
if(temp_c.c_Name==tempstr)
indexlist1.append(i);
}
}
if(indexlist1.isEmpty())
Show_Label2(QString("未找到%1为%2的课程信息").arg(sg1.Get_Comboboxtext()).arg(tempstr));
else Show_Label2(QString("成功找到%1为%2的课程信息!").arg(sg1.Get_Comboboxtext()).arg(tempstr));
Show_SelectTable();
}
else Show_Label2("查询操作已取消!");
}
else
{
TipsDialog tig;
tig.Tips_Show("请在学生信息视图或课程信息视图下进行此操作!!!");
tig.exec();
Show_Label2("查询失败!");
}
}
在表格视图中直接对信息进行修改(原数据也进行改变)
- 在构造函数中我们已经链接了一个信号槽函数
connect(ui->tableView->itemDelegate(),&QAbstractItemDelegate::closeEditor,this,&MainWindow::on_ShowInfotableView_changed); //信号与槽进行连接(后续可在tabelView中直接修改) - 而其中的槽函数
MainWindow::on_ShowInfotableView_changed() 代码如下:
void MainWindow::on_ShowInfotableView_changed()
{
QModelIndex index = ui->tableView->currentIndex();
int col=index.column();
Student & temp_ss=m_students.GetStudent(m_row);
QVariant data;
switch(m_View_kind)
{
case 0:
{
data=studentTableView->data(index);
switch(col)
{
case 0:
temp_ss.s_ID=data.toString();
break;
case 1:
temp_ss.s_Name=data.toString();
break;
case 2:
temp_ss.s_class=data.toString();
break;
case 3:
temp_ss.ph_number=data.toString();
break;
case 4:
temp_ss.birthday=data.toDate();
break;
case 5:
temp_ss.adress=data.toString();
break;
default:
break;
}
Show_Table_s_changed();
Show_Label2("修改已保存!");
break;
}
case 1:
{
Course & temp_c=temp_ss.s_courses.GetCourse(m_row1);
data=studentTableView->data(index);
switch(col)
{
case 0:
temp_c.c_ID=data.toString();
break;
case 1:
temp_c.c_Name=data.toString();
break;
case 2:
temp_c.credit=data.toFloat();
break;
case 3:
temp_c.term=data.toString();
break;
case 4:
temp_c.c_room=data.toString();
break;
case 5:
temp_c.grade=data.toFloat();
break;
default:
break;
}
Show_Table_c_changed();
Show_Label2("修改已保存!");
break;
}
case 2:
{
data=studentTableView->data(index);
switch(col)
{
case 0:
temp_ss.s_ID=data.toString();
break;
case 1:
temp_ss.s_Name=data.toString();
break;
case 2:
temp_ss.s_class=data.toString();
break;
case 3:
temp_ss.ph_number=data.toString();
break;
case 4:
temp_ss.birthday=data.toDate();
break;
case 5:
temp_ss.adress=data.toString();
break;
default:
break;
}
Show_Table_sc_changed();
Show_Label2("修改已保存!");
break;
}
case 3:
{
Course & temp_c=temp_ss.s_courses.GetCourse(m_row1);
data=studentTableView->data(index);
switch(col)
{
case 0:
temp_c.c_ID=data.toString();
break;
case 1:
temp_c.c_Name=data.toString();
break;
case 2:
temp_c.credit=data.toFloat();
break;
case 3:
temp_c.term=data.toString();
break;
case 4:
temp_c.c_room=data.toString();
break;
case 5:
temp_c.grade=data.toFloat();
break;
default:
break;
}
Show_Table_sc_changed();
Show_Label2("修改已保存!");
break;
}
}
}
- 到这里,我们的项目就已经完成的差不多了,我们可以再添加亿点点细节让整个系统更加完备。
功能演示
功能介绍
- 添加/删除学生信息:
在学生信息视图下操作,删除学生时要选中一个学生才能进行; - 指定学生添加/删除课程信息:
添加操作要在学生信息视图下选定一个学生进行添加,删除操作要在选课信息视图下选定一个课程才能进行; - 可查询学生/课程信息,并且在查询后可直接进行修改或删除操作:
在学生信息视图或课程信息视图下进行; - 保存/读取文件:
可直接读取数据库中的文件并保存,也可打开其他文件并另存为; - 可查看指定课程的学生信息,并可以进行成绩排序:
在特定课程学生信息视图下进行操作; - 在选择修改时才可进行修改,保护数据:
点击“修改”选项后方可对数据进行修改,正常情况下不可修改;
操作演示
部分操作图片:
资源获取
- 主窗口cpp文件(mainwindow.cpp):点这里
- 完整项目工程资源:点这里
|