update 基本UI界面 基本增删改逻辑

main
wang-qin928 3 weeks ago
parent 77dc115332
commit fa7c9d4e85

@ -20,8 +20,7 @@ SOURCES += \
mainwindow.cpp mainwindow.cpp
HEADERS += \ HEADERS += \
mainwindow.h \ mainwindow.h
student.h
# Default rules for deployment. # Default rules for deployment.

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.1, 2025-12-17T16:06:52. --> <!-- Written by QtCreator 4.11.1, 2025-12-18T17:41:46. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>
@ -59,6 +59,15 @@
<value type="QString">-fno-delayed-template-parsing</value> <value type="QString">-fno-delayed-template-parsing</value>
</valuelist> </valuelist>
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value> <value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
<valuemap type="QVariantMap" key="ClangTools">
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.TidyAndClazy</value>
<value type="int" key="ClangTools.ParallelJobs">16</value>
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
</valuemap>
</valuemap> </valuemap>
</data> </data>
<data> <data>
@ -71,7 +80,7 @@
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value> <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/wq/Desktop/build-StudentManager-Desktop_Qt_5_14_2_MinGW_32_bit-Debug</value> <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/UGit/build-StudentManager-Desktop_Qt_5_14_2_MinGW_32_bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
@ -300,7 +309,7 @@
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value> <value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">C:/Users/wq/Desktop/build-StudentManager-Desktop_Qt_5_14_2_MinGW_32_bit-Debug</value> <value type="QString" key="RunConfiguration.WorkingDirectory.default">D:/UGit/build-StudentManager-Desktop_Qt_5_14_2_MinGW_32_bit-Debug</value>
</valuemap> </valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value> <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap> </valuemap>
@ -531,19 +540,19 @@
</valuelist> </valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value> <value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable"></value> <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/UGit/StudentManager/StudentManager.pro</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value> <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">D:/UGit/StudentManager/StudentManager.pro</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
<value type="QString" key="RunConfiguration.Arguments"></value> <value type="QString" key="RunConfiguration.Arguments"></value>
<value type="bool" key="RunConfiguration.Arguments.multi">false</value> <value type="bool" key="RunConfiguration.Arguments.multi">false</value>
<value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value> <value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value> <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value> <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value> <value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default"></value> <value type="QString" key="RunConfiguration.WorkingDirectory.default">C:/Users/wq/Desktop/build-StudentManager-Desktop_Qt_5_14_2_MinGW_64_bit-Debug</value>
</valuemap> </valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value> <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap> </valuemap>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -5,6 +5,7 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication a(argc, argv); QApplication a(argc, argv);
a.setWindowIcon(QIcon("D:/UGit/StudentManager/favicon.ico")); // 设置全局icon文件
MainWindow w; MainWindow w;
w.show(); w.show();
return a.exec(); return a.exec();

@ -1,123 +1,289 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QInputDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QHeaderView>
#include <QLabel>
#include <QMenu>
#include <QDebug> #include <QDebug>
#include <QMenuBar>
//#include <QFile>
//#include <QTextStream>
//#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
{
setupUI();
}
MainWindow::~MainWindow() {}
void MainWindow::setupUI()
{ {
QWidget *central = new QWidget(this); QWidget *central = new QWidget(this);
setCentralWidget(central); setCentralWidget(central);
// 表格 // 顶部菜单栏
tableView = new QTableView(this); QMenuBar *menuBar = this->menuBar();
model = new QStandardItemModel(this);
model->setHorizontalHeaderLabels({"学号", "姓名", "成绩"});
tableView->setModel(model);
// 输入框 fileMenu = menuBar->addMenu("文件(&F)"); // 快捷键 alt + F
idEdit = new QLineEdit(); editMenu = menuBar->addMenu("编辑(&E)"); // 快捷键 alt + E
idEdit->setPlaceholderText("学号"); // 占位符 && 水印文字 // TODO
nameEdit = new QLineEdit();
nameEdit->setPlaceholderText("姓名");
scoreEdit = new QLineEdit();
scoreEdit->setPlaceholderText("成绩");
// 按钮 // 左侧班级树控件
addButton = new QPushButton("添加"); tree = new QTreeWidget;
deleteButton = new QPushButton("删除"); 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("删除学生");
// 布局 // 布局
// Edit水平布局 QVBoxLayout *rightLayout = new QVBoxLayout; // 垂直布局
QHBoxLayout *formLayout_Edit = new QHBoxLayout(); rightLayout->addWidget(new QLabel("姓名")); // index 0
formLayout_Edit->addWidget(idEdit); rightLayout->addWidget(nameEdit); // index 1
formLayout_Edit->addWidget(nameEdit); rightLayout->addWidget(new QLabel("性别"));
formLayout_Edit->addWidget(scoreEdit); // 使各个Edit之间水平分布 rightLayout->addWidget(genderEdit);
rightLayout->addWidget(new QLabel("年龄"));
// Button水平布局 rightLayout->addWidget(ageEdit);
QHBoxLayout *formLayout_button = new QHBoxLayout(); rightLayout->addWidget(new QLabel("学号"));
formLayout_button->addWidget(addButton); rightLayout->addWidget(idEdit);
formLayout_button->addWidget(deleteButton); rightLayout->addWidget(new QLabel("电话"));
rightLayout->addWidget(phoneEdit);
// 垂直布局 rightLayout->addWidget(addBtn);
QVBoxLayout *mainLayout = new QVBoxLayout(); rightLayout->addWidget(delBtn);
mainLayout->addWidget(tableView); // index 0垂直布局中第0个元素表格 rightLayout->addStretch(); // 设置可伸缩对齐
mainLayout->addLayout(formLayout_Edit); // index 1垂直布局中第1个元素水平排列的输入框/按钮)
mainLayout->addLayout(formLayout_button); // index 2垂直布局中第2个元素 (按钮) QHBoxLayout *mainLayout = new QHBoxLayout(central); // 水平布局
mainLayout->addWidget(tree, 1); // index 1
// 控制大小 mainLayout->addWidget(table, 3); // index 3
mainLayout->setStretch(0, 1); // 表格撑满 mainLayout->addLayout(rightLayout, 2); // index 2
mainLayout->setStretch(1, 0); // 输入区最小
mainLayout->setContentsMargins(10, 10, 10, 10); // 让每一个控件都与边缘保持10个像素的距离 // 指定信号 槽
// 右键点击弹出增删改班级窗口
central->setLayout(mainLayout); connect(tree, &QTreeWidget::customContextMenuRequested, // 右键点击信号
this, &MainWindow::showTreeMenu);
tableView->setSizePolicy( // 左键点击班级名 刷新中间的学生信息
QSizePolicy::Expanding, connect(tree, &QTreeWidget::itemClicked, // 左键点击信号
QSizePolicy::Expanding); this, &MainWindow::onClassClicked);
// 左键点击执行添加学生逻辑
// 信号槽 connect(addBtn, &QPushButton::clicked,
connect(addButton, &QPushButton::clicked, this, &MainWindow::on_addButton_clicked); this, &MainWindow::addStudent);
connect(deleteButton, &QPushButton::clicked, this, &MainWindow::on_deleteButton_clicked); // 左键点击执行删除学生逻辑
connect(delBtn, &QPushButton::clicked,
this, &MainWindow::deleteStudent);
// 点击学生单元格 回显学生信息
connect(table, &QTableWidget::cellClicked, // 单元格点击信号
this, &MainWindow::tableItemClicked);
// 确认窗口大小 // 确认窗口大小
resize(900, 600); resize(900, 600);
setMinimumSize(800, 500); setMinimumSize(800, 500);
} }
// 这个析构还必须得有 void MainWindow::showTreeMenu(const QPoint &pos)
MainWindow::~MainWindow()
{ {
// 右键点击 后触发这个函数
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::on_addButton_clicked() void MainWindow::addClass()
{ {
// 添加学生信息的逻辑 // 弹出对话框 输入班级名称
Student stu; QString name = QInputDialog::getText(this, "新建班级", "班级名称");
stu.id = idEdit->text(); if (name.isEmpty())
stu.name = nameEdit->text(); return;
stu.score = scoreEdit->text().toDouble(); // 检查班级是否已存在
// qDebug() << "id : " << stu.id if (classData.contains(name))
// << "name : " << stu.name
// << "score : " << stu.score;
// 判空F
if (stu.id.isEmpty() || stu.name.isEmpty())
{ {
QMessageBox::warning(this, "错误", "学号和姓名不能为空!"); QMessageBox::warning(this, "错误", "班级已存在,请重新输入");
return; return;
} }
students.push_back(stu); // 将新班级添加到数据结构和树控件中
// 由于是新班级,初始化为空列表
classData[name] = {};
// 在树控件中添加新节点
// 数据与UI同步更新
tree->addTopLevelItem(new QTreeWidgetItem({name}));
}
// 刷新表格 void MainWindow::deleteClass()
refreshTable(); {
// 获取当前选中班级 // 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()
idEdit->clear(); {
nameEdit->clear(); // 获取当前选中班级
scoreEdit->clear(); 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::on_deleteButton_clicked() 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()
{ {
int row = tableView->currentIndex().row(); QString cls = currentClass();
if (row < 0) 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; return;
}
s.age = age; // 只有年龄有效,才赋值给结构体
students.remove(row); // 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(); refreshTable();
// 刷新输入框内容
nameEdit->clear();
genderEdit->clear();
ageEdit->clear();
idEdit->clear();
phoneEdit->clear();
} }
void MainWindow::refreshTable() void MainWindow::deleteStudent()
{ {
model->removeRows(0, model->rowCount()); QString cls = currentClass(); // 拿到班级名称
int row = table->currentRow(); // 获取当前选中行
if (cls.isEmpty() || row < 0)
return;
for (const Student &stu : students) if (QMessageBox::question(this, "确认", "删除该学生?") == QMessageBox::Yes)
{ {
QList<QStandardItem *> row; classData[cls].removeAt(row);
row << new QStandardItem(stu.id) refreshTable();
<< new QStandardItem(stu.name)
<< new QStandardItem(QString::number(stu.score));
model->appendRow(row);
} }
} }
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);
}

@ -2,21 +2,21 @@
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow> #include <QMainWindow>
#include <QVector> #include <QTreeWidget>
#include <QStandardItemModel> #include <QTableWidget>
#include <QTableView>
#include <QLineEdit> #include <QLineEdit>
#include <QPushButton> #include <QPushButton>
#include <QVBoxLayout> #include <QMap>
#include <QHBoxLayout> #include <QList>
#include "student.h"
QT_BEGIN_NAMESPACE struct Student
namespace Ui
{ {
class MainWindow; QString name;
} QString gender;
QT_END_NAMESPACE int age;
QString id;
QString phone;
};
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
@ -25,23 +25,51 @@ class MainWindow : public QMainWindow
public: public:
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
~MainWindow(); ~MainWindow();
private slots: private slots:
void on_addButton_clicked(); // 班级管理
void on_deleteButton_clicked(); void showTreeMenu(const QPoint &pos);
void addClass();
void deleteClass();
void renameClass();
void onClassClicked(QTreeWidgetItem *item);
// 学生管理
void addStudent();
void deleteStudent();
// void updateStudent();
// void searchStudent();
void tableItemClicked(int row, int column);
// 文件操作 与 分页
// void importData();
// void saveData();
// void refreshAll();
// void prevPage();
// void nextPage();
private: private:
QVector<Student> students; // 学生信息列表 void setupUI();
QStandardItemModel *model; // 数据模型 void refreshTable();
// void saveClassToFile(const QString &className);
QString currentClass() const;
// 纯代码声明控件 private:
QTableView *tableView; // 顶部菜单栏
QLineEdit *idEdit; QMenu *fileMenu;
QLineEdit *nameEdit; QMenu *editMenu;
QLineEdit *scoreEdit; // 左侧班级树控件
QTreeWidget *tree;
// 中间学生表格控件
QTableWidget *table;
QPushButton *addButton; QLineEdit *nameEdit;
QPushButton *deleteButton; QLineEdit *genderEdit;
QLineEdit *ageEdit;
QLineEdit *idEdit;
QLineEdit *phoneEdit;
void refreshTable(); // 刷新表格显示 QPushButton *addBtn;
QPushButton *delBtn;
// 班级数据存储
QMap<QString, QList<Student>> classData;
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

@ -1,14 +0,0 @@
#ifndef STUDENT_H
#define STUDENT_H
#include <QString>
class Student
{
public:
QString id; // 学号
QString name; // 姓名
double score; // 成绩
};
#endif // STUDENT_H
Loading…
Cancel
Save