杰瑞科技汇

java swing 管理系统

我们将创建一个 “学生信息管理系统”,因为它足够简单,可以清晰地展示核心功能,同时又能扩展到更复杂的业务场景。

java swing 管理系统-图1
(图片来源网络,侵删)

最终效果预览


项目结构 (MVC 分层)

一个良好的项目结构是可维护和可扩展的基础,我们将项目分为三个主要部分:

StudentManagementSystem/
├── model/                 // 模型层:数据和业务逻辑
│   ├── Student.java       // 学生实体类
│   └── StudentModel.java  // 数据模型,负责数据的增删改查
│
├── view/                  // 视图层:用户界面
│   ├── MainFrame.java     // 主窗口
│   ├── StudentForm.java   // 添加/编辑学生的表单对话框
│   ├── StudentTable.java  // 显示学生列表的自定义表格
│   └── components/        // 自定义UI组件 (可选,用于美化)
│
└── controller/            // 控制器层:连接模型和视图
    └── StudentController.java // 处理用户事件,调用模型,更新视图

核心代码实现

1. Model (模型层)

Student.java - 学生实体类 这是一个简单的 POJO (Plain Old Java Object),用于存储单个学生的信息。

// model/Student.java
package model;
import java.io.Serializable;
public class Student implements Serializable {
    private int id;
    private String name;
    private String studentId;
    private String gender;
    private int age;
    public Student(int id, String name, String studentId, String gender, int age) {
        this.id = id;
        this.name = name;
        this.studentId = studentId;
        this.gender = gender;
        this.age = age;
    }
    // Getters and Setters
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getStudentId() { return studentId; }
    public void setStudentId(String studentId) { this.studentId = studentId; }
    public String getGender() { return gender; }
    public void setGender(String gender) { this.gender = gender; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", studentId='" + studentId + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                '}';
    }
}

StudentModel.java - 数据模型 这个类负责管理所有的学生数据,它不关心 UI,只提供数据操作接口。

// model/StudentModel.java
package model;
import java.util.ArrayList;
import java.util.List;
public class StudentModel {
    private final List<Student> students;
    private int nextId = 1;
    public StudentModel() {
        this.students = new ArrayList<>();
        // 初始化一些测试数据
        addStudent(new Student(nextId++, "张三", "2025001", "男", 20));
        addStudent(new Student(nextId++, "李四", "2025002", "女", 21));
        addStudent(new Student(nextId++, "王五", "2025003", "男", 19));
    }
    public void addStudent(Student student) {
        student.setId(nextId++);
        students.add(student);
    }
    public void updateStudent(Student student) {
        for (int i = 0; i < students.size(); i++) {
            if (students.get(i).getId() == student.getId()) {
                students.set(i, student);
                break;
            }
        }
    }
    public void deleteStudent(int id) {
        students.removeIf(student -> student.getId() == id);
    }
    public Student getStudentById(int id) {
        for (Student student : students) {
            if (student.getId() == id) {
                return student;
            }
        }
        return null;
    }
    public List<Student> getAllStudents() {
        return new ArrayList<>(students); // 返回副本,保证数据安全
    }
}

2. View (视图层)

MainFrame.java - 主窗口 这是应用程序的主界面,包含菜单栏、工具栏和学生列表表格。

