面向对象设计大作业2:在AI的帮助下编写一个Swing GUI程序
本文介绍了一个基于Java Swing的学生管理系统GUI实现。系统采用MVC架构模式,将业务逻辑封装在StudentService中,提供三种数据存储方式(List、文本文件、Excel)。主要功能包括: 主界面使用JTable展示学生数据,支持三种存储方式的切换 提供添加学生信息的弹窗对话框 支持删除选中学生记录 实现按姓名/专业/GPA搜索功能 系统实现了业务逻辑与界面的分离,同一套业务代码
要求
为你的商城购物车系统、学生管理系统添加GUI(图形用户界面)。也可自己选择编写一些实用的GUI小程序。
如果完成的好,答辩通过。可以有1次特别加分
请在留言提交博客链接。
要求:
1.建议数据展示使用JTable或更好的展示方式。
2.尽量使用MVC模式。或者能在报告中说明,你如何使用了MVC模式。
3.系统的业务逻辑代码应既可用于控制台界面、也可用于图形用户界面。需配验证运行界面截图。
4.提交后,需联系助教或者老师演示运行才能加分。
5.对AI生成的代码,要能看懂大部分,并能进行局部修改。
参考文章:
提示词
根据要求,我所撰写的提示词如下:

同时,把我已有的功能基本完善的学生管理系统的几个java文件上传。
需要上传的 Java 文件有:
1. 实体类文件:Student.java(包含学生的属性,如学号、姓名、专业等)。
2. 数据访问层的接口文件 StudentDAO.java 和各实现类文件 ListStudentDAO.java、TextFileStudentDAO.java、ExcelStudentDAO.java 。
3. 服务层文件 StudentService.java 。
4.控制台版本的主程序 Main.java 最好也上传,这样可利于大模型确认业务逻辑的完整性。
代码展示
MainFrame.java(主界面)
package gui;
import dao.StudentDAO;
import dao.impl.ExcelStudentDAO;
import dao.impl.ListStudentDAO;
import dao.impl.TextFileStudentDAO;
import entity.Student;
import service.StudentService;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class MainFrame extends JFrame {
private StudentService service;
private DefaultTableModel tableModel;
private JTable studentTable;
private JComboBox<String> storageTypeCombo;
// 初始化界面
public MainFrame() {
setTitle("学生信息管理系统");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // 居中显示
// 初始化数据访问层
initDAO();
// 创建界面组件
createComponents();
// 加载学生数据
refreshStudentTable();
}
// 初始化数据访问对象
private void initDAO() {
// 默认使用List存储
StudentDAO dao = new ListStudentDAO();
service = new StudentService(dao);
}
// 创建界面组件
private void createComponents() {
// 主面板使用边界布局
JPanel mainPanel = new JPanel(new BorderLayout());
// 顶部面板:存储类型选择和操作按钮
JPanel topPanel = createTopPanel();
mainPanel.add(topPanel, BorderLayout.NORTH);
// 中间面板:学生表格
JPanel centerPanel = createCenterPanel();
mainPanel.add(centerPanel, BorderLayout.CENTER);
// 底部面板:状态信息
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JLabel("状态:就绪"));
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
add(mainPanel);
}
// 创建顶部面板
private JPanel createTopPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
// 存储类型选择
panel.add(new JLabel("存储类型:"));
storageTypeCombo = new JComboBox<>(new String[]{"List存储", "文本文件存储", "Excel存储"});
storageTypeCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
changeStorageType();
}
});
panel.add(storageTypeCombo);
// 操作按钮
JButton addBtn = new JButton("添加学生");
addBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
openAddStudentDialog();
}
});
JButton deleteBtn = new JButton("删除学生");
deleteBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteSelectedStudent();
}
});
JButton searchBtn = new JButton("搜索学生");
searchBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
openSearchDialog();
}
});
panel.add(addBtn);
panel.add(deleteBtn);
panel.add(searchBtn);
return panel;
}
// 创建中间表格面板
private JPanel createCenterPanel() {
JPanel panel = new JPanel(new BorderLayout());
// 表格列名
String[] columnNames = {"学号", "姓名", "专业", "GPA", "年龄", "性别"};
tableModel = new DefaultTableModel(columnNames, 0);
studentTable = new JTable(tableModel);
// 添加滚动面板
JScrollPane scrollPane = new JScrollPane(studentTable);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
// 切换存储类型
private void changeStorageType() {
int selected = storageTypeCombo.getSelectedIndex();
StudentDAO dao = null;
switch (selected) {
case 0:
dao = new ListStudentDAO();
break;
case 1:
dao = new TextFileStudentDAO();
break;
case 2:
dao = new ExcelStudentDAO();
break;
}
if (dao != null) {
service = new StudentService(dao);
refreshStudentTable();
JOptionPane.showMessageDialog(this, "已切换到" + storageTypeCombo.getSelectedItem());
}
}
// 刷新学生表格
public void refreshStudentTable() {
// 清空表格
tableModel.setRowCount(0);
// 重新加载数据
List<Student> students = service.getStudents();
for (Student student : students) {
Object[] rowData = {
student.getId(),
student.getName(),
student.getMajor(),
student.getGpa(),
student.getAge(),
student.getGender()
};
tableModel.addRow(rowData);
}
}
// 打开添加学生对话框
private void openAddStudentDialog() {
AddStudentDialog dialog = new AddStudentDialog(this, service);
dialog.setVisible(true);
}
// 删除选中的学生
private void deleteSelectedStudent() {
int selectedRow = studentTable.getSelectedRow();
if (selectedRow == -1) {
JOptionPane.showMessageDialog(this, "请先选择要删除的学生");
return;
}
String id = (String) tableModel.getValueAt(selectedRow, 0);
int confirm = JOptionPane.showConfirmDialog(this, "确定要删除学号为" + id + "的学生吗?",
"确认删除", JOptionPane.YES_NO_OPTION);
if (confirm == JOptionPane.YES_OPTION) {
boolean success = service.removeStudent(id);
if (success) {
JOptionPane.showMessageDialog(this, "删除成功");
refreshStudentTable();
} else {
JOptionPane.showMessageDialog(this, "删除失败");
}
}
}
// 打开搜索对话框
private void openSearchDialog() {
SearchDialog dialog = new SearchDialog(this, service);
dialog.setVisible(true);
}
// 主方法,启动程序
public static void main(String[] args) {
// 在事件调度线程中运行GUI
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new MainFrame().setVisible(true);
}
});
}
}
AddStudentDialog.java(添加学生对话框)
package gui;
import entity.Student;
import service.StudentService;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddStudentDialog extends JDialog {
private StudentService service;
private MainFrame parentFrame;
// 输入字段
private JTextField idField;
private JTextField nameField;
private JTextField majorField;
private JTextField gpaField;
private JTextField ageField;
private JTextField genderField;
public AddStudentDialog(MainFrame parent, StudentService service) {
super(parent, "添加学生", true);
this.parentFrame = parent;
this.service = service;
setSize(300, 300);
setLocationRelativeTo(parent);
initComponents();
}
private void initComponents() {
JPanel panel = new JPanel(new GridLayout(7, 2, 15, 15));
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// 添加输入字段
panel.add(new JLabel("学号:"));
idField = new JTextField("请输入学号:");
panel.add(idField);
panel.add(new JLabel("姓名:"));
nameField = new JTextField("请输入姓名:");
panel.add(nameField);
panel.add(new JLabel("专业:"));
majorField = new JTextField("请输入专业:");
panel.add(majorField);
panel.add(new JLabel("GPA:"));
gpaField = new JTextField("请输入绩点:");
panel.add(gpaField);
panel.add(new JLabel("年龄:"));
ageField = new JTextField("请输入年龄:");
panel.add(ageField);
panel.add(new JLabel("性别:"));
genderField = new JTextField("请输入male或female:");
panel.add(genderField);
// 按钮
JButton confirmBtn = new JButton("确认");
confirmBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
saveStudent();
}
});
JButton cancelBtn = new JButton("取消");
cancelBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
panel.add(confirmBtn);
panel.add(cancelBtn);
add(panel);
}
// 保存学生信息
private void saveStudent() {
try {
// 获取输入值
String id = idField.getText().trim();
String name = nameField.getText().trim();
String major = majorField.getText().trim();
double gpa = Double.parseDouble(gpaField.getText().trim());
int age = Integer.parseInt(ageField.getText().trim());
String gender = genderField.getText().trim();
// 简单验证
if (id.isEmpty() || name.isEmpty() || major.isEmpty()) {
JOptionPane.showMessageDialog(this, "学号、姓名和专业不能为空");
return;
}
// 新增验证
if (id.isEmpty() || name.isEmpty() || major.isEmpty()) {
JOptionPane.showMessageDialog(this, "学号、姓名和专业不能为空");
return;
}
// 新增:性别只能是男/女
if (!"male".equals(gender) && !"female".equals(gender)) {
JOptionPane.showMessageDialog(this, "性别只能输入male或female");
return;
}
// 创建学生对象并保存
Student student = new Student(id, name, major, gpa, age, gender);
service.addStudent(student);
JOptionPane.showMessageDialog(this, "添加成功");
parentFrame.refreshStudentTable(); // 刷新主界面表格
dispose(); // 关闭对话框
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "GPA或年龄格式错误");
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "添加失败: " + e.getMessage());
}
}
}
SearchDialog.java(搜索对话框)
package gui;
import entity.Student;
import service.StudentService;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class SearchDialog extends JDialog {
private StudentService service;
private JComboBox<String> searchTypeCombo;
private JTextField searchField;
private DefaultTableModel resultTableModel;
public SearchDialog(MainFrame parent, StudentService service) {
super(parent, "搜索学生", true);
this.service = service;
setSize(600, 400);
setLocationRelativeTo(parent);
initComponents();
}
private void initComponents() {
JPanel mainPanel = new JPanel(new BorderLayout());
// 顶部搜索面板
JPanel searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
searchPanel.add(new JLabel("搜索类型:"));
searchTypeCombo = new JComboBox<>(new String[]{"按姓名", "按专业", "按GPA"});
searchPanel.add(searchTypeCombo);
searchField = new JTextField(20);
searchPanel.add(searchField);
JButton searchBtn = new JButton("搜索");
searchBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
performSearch();
}
});
searchPanel.add(searchBtn);
mainPanel.add(searchPanel, BorderLayout.NORTH);
// 中间结果表格
String[] columnNames = {"学号", "姓名", "专业", "GPA", "年龄", "性别"};
resultTableModel = new DefaultTableModel(columnNames, 0);
JTable resultTable = new JTable(resultTableModel);
JScrollPane scrollPane = new JScrollPane(resultTable);
mainPanel.add(scrollPane, BorderLayout.CENTER);
add(mainPanel);
}
// 执行搜索
private void performSearch() {
// 清空之前的结果
resultTableModel.setRowCount(0);
String searchText = searchField.getText().trim();
if (searchText.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入搜索内容");
return;
}
List<Student> results = null;
int searchType = searchTypeCombo.getSelectedIndex();
try {
switch (searchType) {
case 0: // 按姓名
results = service.searchByName(searchText);
break;
case 1: // 按专业
results = service.searchByMajor(searchText);
break;
case 2: // 按GPA
double gpa = Double.parseDouble(searchText);
results = service.searchByGpa(gpa);
break;
}
// 显示结果
if (results == null || results.isEmpty()) {
JOptionPane.showMessageDialog(this, "没有找到匹配的学生");
return;
}
for (Student student : results) {
Object[] rowData = {
student.getId(),
student.getName(),
student.getMajor(),
student.getGpa(),
student.getAge(),
student.getGender()
};
resultTableModel.addRow(rowData);
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "GPA格式错误");
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "搜索失败: " + e.getMessage());
}
}
}
代码运行结果
1、运行 MainFrame 类的 main 方法启动程序,通过下拉框切换存储方式。

2、点击 "添加学生" 按钮打开添加对话框,依次输入学生信息。

3、选择表格中的学生行,点击 "删除学生" 可删除选中学生。

删除完也是立马就更新了学生名单。

4、点击 "搜索学生" 按钮打开搜索对话框,可按姓名、专业或 GPA 搜索。
按姓名搜索:

按专业搜索:

按 GPA 搜索:

总结
1、界面设计
1)使用的 Swing 基本组件有 JFrame, JPanel, JTable 等。
2)采用边界布局 (BorderLayout) 和网格布局 (GridLayout) 组织界面。
3)界面分为主窗口、添加对话框和搜索对话框三个主要部分。
2、代码组织
1)每个界面元素都有专门的方法创建,提高可读性。
2)业务逻辑通过调用 StudentService 实现,与界面代码完全分离。
3)使用面向对象的设计,将不同功能封装到不同类中。
3、功能实现
1)保留了原有的三种存储方式(List、文本文件、Excel)。
2)实现了添加、删除、查询、显示所有学生的功能。
3)提供了友好的用户提示和错误处理。
4、业务逻辑的复用
本系统的业务逻辑封装在 StudentService 中,控制台版本和 GUI 版本共用同一套 Service/DAO 代码。(此次 GUI 程序是在我上次发布的学生管理系统的基础上实现的,只是新增了 MainFrame.java、AddStudentDialog.java、SearchDialog.java等界面相关文件,并未修改任何核心业务代码,所以系统的业务逻辑代码应既可用于控制台界面、也可用于图形用户界面,实现了代码的复用,指路:项目案例作业3(AI辅助):使用DAO模式改造学生信息管理系统)
5、MVC 模式的应用
1. Model
对应文件:Student.java、StudentService.java、StudentDAO.java以及ListStudentDAO.java、TextFileStudentDAO.java、ExcelStudentDAO.java。
核心作用:Student.java 定义学生数据结构,存储学号、姓名等核心信息,作为数据载体;DAO 层则提供存储方式,封装数据读写逻辑;StudentService.java 有封装、添加、删除、搜索学生等业务逻辑,调用 DAO 层完成数据操作,同时提供统一接口供上层调用。
2. View
对应文件:MainFrame.java、AddStudentDialog.java、SearchDialog.java。
核心作用:1)通过 JFrame、JPanel、JTable 等 Swing 组件构建可视化界面,展示 Model 提供的学生数据;2)提供按钮、输入框、下拉框等交互组件,接收用户操作;3)接收控制器通知,更新界面展示。
3. Controller
对应文件:ActionListener 事件监听器、MainFrame 中的 refreshStudentTable() 方法等。
核心作用:1)监听视图层的用户操作,接收用户输入数据;2)根据用户操作调用模型层的 StudentService 方法处理业务;3)业务处理完成后,通知视图层更新展示。
| 分层 | 核心职责 | 系统中对应的代码文件 / 模块 | 具体说明 |
|---|---|---|---|
| Model | 数据存储、业务逻辑、数据访问 |
1. 实体类:Student.java 2. 服务层:StudentService.java 3. DAO 层:StudentDAO.java + 各实现类(ListStudentDAO.java、TextFileStudentDAO.java、ExcelStudentDAO.java) |
1. Student 存储学生数据,是数据模型; 2. StudentService 处理添加 / 删除 / 搜索等业务逻辑; 3. DAO 层负责数据持久化(List / 文本 / Excel 存储),不依赖任何界面代码。 |
| View | 界面展示、接收用户操作 |
1. 主界面:MainFrame.java 2. 对话框:AddStudentDialog.java、SearchDialog.java |
1. 用 JTable、按钮、输入框等组件展示数据; 2. 仅接收用户操作(点击按钮、输入文本),不包含业务逻辑代码。 |
| Controller | 协调 Model 和 View,转发操作、更新界面 |
1. 各界面的 ActionListener 事件处理(如按钮点击监听) 2. MainFrame 中的 refreshStudentTable () 方法 |
1. 接收 View 的操作(如 “添加学生” 点击),调用 Model 的 Service 方法处理; 2. 处理完后通知 View 更新(如调用 refreshStudentTable () 刷新表格),不直接操作数据。 |
6、对 AI 代码的局部修改
1、新增验证: “学号、姓名、专业不能为空”,新增 “性别只能是male / female”。


2、优化了界面布局,将间距从(10,10)调整到(15,15)。

3、添加了输入提示。

效果如下:

意思就是我本次作业的分享~
更多推荐

所有评论(0)