直观的 QT 图形界面:采用 QT 构建的用户友好界面,提供清晰的菜单选项,确保用户轻松导航和访问各项功能。 数据库驱动的数据存储:系统使用数据库技术安全高效地存储学生信息,保障数据的完整性和可靠性。 全面的基本功能:包括添加、删除、修改和查询学生数据,支持模糊查找,便捷地获取所需信息。 高级统计功能:系统具备先进的数据统计功能,提供图形化展示,使成绩分析直观易懂,支持对学生表现的全面分析。 数据的批量导入和导出:提供批量导入学生信息的能力,方便从其他系统迁移数据;同时支持将数据以 CSV 格式导出,便于备份或在其他应用中使用。 内置帮助文档:配备完善的帮助文档,用户可通过按 F1 快捷键获取即时帮助,轻松了解系统的使用方法和功能细节。

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include

#include

#include

#include

#include

#include

#include

#include

#include "studentmanager.h"

#include "student.h"

using namespace QtCharts;

class MainWindow : public QMainWindow {

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = nullptr);

private:

QPushButton *addButton;

QPushButton *deleteButton;

QPushButton *updateButton;

QLineEdit *nameEdit;

QDoubleSpinBox *scoreSpin;

QTableWidget *studentTable;

QPushButton *searchButton;

QRadioButton *sortAscButton;

QRadioButton *sortDescButton;

QLineEdit *searchEdit;

QLabel *analysisLabel;

QChartView *chartView;

QPushButton *exportButton;

QPushButton *importButton;

StudentManager studentManager;

void setupUi();

void connectSignalsSlots();

void refreshStudentTable();

void refreshStudentTable(const QList& students);

void updateChart();

QChart* createChart();

int getNextStudentId();

void updateAnalysis(const QList& students);

void importData();

void exportData();

private slots:

void addStudent();

void deleteStudent();

void updateStudent();

void searchStudents();

void sortStudents();

void onExportButtonClicked();

void onImportButtonClicked();

};

#endif // MAINWINDOW_H

/**

* @brief 学生成绩管理系统 20240408

* @author VX:Cgsjed

*/

#include "mainwindow.h"

#include

#include

#include

#include

#include

#include

# define tc(a) QString::fromLocal8Bit(a)

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {

setupUi();

connectSignalsSlots();

refreshStudentTable();

}

void MainWindow::setupUi() {

QWidget *centralWidget = new QWidget(this);

QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);

QHBoxLayout *inputLayout = new QHBoxLayout();

nameEdit = new QLineEdit();

scoreSpin = new QDoubleSpinBox();

addButton = new QPushButton(tc("添加"));

deleteButton = new QPushButton(tc("删除"));

updateButton = new QPushButton(tc("刷新"));

inputLayout->addWidget(new QLabel(tc("姓名")));

inputLayout->addWidget(nameEdit);

inputLayout->addWidget(new QLabel(tc("分数")));

inputLayout->addWidget(scoreSpin);

inputLayout->addWidget(addButton);

inputLayout->addWidget(deleteButton);

inputLayout->addWidget(updateButton);

studentTable = new QTableWidget();

studentTable->setColumnCount(3); // ID, Name, Score

studentTable->setFixedWidth(300);

QStringList headers = {tc("编号"), tc("姓名"), tc("分数")};

studentTable->setHorizontalHeaderLabels(headers);

studentTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

studentTable->setSortingEnabled(true);

QHBoxLayout *searchLayout = new QHBoxLayout();

searchButton = new QPushButton(tc("查询"));

searchEdit = new QLineEdit();

sortAscButton = new QRadioButton(tc("分数正序"));

sortDescButton = new QRadioButton(tc("分数倒序"));

sortAscButton->setChecked(true);

exportButton = new QPushButton(tc("数据导出"), this);

importButton = new QPushButton(tc("导入数据"), this);

searchLayout->addWidget(exportButton);

searchLayout->addWidget(importButton);

searchLayout->addWidget(new QLabel(tc("输出查询的姓名")));

searchLayout->addWidget(searchEdit);

searchLayout->addWidget(searchButton);

searchLayout->addWidget(sortAscButton);

searchLayout->addWidget(sortDescButton);

chartView = new QChartView(createChart());

mainLayout->addLayout(inputLayout);

mainLayout->addLayout(searchLayout);

QHBoxLayout *searchLayout1 = new QHBoxLayout();

searchLayout1->addWidget(studentTable);

searchLayout1->addWidget(chartView);

mainLayout->addLayout(searchLayout1);

setCentralWidget(centralWidget);

this->setWindowTitle(tc("学生成绩管理系统"));

}

void MainWindow::connectSignalsSlots() {

connect(addButton, &QPushButton::clicked, this, &MainWindow::addStudent);

connect(deleteButton, &QPushButton::clicked, this, &MainWindow::deleteStudent);

connect(updateButton, &QPushButton::clicked, this, &MainWindow::updateStudent);

connect(searchButton, &QPushButton::clicked, this, &MainWindow::searchStudents);

connect(sortAscButton, &QRadioButton::toggled, this, &MainWindow::sortStudents);

connect(sortDescButton, &QRadioButton::toggled, this, &MainWindow::sortStudents);

connect(exportButton, &QPushButton::clicked, this, &MainWindow::onExportButtonClicked);

connect(importButton, &QPushButton::clicked, this, &MainWindow::onImportButtonClicked);

}

void MainWindow::addStudent() {

QString name = nameEdit->text();

double score = scoreSpin->value();

if (name.isEmpty() || score < 0) {

QMessageBox::warning(this, "Input Error", "Invalid name or score.");

return;

}

Student student(getNextStudentId(), name, score);

studentManager.addStudent(student);

refreshStudentTable();

updateChart();

}