java swing 管理系统-图2
(图片来源网络,侵删)
// view/MainFrame.java
package view;
import controller.StudentController;
import model.StudentModel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MainFrame extends JFrame {
    private StudentTable studentTable;
    private StudentController controller;
    public MainFrame(StudentModel model) {
        this.controller = new StudentController(model, this);
        initUI();
    }
    private void initUI() {
        setTitle("学生信息管理系统");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null); // 居中显示
        // 创建菜单栏
        createMenuBar();
        // 创建工具栏
        createToolBar();
        // 创建表格
        studentTable = new StudentTable(controller);
        JScrollPane scrollPane = new JScrollPane(studentTable);
        add(scrollPane, BorderLayout.CENTER);
    }
    private void createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu fileMenu = new JMenu("文件");
        JMenu editMenu = new JMenu("编辑");
        JMenuItem exitItem = new JMenuItem("退出");
        JMenuItem addItem = new JMenuItem("添加学生");
        JMenuItem editItem = new JMenuItem("编辑学生");
        JMenuItem deleteItem = new JMenuItem("删除学生");
        exitItem.addActionListener(e -> System.exit(0));
        addItem.addActionListener(e -> controller.showAddStudentDialog());
        editItem.addActionListener(e -> controller.showEditStudentDialog());
        deleteItem.addActionListener(e -> controller.deleteStudent());
        fileMenu.add(exitItem);
        editMenu.add(addItem);
        editMenu.add(editItem);
        editMenu.add(deleteItem);
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        setJMenuBar(menuBar);
    }
    private void createToolBar() {
        JToolBar toolBar = new JToolBar();
        JButton addButton = new JButton("添加");
        JButton editButton = new JButton("编辑");
        JButton deleteButton = new JButton("删除");
        addButton.addActionListener(e -> controller.showAddStudentDialog());
        editButton.addActionListener(e -> controller.showEditStudentDialog());
        deleteButton.addActionListener(e -> controller.deleteStudent());
        toolBar.add(addButton);
        toolBar.addSeparator();
        toolBar.add(editButton);
        toolBar.addSeparator();
        toolBar.add(deleteButton);
        add(toolBar, BorderLayout.NORTH);
    }
    public StudentTable getStudentTable() {
        return studentTable;
    }
}

StudentTable.java - 自定义表格 为了方便地获取选中的行数据,我们创建一个继承自 JTable 的自定义表格。

// view/StudentTable.java
package view;
import controller.StudentController;
import model.Student;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.util.List;
public class StudentTable extends JTable {
    private StudentTableModel tableModel;
    private StudentController controller;
    public StudentTable(StudentController controller) {
        this.controller = controller;
        this.tableModel = new StudentTableModel(controller.getStudentModel().getAllStudents());
        setModel(tableModel);
    }
    public void refreshData(List<Student> students) {
        tableModel.setStudents(students);
        tableModel.fireTableDataChanged(); // 通知模型数据已更改
    }
    public Student getSelectedStudent() {
        int rowIndex = getSelectedRow();
        if (rowIndex != -1) {
            return tableModel.getStudentAt(rowIndex);
        }
        return null;
    }
    // 表格模型
    private static class StudentTableModel extends AbstractTableModel {
        private final List<Student> students;
        private final String[] columnNames = {"ID", "姓名", "学号", "性别", "年龄"};
        public StudentTableModel(List<Student> students) {
            this.students = students;
        }
        public void setStudents(List<Student> students) {
            this.students.clear();
            this.students.addAll(students);
        }
        public Student getStudentAt(int rowIndex) {
            return students.get(rowIndex);
        }
        @Override
        public int getRowCount() {
            return students.size();
        }
        @Override
        public int getColumnCount() {
            return columnNames.length;
        }
        @Override
        public String getColumnName(int column) {
            return columnNames[column];
        }
        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Student student = students.get(rowIndex);
            switch (columnIndex) {
                case 0: return student.getId();
                case 1: return student.getName();
                case 2: return student.getStudentId();
                case 3: return student.getGender();
                case 4: return student.getAge();
                default: return null;
            }
        }
    }
}

StudentForm.java - 添加/编辑表单 这是一个模态对话框,用于输入或修改学生信息。

// view/StudentForm.java
package view;
import model.Student;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class StudentForm extends JDialog {
    private JTextField nameField, studentIdField, ageField;
    private JComboBox<String> genderCombo;
    private JButton saveButton, cancelButton;
    private Student studentToEdit;
    public StudentForm(Frame owner, String title, boolean modal) {
        super(owner, title, modal);
        initUI();
    }
    private void initUI() {
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        // 表单字段
        gbc.gridx = 0; gbc.gridy = 0; add(new JLabel("姓名:"), gbc);
        gbc.gridx = 1; gbc.gridy = 0; nameField = new JTextField(20); add(nameField, gbc);
        gbc.gridx = 0; gbc.gridy = 1; add(new JLabel("学号:"), gbc);
        gbc.gridx = 1; gbc.gridy = 1; studentIdField = new JTextField(20); add(studentIdField, gbc);
        gbc.gridx = 0; gbc.gridy = 2; add(new JLabel("性别:"), gbc);
        gbc.gridx = 1; gbc.gridy = 2; genderCombo = new JComboBox<>(new String[]{"男", "女"}); add(genderCombo, gbc);
        gbc.gridx = 0; gbc.gridy = 3; add(new JLabel("年龄:"), gbc);
        gbc.gridx = 1; gbc.gridy = 3; ageField = new JTextField(20); add(ageField, gbc);
        // 按钮
        gbc.gridx = 0; gbc.gridy = 4; gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        JPanel buttonPanel = new JPanel();
        saveButton = new JButton("保存");
        cancelButton = new JButton("取消");
        buttonPanel.add(saveButton);
        buttonPanel.add(cancelButton);
        add(buttonPanel, gbc);
        // 按钮事件
        saveButton.addActionListener(e -> {
            if (validateInput()) {
                saveStudent();
                dispose();
            }
        });
        cancelButton.addActionListener(e -> dispose());
        pack();
        setLocationRelativeTo(getOwner());
    }
    private boolean validateInput() {
        if (nameField.getText().trim().isEmpty() || studentIdField.getText().trim().isEmpty() || ageField.getText().trim().isEmpty()) {
            JOptionPane.showMessageDialog(this, "所有字段都必须填写!", "错误", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        try {
            Integer.parseInt(ageField.getText());
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, "年龄必须是数字!", "错误", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        return true;
    }
    private void saveStudent() {
        String name = nameField.getText();
        String studentId = studentIdField.getText();
        String gender = (String) genderCombo.getSelectedItem();
        int age = Integer.parseInt(ageField.getText());
        if (studentToEdit == null) {
            // 新增
            controller.addStudent(new Student(0, name, studentId, gender, age));
        } else {
            // 编辑
            studentToEdit.setName(name);
            studentToEdit.setStudentId(studentId);
            studentToEdit.setGender(gender);
            studentToEdit.setAge(age);
            controller.updateStudent(studentToEdit);
        }
    }
    public void setStudent(Student student) {
        this.studentToEdit = student;
        if (student != null) {
            nameField.setText(student.getName());
            studentIdField.setText(student.getStudentId());
            genderCombo.setSelectedItem(student.getGender());
            ageField.setText(String.valueOf(student.getAge()));
            setTitle("编辑学生信息");
        } else {
            clearForm();
            setTitle("添加学生信息");
        }
    }
    private void clearForm() {
        nameField.setText("");
        studentIdField.setText("");
        genderCombo.setSelectedIndex(0);
        ageField.setText("");
    }
    // 为了让表单能调用控制器,需要设置控制器
    public void setController(controller.StudentController controller) {
        this.controller = controller;
    }
    // 注意:这里需要声明 controller 变量
    private controller.StudentController controller;
}

3. Controller (控制器层)

StudentController.java - 控制器 这是整个系统的核心,它接收来自视图的用户操作,调用模型进行数据处理,然后通知视图更新。

// controller/StudentController.java
package controller;
import model.Student;
import model.StudentModel;
import view.MainFrame;
import view.StudentForm;
public class StudentController {
    private final StudentModel model;
    private final MainFrame view;
    private StudentForm studentForm;
    public StudentController(StudentModel model, MainFrame view) {
        this.model = model;
        this.view = view;
        // 初始化表单对话框
        this.studentForm = new StudentForm(view, "学生信息", true);
        this.studentForm.setController(this); // 将控制器设置给表单
    }
    public void showAddStudentDialog() {
        studentForm.setStudent(null); // 清空表单,准备新增
        studentForm.setVisible(true);
    }
    public void showEditStudentDialog() {
        Student selectedStudent = view.getStudentTable().getSelectedStudent();
        if (selectedStudent != null) {
            studentForm.setStudent(selectedStudent); // 填充表单,准备编辑
            studentForm.setVisible(true);
        } else {
            JOptionPane.showMessageDialog(view, "请先选择一个学生!", "提示", JOptionPane.INFORMATION_MESSAGE);
        }
    }
    public void deleteStudent() {
        Student selectedStudent = view.getStudentTable().getSelectedStudent();
        if (selectedStudent != null) {
            int confirm = JOptionPane.showConfirmDialog(view,
                    "确定要删除学生 " + selectedStudent.getName() + " 吗?",
                    "确认删除",
                    JOptionPane.YES_NO_OPTION);
            if (confirm == JOptionPane.YES_OPTION) {
                model.deleteStudent(selectedStudent.getId());
                refreshStudentTable();
            }
        } else {
            JOptionPane.showMessageDialog(view, "请先选择一个学生!", "提示", JOptionPane.INFORMATION_MESSAGE);
        }
    }
    public void addStudent(Student student) {
        model.addStudent(student);
        refreshStudentTable();
    }
    public void updateStudent(Student student) {
        model.updateStudent(student);
        refreshStudentTable();
    }
    private void refreshStudentTable() {
        view.getStudentTable().refreshData(model.getAllStudents());
    }
    public StudentModel getStudentModel() {
        return model;
    }
}

入口类 (App.java)

我们创建一个主类来启动应用程序。

// App.java
import controller.StudentController;
import model.StudentModel;
import view.MainFrame;
import javax.swing.*;
public class App {
    public static void main(String[] args) {
        // 设置 Swing 的外观风格,使其更现代化
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 在事件调度线程中创建和显示 GUI,这是 Swing 的标准做法
        SwingUtilities.invokeLater(() -> {
            StudentModel model = new StudentModel();
            MainFrame view = new MainFrame(model);
            StudentController controller = new StudentController(model, view);
            view.setVisible(true);
        });
    }
}

如何运行

  1. 创建项目: 在你的 IDE (如 IntelliJ IDEA, Eclipse) 中创建一个新的 Java 项目。
  2. 创建包: 按照上面的项目结构创建 model, view, controller 包。
  3. 复制代码: 将上面的 Java 代码分别复制到对应的文件中。
  4. 运行: 运行 App.java 文件。

扩展与改进建议

这个基础系统已经具备了核心功能,你可以在此基础上进行扩展:

  1. 数据持久化: 目前数据存储在内存中,程序关闭后数据会丢失。
    • 方案: 使用 Java 序列化将 StudentModel 对象保存到文件中,或者在程序启动时从文件读取,更高级的方案是连接数据库(如 MySQL, SQLite)。
  2. 搜索与筛选: 在工具栏添加一个搜索框,可以根据姓名或学号进行实时搜索。
  3. 分页显示: 如果学生数据量很大,可以实现分页功能,避免一次性加载所有数据。
  4. UI 美化:
    • 使用第三方库如 FlatLaf 提供更现代的界面外观。
    • 使用图标来美化按钮和菜单。
  5. 功能增强:
    • 添加“统计”功能,例如按性别、年龄段统计学生人数。
    • 添加“导出”功能,将学生列表导出为 Excel 或 CSV 文件。
  6. 更复杂的 MVC: 对于更庞大的系统,可以将 Controller 进一步细分,或者引入观察者模式,让模型在数据变化时主动通知视图,实现更松散的耦合。

这个项目为你提供了一个非常棒的 Java Swing 学习和实践模板,它涵盖了从基础组件到高级设计模式的方方面面,祝你学习愉快!

分享:
扫描分享到社交APP
上一篇
下一篇