You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

290 lines
9.0 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "mainwindow.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QInputDialog>
#include <QMessageBox>
#include <QHeaderView>
#include <QLabel>
#include <QMenu>
#include <QDebug>
#include <QMenuBar>
//#include <QFile>
//#include <QTextStream>
//#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupUI();
}
MainWindow::~MainWindow() {}
void MainWindow::setupUI()
{
QWidget *central = new QWidget(this);
setCentralWidget(central);
// 顶部菜单栏
QMenuBar *menuBar = this->menuBar();
fileMenu = menuBar->addMenu("文件(&F)"); // 快捷键 alt + F
editMenu = menuBar->addMenu("编辑(&E)"); // 快捷键 alt + E
// TODO
// 左侧班级树控件
tree = new QTreeWidget;
tree->setHeaderLabel("班级列表");
tree->setContextMenuPolicy(Qt::CustomContextMenu);
// 显示学生信息控件
table = new QTableWidget;
table->setColumnCount(5);
table->setHorizontalHeaderLabels({"姓名", "性别", "年龄", "学号", "电话"});
table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// 输入学生信息控件
nameEdit = new QLineEdit;
genderEdit = new QLineEdit;
ageEdit = new QLineEdit;
idEdit = new QLineEdit;
phoneEdit = new QLineEdit;
addBtn = new QPushButton("新增学生");
delBtn = new QPushButton("删除学生");
// 布局
QVBoxLayout *rightLayout = new QVBoxLayout; // 垂直布局
rightLayout->addWidget(new QLabel("姓名")); // index 0
rightLayout->addWidget(nameEdit); // index 1
rightLayout->addWidget(new QLabel("性别"));
rightLayout->addWidget(genderEdit);
rightLayout->addWidget(new QLabel("年龄"));
rightLayout->addWidget(ageEdit);
rightLayout->addWidget(new QLabel("学号"));
rightLayout->addWidget(idEdit);
rightLayout->addWidget(new QLabel("电话"));
rightLayout->addWidget(phoneEdit);
rightLayout->addWidget(addBtn);
rightLayout->addWidget(delBtn);
rightLayout->addStretch(); // 设置可伸缩对齐
QHBoxLayout *mainLayout = new QHBoxLayout(central); // 水平布局
mainLayout->addWidget(tree, 1); // index 1
mainLayout->addWidget(table, 3); // index 3
mainLayout->addLayout(rightLayout, 2); // index 2
// 指定信号 槽
// 右键点击弹出增删改班级窗口
connect(tree, &QTreeWidget::customContextMenuRequested, // 右键点击信号
this, &MainWindow::showTreeMenu);
// 左键点击班级名 刷新中间的学生信息
connect(tree, &QTreeWidget::itemClicked, // 左键点击信号
this, &MainWindow::onClassClicked);
// 左键点击执行添加学生逻辑
connect(addBtn, &QPushButton::clicked,
this, &MainWindow::addStudent);
// 左键点击执行删除学生逻辑
connect(delBtn, &QPushButton::clicked,
this, &MainWindow::deleteStudent);
// 点击学生单元格 回显学生信息
connect(table, &QTableWidget::cellClicked, // 单元格点击信号
this, &MainWindow::tableItemClicked);
// 确认窗口大小
resize(900, 600);
setMinimumSize(800, 500);
}
void MainWindow::showTreeMenu(const QPoint &pos)
{
// 右键点击 后触发这个函数
QMenu menu;
QAction *add = menu.addAction("新建班级");
QAction *del = menu.addAction("删除班级");
QAction *ren = menu.addAction("重命名班级");
// 显示右键菜单 并获取用户选择
QAction *ret = menu.exec(tree->viewport()->mapToGlobal(pos));
// 执行用户选择的操作
if (ret == add)
addClass();
else if (ret == del)
deleteClass();
else if (ret == ren)
renameClass();
}
void MainWindow::addClass()
{
// 弹出对话框 输入班级名称
QString name = QInputDialog::getText(this, "新建班级", "班级名称");
if (name.isEmpty())
return;
// 检查班级是否已存在
if (classData.contains(name))
{
QMessageBox::warning(this, "错误", "班级已存在,请重新输入");
return;
}
// 将新班级添加到数据结构和树控件中
// 由于是新班级,初始化为空列表
classData[name] = {};
// 在树控件中添加新节点
// 数据与UI同步更新
tree->addTopLevelItem(new QTreeWidgetItem({name}));
}
void MainWindow::deleteClass()
{
// 获取当前选中班级 // auto == QTreeWidgetItem*
auto item = tree->currentItem();
if (!item)
return;
QString name = item->text(0); // 获取选中项的班级名称
// 弹出确认对话框
if (QMessageBox::question(this, "确认", "确定删除班级?") == QMessageBox::Yes)
{
// 从数据结构和树控件中删除班级
classData.remove(name);
// 数据与UI同步更新
delete item; // 避免内存泄漏
table->clearContents(); // 清理学生信息内容
table->setRowCount(0); // 清空表格行数
}
QMessageBox::information(this, "提示", "班级已删除");
}
void MainWindow::renameClass()
{
// 获取当前选中班级
auto item = tree->currentItem();
if (!item)
return;
// 获取旧班级名称
QString oldName = item->text(0);
// 弹出对话框 输入新名称
QString newName = QInputDialog::getText(this, "重命名", "新名称");
// 检查新名称有效性
if (newName.isEmpty())
return;
if (classData.contains(newName))
QMessageBox::warning(this, "提示", "班级已存在");
// 更新数据结构和树控件
classData[newName] = classData.take(oldName); // 从数据结构中移除旧键值对,并返回旧名称关联的值,赋给新名称
item->setText(0, newName);
}
void MainWindow::onClassClicked(QTreeWidgetItem *item)
{
// 用户点击班级节点后触发此函数
Q_UNUSED(item) // 避免未使用参数警告
refreshTable(); // 刷新右侧学生表格内容
}
QString MainWindow::currentClass() const // 只读成员函数
{
// 获取当前选中班级名称 auto == QTreeWidgetItem*
auto item = tree->currentItem();
return item ? item->text(0) : "";
}
void MainWindow::refreshTable()
{
QString cls = currentClass();
table->setRowCount(0); // 先清空表格内容
if (!classData.contains(cls))
return; // 班级不存在
auto &list = classData[cls]; // 获取当前班级的学生列表引用
table->setRowCount(list.size()); // 设置表格行数为学生数量
for (int i = 0; i < list.size(); ++i)
{
// 遍历学生列表 填充表格内容
table->setItem(i, 0, new QTableWidgetItem(list[i].name));
table->setItem(i, 1, new QTableWidgetItem(list[i].gender));
table->setItem(i, 2, new QTableWidgetItem(QString::number(list[i].age)));
table->setItem(i, 3, new QTableWidgetItem(list[i].id));
table->setItem(i, 4, new QTableWidgetItem(list[i].phone));
}
}
void MainWindow::addStudent()
{
QString cls = currentClass();
if (cls.isEmpty())
return;
Student s;
s.name = nameEdit->text();
s.gender = genderEdit->text();
s.id = idEdit->text();
s.phone = phoneEdit->text();
// 处理年龄用toInt的第二个参数判断是否为有效数字
bool isAgeValid; // 检测是否转换成功
int age = ageEdit->text().toInt(&isAgeValid);
if (!isAgeValid || age <= 0 || age > 120) // 年龄有效条件:转换成功 + 年龄在合理范围
{
QMessageBox::warning(this, "错误", "年龄必须是1-120的整数");
return;
}
s.age = age; // 只有年龄有效,才赋值给结构体
// qDebug() << s.name << s.id << s.age << s.phone << s.gender;
if (s.name.isEmpty() || s.gender.isEmpty() || s.id.isEmpty() || s.phone.isEmpty())
{
QMessageBox::warning(this, "错误", "信息不完整(姓名、性别、学号、电话不能为空)");
return;
}
for (auto &st : classData[cls])
{
if (st.id == s.id)
{
QMessageBox::warning(this, "错误", "学号重复");
return;
}
}
classData[cls].append(s); // 将新学生追加到当前班级的学生列表
refreshTable();
// 刷新输入框内容
nameEdit->clear();
genderEdit->clear();
ageEdit->clear();
idEdit->clear();
phoneEdit->clear();
}
void MainWindow::deleteStudent()
{
QString cls = currentClass(); // 拿到班级名称
int row = table->currentRow(); // 获取当前选中行
if (cls.isEmpty() || row < 0)
return;
if (QMessageBox::question(this, "确认", "删除该学生?") == QMessageBox::Yes)
{
classData[cls].removeAt(row);
refreshTable();
}
}
void MainWindow::tableItemClicked(int row, int) // 点击学生信息进行回显
{
QString cls = currentClass();
if (cls.isEmpty())
return;
auto s = classData[cls][row];
nameEdit->setText(s.name);
genderEdit->setText(s.gender);
ageEdit->setText(QString::number(s.age));
idEdit->setText(s.id);
phoneEdit->setText(s.phone);
}