void MainWindow::deleteStudent() {

int row = studentTable->currentRow();

if (row == -1) {

QMessageBox::warning(this, "Selection Error", "Please select a student to delete.");

return;

}

int id = studentTable->item(row, 0)->text().toInt();

studentManager.deleteStudent(id);

refreshStudentTable();

updateChart();

}

void MainWindow::updateStudent()

{

refreshStudentTable();

}

void MainWindow::searchStudents() {

QString name = searchEdit->text();

auto students = studentManager.findStudentsByName(name);

refreshStudentTable(students);

updateChart();

}

void MainWindow::sortStudents() {

bool isAscending = sortAscButton->isChecked();

studentTable->sortItems(2, isAscending ? Qt::AscendingOrder : Qt::DescendingOrder);

}

void MainWindow::onExportButtonClicked()

{

// 实现导出数据到文件的逻辑

exportData();

}

void MainWindow::onImportButtonClicked()

{

// 实现从文件导入数据的逻辑

importData();

}

void MainWindow::refreshStudentTable() {

auto students = studentManager.getAllStudents();

refreshStudentTable(students);

}

void MainWindow::refreshStudentTable(const QList& students) {

studentTable->clearContents();

studentTable->setRowCount(students.count());

for (int i = 0; i < students.count(); ++i) {

auto student = students[i];

studentTable->setItem(i, 0, new QTableWidgetItem(QString::number(student.getId())));

studentTable->setItem(i, 1, new QTableWidgetItem(student.getName()));

studentTable->setItem(i, 2, new QTableWidgetItem(QString::number(student.getScore())));

}

studentTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

studentTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);

studentTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);

}

void MainWindow::updateChart() {

auto chart = createChart();

chartView->setChart(chart);

}

QChart* MainWindow::createChart() {

QBarSeries *series = new QBarSeries();

QBarSet *set = new QBarSet(tc("及格线"));

QStringList categories;

// 从学生管理器获取数据并填充到柱状图中

QList students = studentManager.getAllStudents();

for (const Student &student : students) {

*set << student.getScore(); // 将分数添加到柱状图

categories << student.getName(); // 将学生名字添加到类别中

}

series->append(set);

QChart *chart = new QChart();

chart->addSeries(series);

chart->setTitle(tc("班级成绩柱状图"));

chart->setAnimationOptions(QChart::SeriesAnimations);

QBarCategoryAxis *axisX = new QBarCategoryAxis();

axisX->append(categories); // 设置类别为学生姓名

chart->addAxis(axisX, Qt::AlignBottom);

series->attachAxis(axisX);

QValueAxis *axisY = new QValueAxis();

axisY->setRange(0, 100);

axisY->setTickInterval(10);

chart->addAxis(axisY, Qt::AlignLeft);

series->attachAxis(axisY);

// 在 60 分位置绘制一条横线作为及格线

QLineSeries *passLine = new QLineSeries();

passLine->append(QPointF(-5, 60));

passLine->append(QPointF(students.count(), 60)); // 覆盖整个 X 轴范围

QPen pen(Qt::red, 2, Qt::DashLine); // 红色虚线

passLine->setPen(pen);

chart->addSeries(passLine);

passLine->attachAxis(axisX);

passLine->attachAxis(axisY);

chart->legend()->setVisible(true);

chart->legend()->setAlignment(Qt::AlignBottom);

return chart;

}

int MainWindow::getNextStudentId() {

auto students = studentManager.getAllStudents();

int maxId = 0;

for (auto &student : students) {

if (student.getId() > maxId)

maxId = student.getId();

}

return maxId + 1;

}

void MainWindow::importData() {

QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("CSV (*.csv)"));

if (fileName.isEmpty()) {

return;

}

QFile file(fileName);

if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {

QMessageBox::warning(this, tr("Error"), tr("Unable to open file"));

return;

}

QTextStream stream(&file);

// 忽略第一行标题

if (!stream.atEnd()) {

stream.readLine();

}

QSet existingNames;

for (const auto &student : studentManager.getAllStudents()) {

existingNames.insert(student.getName());

}

int nextId = getNextStudentId();

while (!stream.atEnd()) {

QString line = stream.readLine();

QStringList strList = line.split(",");

if (strList.size() >= 3) {

QString name = strList.at(1).trimmed().replace("\"", "");

double score = strList.at(2).trimmed().replace("\"", "").toDouble();

// 仅添加不存在的新名字

if (!existingNames.contains(name)) {

Student student(nextId++, name, score);

studentManager.addStudent(student);

existingNames.insert(name);

}

}

}

file.close();

refreshStudentTable();

updateChart();

}

void MainWindow::exportData()

{

QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("CSV (*.csv)"));

if (fileName.isEmpty()) {

return;

}

QFile file(fileName);

if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {

QMessageBox::warning(this, tr("Error"), tr("Unable to open file"));

return;

}

QTextStream stream(&file);

QStringList strList;

// 写入标题

for (int c = 0; c < studentTable->horizontalHeader()->count(); ++c) {

strList << "\"" + studentTable->model()->headerData(c, Qt::Horizontal).toString() + "\"";

}

stream << strList.join(",") << "\n";

// 写入数据

for (int r = 0; r < studentTable->rowCount(); ++r) {

strList.clear();

for (int c = 0; c < studentTable->columnCount(); ++c) {

strList << "\"" + studentTable->item(r, c)->text() + "\"";

}

stream << strList.join(",") << "\n";

}

file.close();

}

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: