JPanel的移除控件和刷新

本文介绍了在Java Swing中使用JPanel时遇到的刷新不彻底或延迟问题及其解决方案。通过使用revalidate()方法重新布局组件,并结合repaint()方法对容器本身进行重绘,可以有效解决该问题。
部署运行你感兴趣的模型镜像

前几天遇到一个在JPanel中移除控件后,用revalidate()方法重绘后,面板刷新有不彻底或延时的问题,通过网页的各种方法后,添加了JPanel的repaint()方法才解决了这个问题。原来revalidate()方法是对布局管理器对应的容器的子组件重新布局并绘制。但是容器自身“不一定”会绘制。容器自身的重绘,轻量级的方法一般调用repaint()。
如:

     Panel1.remove(pieces);//删除panel1中原有的组件
     demo.setBounds(0, 92, 338, 528);
     Panel1.add(demo);//panel1添加新的组件
     Panel1.revalidate();//对panel1面板中的组件重新布局并绘制
     Panel1.repaint();//对panel1本身进行重绘

您可能感兴趣的与本文相关的镜像

Yolo-v8.3

Yolo-v8.3

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

package com.student.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.student.entity.Student; import com.student.util.DBUtil; public class StudentDAO { // 插入学生 public void insertStudent(Student student) { String sql = "INSERT INTO students (sid, name, age, score) VALUES (?, ?, ?, ?)"; try (Connection conn = DBUtil.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, student.getSid()); pstmt.setString(2, student.getName()); pstmt.setInt(3, student.getAge()); pstmt.setDouble(4, student.getScore()); pstmt.executeUpdate(); } catch (SQLException e) { System.err.println("插入学生信息时出现错误: " + e.getMessage()); } } // 获取所有学生 public List<Student> getAllStudents() { List<Student> students = new ArrayList<>(); String sql = "SELECT * FROM students"; try (Connection conn = DBUtil.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { students.add(extractStudentFromResultSet(rs)); } } catch (SQLException e) { e.printStackTrace(); } return students; } // 删除学生(修改方法名) public void deleteStudent(String sid) { // 这里修改了方法名 String sql = "DELETE FROM students WHERE sid = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, sid); int rowsAffected = pstmt.executeUpdate(); if (rowsAffected == 0) { System.err.println("未找到学号为 " + sid + " 的学生"); } } catch (SQLException e) { e.printStackTrace(); } } // 更新学生信息 public void updateStudent(Student student) { String sql = "UPDATE students SET name = ?, age = ?, score = ? WHERE sid = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, student.getName()); pstmt.setInt(2, student.getAge()); pstmt.setDouble(3, student.getScore()); pstmt.setString(4, student.getSid()); int rowsAffected = pstmt.executeUpdate(); if (rowsAffected == 0) { System.err.println("未找到学号为 " + student.getSid() + " 的学生"); } } catch (SQLException e) { e.printStackTrace(); } } // 搜索学生 public List<Student> searchStudents(String keyword) { List<Student> students = new ArrayList<>(); String sql = "SELECT * FROM students WHERE sid LIKE ? OR name LIKE ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { String searchPattern = "%" + keyword + "%"; pstmt.setString(1, searchPattern); pstmt.setString(2, searchPattern); try (ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { students.add(extractStudentFromResultSet(rs)); } } } catch (SQLException e) { e.printStackTrace(); } return students; } // 排序学生 public List<Student> getStudentsOrderBy(String field) { List<Student> students = new ArrayList<>(); String validField = validateSortField(field); String sql = "SELECT * FROM students ORDER BY " + validField; try (Connection conn = DBUtil.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { students.add(extractStudentFromResultSet(rs)); } } catch (SQLException e) { e.printStackTrace(); } return students; } // 根据ID获取学生 public Student getStudentById(String sid) { String sql = "SELECT * FROM students WHERE sid = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, sid); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { return extractStudentFromResultSet(rs); } } } catch (SQLException e) { e.printStackTrace(); } return null; } // 验证排序字段(防止SQL注入) private String validateSortField(String field) { String[] validFields = {"sid", "name", "age", "score"}; for (String valid : validFields) { if (valid.equalsIgnoreCase(field)) { return valid; } } return "sid"; // 默认值 } // 从ResultSet提取学生对象(复用代码) private Student extractStudentFromResultSet(ResultSet rs) throws SQLException { String sid = rs.getString("sid"); String name = rs.getString("name"); int age = rs.getInt("age"); double score = rs.getDouble("score"); return new Student(sid, name, age, score); } } package com.student.ui; import com.student.dao.StudentDAO; import com.student.entity.Student; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.util.List; public class StudentGUI extends JFrame { private JTable studentTable; private DefaultTableModel tableModel; private StudentDAO studentDAO = new StudentDAO(); private JTextField searchField; private JComboBox<String> sortComboBox; public StudentGUI() { setTitle("学生信息管理系统"); setSize(900, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置淡蓝色背景 getContentPane().setBackground(new Color(230, 240, 255)); // 创建表格 String[] columns = {"学号", "姓名", "年龄", "成绩"}; tableModel = new DefaultTableModel(columns, 0) { @Override public boolean isCellEditable(int row, int column) { return false; // 禁止表格直接编辑 } }; studentTable = new JTable(tableModel); studentTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 创建功能面板 JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); controlPanel.setBackground(new Color(230, 240, 255)); // 搜索组件 searchField = new JTextField(15); JButton searchBtn = new JButton("查找"); searchBtn.addActionListener(e -> searchStudents()); controlPanel.add(new JLabel("搜索:")); controlPanel.add(searchField); controlPanel.add(searchBtn); // 排序组件 sortComboBox = new JComboBox<>(new String[]{"学号", "姓名", "年龄", "成绩"}); JButton sortBtn = new JButton("排序"); sortBtn.addActionListener(e -> sortStudents()); controlPanel.add(new JLabel("排序:")); controlPanel.add(sortComboBox); controlPanel.add(sortBtn); // 操作按钮 JButton addBtn = new JButton("添加学生"); addBtn.addActionListener(e -> showAddDialog()); JButton editBtn = new JButton("修改"); editBtn.addActionListener(e -> showEditDialog()); JButton deleteBtn = new JButton("删除"); deleteBtn.addActionListener(e -> deleteStudent()); // 添加按钮到面板 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); buttonPanel.setBackground(new Color(230, 240, 255)); buttonPanel.add(addBtn); buttonPanel.add(editBtn); buttonPanel.add(deleteBtn); // 主布局 JPanel mainPanel = new JPanel(new BorderLayout(10, 10)); mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); mainPanel.setBackground(new Color(230, 240, 255)); mainPanel.add(controlPanel, BorderLayout.NORTH); mainPanel.add(new JScrollPane(studentTable), BorderLayout.CENTER); mainPanel.add(buttonPanel, BorderLayout.SOUTH); setContentPane(mainPanel); refreshTable(); } // 添加学生对话框 private void showAddDialog() { JDialog dialog = new JDialog(this, "添加学生", true); dialog.setSize(300, 250); dialog.setLayout(new BorderLayout()); dialog.getContentPane().setBackground(new Color(230, 240, 255)); JPanel formPanel = createFormPanel(); JButton saveBtn = new JButton("保存"); // 获取表单字段 JTextField sidField = (JTextField) formPanel.getComponent(1); JTextField nameField = (JTextField) formPanel.getComponent(3); JTextField ageField = (JTextField) formPanel.getComponent(5); JTextField scoreField = (JTextField) formPanel.getComponent(7); saveBtn.addActionListener(e -> { try { Student student = new Student( sidField.getText(), nameField.getText(), Integer.parseInt(ageField.getText()), Double.parseDouble(scoreField.getText()) ); studentDAO.insertStudent(student); refreshTable(); dialog.dispose(); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(this, "请输入有效的数字", "错误", JOptionPane.ERROR_MESSAGE); } }); dialog.add(formPanel, BorderLayout.CENTER); dialog.add(saveBtn, BorderLayout.SOUTH); dialog.setVisible(true); } // 修改学生对话框 private void showEditDialog() { int selectedRow = studentTable.getSelectedRow(); if (selectedRow == -1) { JOptionPane.showMessageDialog(this, "请先选择要修改的学生", "提示", JOptionPane.WARNING_MESSAGE); return; } String sid = (String) tableModel.getValueAt(selectedRow, 0); Student student = studentDAO.getStudentById(sid); JDialog dialog = new JDialog(this, "修改学生信息", true); dialog.setSize(300, 250); dialog.setLayout(new BorderLayout()); dialog.getContentPane().setBackground(new Color(230, 240, 255)); JPanel formPanel = createFormPanel(); // 填充当前数据 ((JTextField) formPanel.getComponent(1)).setText(student.getSid()); ((JTextField) formPanel.getComponent(3)).setText(student.getName()); ((JTextField) formPanel.getComponent(5)).setText(String.valueOf(student.getAge())); ((JTextField) formPanel.getComponent(7)).setText(String.valueOf(student.getScore())); // 学号不可编辑 ((JTextField) formPanel.getComponent(1)).setEditable(false); JButton saveBtn = new JButton("保存"); saveBtn.addActionListener(e -> { try { student.setName(((JTextField) formPanel.getComponent(3)).getText()); student.setAge(Integer.parseInt(((JTextField) formPanel.getComponent(5)).getText())); student.setScore(Double.parseDouble(((JTextField) formPanel.getComponent(7)).getText())); studentDAO.updateStudent(student); refreshTable(); dialog.dispose(); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(this, "请输入有效的数字", "错误", JOptionPane.ERROR_MESSAGE); } }); dialog.add(formPanel, BorderLayout.CENTER); dialog.add(saveBtn, BorderLayout.SOUTH); dialog.setVisible(true); } // 创建表单面板(复用) private JPanel createFormPanel() { JPanel formPanel = new JPanel(new GridLayout(4, 2, 5, 10)); formPanel.setBackground(new Color(230, 240, 255)); formPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); formPanel.add(new JLabel("学号:")); formPanel.add(new JTextField()); formPanel.add(new JLabel("姓名:")); formPanel.add(new JTextField()); formPanel.add(new JLabel("年龄:")); formPanel.add(new JTextField()); formPanel.add(new JLabel("成绩:")); formPanel.add(new JTextField()); return formPanel; } // 删除学生 private void deleteStudent() { int selectedRow = studentTable.getSelectedRow(); if (selectedRow == -1) { JOptionPane.showMessageDialog(this, "请先选择要删除的学生", "提示", JOptionPane.WARNING_MESSAGE); return; } int confirm = JOptionPane.showConfirmDialog( this, "确定要删除该学生吗?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { String sid = (String) tableModel.getValueAt(selectedRow, 0); studentDAO.deleteStudent(sid); refreshTable(); } } // 搜索学生 private void searchStudents() { String keyword = searchField.getText().trim(); if (keyword.isEmpty()) { refreshTable(); return; } List<Student> students = studentDAO.searchStudents(keyword); updateTable(students); } // 排序学生 private void sortStudents() { String sortBy = (String) sortComboBox.getSelectedItem(); String sortField = ""; switch (sortBy) { case "学号": sortField = "sid"; break; case "姓名": sortField = "name"; break; case "年龄": sortField = "age"; break; case "成绩": sortField = "score"; break; } List<Student> students = studentDAO.getStudentsOrderBy(sortField); updateTable(students); } // 刷新表格 private void refreshTable() { List<Student> students = studentDAO.getAllStudents(); updateTable(students); } // 更新表格数据 private void updateTable(List<Student> students) { tableModel.setRowCount(0); for (Student s : students) { tableModel.addRow(new Object[]{s.getSid(), s.getName(), s.getAge(), s.getScore()}); } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { StudentGUI gui = new StudentGUI(); gui.setVisible(true); }); } } 请根据这两个代码修改
06-25
package gui; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.List; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.table.DefaultTableModel; import enrollment.Enrollment; import enrollment.EnrollmentDao; import enrollment.EnrollmentDaoImpl; public class EnrollmentManagementPanel extends JPanel { private final EnrollmentDao enrollmentDao = new EnrollmentDaoImpl(); private final DefaultTableModel model = new DefaultTableModel( new String[]{"学生ID", "课程代码", "选课时间", "成绩", "等级", "状态", "是否补考", "评语"}, 0); private final JTable table = new JTable(model); // 表单字段 private final JTextField txtStudentId = new JTextField(8); private final JTextField txtCourseCode = new JTextField(10); private final JTextField txtEnrollmentTime = new JTextField(16); // YYYY-MM-DD HH:MM:SS private final JTextField txtGrade = new JTextField(6); // 可为空 private final JLabel lblGradeLevel = new JLabel("N/A"); private final JComboBox<String> cmbStatus = new JComboBox<>(new String[]{"已选课", "已退课", "已评分"}); private final JCheckBox chkMakeUpExam = new JCheckBox("是", true); private final JCheckBox chkMakeUpExam1 = new JCheckBox("否", false); private final JTextArea txtComment = new JTextArea(1, 20); private final JScrollPane commentScrollPane = new JScrollPane(txtComment); public EnrollmentManagementPanel() { setLayout(new BorderLayout()); // 表格区域 add(new JScrollPane(table), BorderLayout.CENTER); // 表单输入区 //JPanel form = new JPanel(new GridLayout(5, 6, 10, 10)); //form.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // 创建主表单面板,使用更灵活的 GridBagLayout 替代 GridLayout JPanel form = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(5, 5, 5, 5); gbc.fill = GridBagConstraints.HORIZONTAL; String[] fields = {"学生ID", "课程代码", "选课时间", "成绩", "等级", "状态", "是否补考", "评语"}; /* 0-学生ID 1-课程代码 2-选课时间 3-成绩 4-null(等级只读) 5-null(下拉框) 6-null(单选) 7-null(文本区) */ JTextField[] fieldArr = { txtStudentId, txtCourseCode, txtEnrollmentTime, txtGrade, null, null, null, null }; for (int i = 0; i < fields.length; i++) { gbc.gridx = 0; gbc.gridy = i; gbc.anchor = GridBagConstraints.EAST; form.add(new JLabel(fields[i] + ":"), gbc); gbc.gridx = 1; gbc.weightx = 1.0; switch (fields[i]) { case "等级" -> form.add(lblGradeLevel, gbc); // 只读标签 case "状态" -> form.add(cmbStatus, gbc); case "是否补考" -> { JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); p.add(chkMakeUpExam); form.add(p, gbc); } case "评语" -> form.add(commentScrollPane, gbc); default -> form.add(fieldArr[i], gbc); // 用成员控件,不再 new! } } //UIManager.put("Label.font", new Font("微软雅黑", Font.PLAIN, 14)); //UIManager.put("TextField.font", new Font("微软雅黑", Font.PLAIN, 14)); /*form.add(new JLabel("学生ID:", SwingConstants.RIGHT)); form.add(txtStudentId); form.add(new JLabel("课程代码:", SwingConstants.RIGHT)); form.add(txtCourseCode); form.add(new JLabel("选课时间:", SwingConstants.RIGHT)); form.add(txtEnrollmentTime); form.add(new JLabel("成绩:", SwingConstants.RIGHT)); form.add(txtGrade); form.add(new JLabel("等级:", SwingConstants.RIGHT)); form.add(lblGradeLevel); form.add(new JLabel("状态:", SwingConstants.RIGHT)); form.add(cmbStatus); form.add(new JLabel("是否补考:", SwingConstants.RIGHT)); form.add(chkMakeUpExam); form.add(new JLabel("评语:", SwingConstants.RIGHT)); form.add(commentScrollPane);*/ // 按钮组 JButton btnAdd = new JButton("添加选课"); JButton btnUpdateGrade = new JButton("更新成绩"); JButton btnDelete = new JButton("删除记录"); JButton btnFindByStudent = new JButton("按学生查"); JButton btnByCourse = new JButton("按课程查"); JButton btnRefresh = new JButton("刷新全部"); JButton btnClear = new JButton("清空"); JPanel btnPanel = new JPanel(); btnPanel.add(btnAdd); btnPanel.add(btnUpdateGrade); btnPanel.add(btnDelete); btnPanel.add(btnFindByStudent); btnPanel.add(btnByCourse); btnPanel.add(btnRefresh); btnPanel.add(btnClear); form.add(btnPanel); add(form, BorderLayout.SOUTH); // ==================== 事件绑定 ==================== btnAdd.addActionListener(e -> addEnrollment()); btnUpdateGrade.addActionListener(e -> updateGrade()); btnDelete.addActionListener(e -> deleteEnrollment()); btnFindByStudent.addActionListener(e -> findByStudentId()); btnByCourse.addActionListener(e -> findByCourseCode()); btnRefresh.addActionListener(e -> refreshTable()); btnClear.addActionListener(e -> clearForm()); // 成绩变化时实时更新等级显示 txtGrade.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() { @Override public void insertUpdate(javax.swing.event.DocumentEvent e) { updateGradeLevel(); } @Override public void removeUpdate(javax.swing.event.DocumentEvent e) { updateGradeLevel(); } @Override public void changedUpdate(javax.swing.event.DocumentEvent e) { updateGradeLevel(); } }); // 表格点击 → 回填表单 table.getSelectionModel().addListSelectionListener(evt -> { if (!evt.getValueIsAdjusting()) fillFormFromTable(); }); // 初始化加载所有数据 refreshTable(); } // ==================== 核心操作方法 ==================== /** * 添加选课记录 */ private void addEnrollment() { try { Enrollment e = getFormEnrollment(); enrollmentDao.insert(e); model.addRow(new Object[]{ e.getStudentId(), e.getCourseCode(), e.getEnrollmentTime(), formatDouble(e.getGrade()), e.getGradeLevel(), e.getStatus(), e.isMakeUpExam() ? "✅" : "❌", e.getComment() }); JOptionPane.showMessageDialog(this, "✅ 添加成功!"); clearForm(); } catch (Exception ex) { showError("❌ 添加失败:" + ex.getMessage()); } } /** * 更新成绩(独立操作,更安全) */ private void updateGrade() { int row = table.getSelectedRow(); if (row < 0) { showInfo("请先选择一条记录来更新成绩!"); return; } try { int studentId = (int) model.getValueAt(row, 0); String courseCode = (String) model.getValueAt(row, 1); Double grade = parseDouble(txtGrade.getText(), "成绩"); enrollmentDao.updateGrade(studentId, courseCode, grade); // 更新表格 model.setValueAt(formatDouble(grade), row, 3); model.setValueAt(getGradeLevel(grade), row, 4); model.setValueAt("已评分", row, 5); model.setValueAt(grade < 60 ? "✅" : "❌", row, 6); // 补考标记 showInfo("✅ 成绩更新成功,等级:" + getGradeLevel(grade) + "," + (grade >= 60 ? "已通过" : "需补考")); } catch (Exception ex) { showError("❌ 更新成绩失败:" + ex.getMessage()); } } /** * 删除选课记录(按学生+课程) */ private void deleteEnrollment() { int row = table.getSelectedRow(); if (row < 0) { showInfo("请先选择要删除的选课记录!"); return; } int studentId = (int) model.getValueAt(row, 0); String courseCode = (String) model.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog(this, "确定删除 学生ID=" + studentId + " 的课程 " + courseCode + " 的记录?", "确认删除", JOptionPane.YES_NO_OPTION); if (confirm != JOptionPane.YES_OPTION) return; try { enrollmentDao.delete(studentId, courseCode); model.removeRow(row); JOptionPane.showMessageDialog(this, "✅ 删除成功!"); } catch (Exception ex) { showError("❌ 删除失败:" + ex.getMessage()); } } /** * 按学生 ID 查询其所有选课 */ private void findByStudentId() { try { int id = Integer.parseInt(txtStudentId.getText().trim()); var list = enrollmentDao.findByStudentId(id); model.setRowCount(0); for (Enrollment e : list) { addEnrollmentToTable(e); } showInfo("共加载 " + list.size() + " 条该学生的选课记录"); } catch (NumberFormatException e) { showError("学生ID必须是数字"); } catch (Exception ex) { showError("查询失败:" + ex.getMessage()); } } /** * 按课程代码查询所有选课学生 */ private void findByCourseCode() { String code = txtCourseCode.getText().trim(); if (code.isEmpty()) { showInfo("请输入课程代码!"); return; } try { var list = enrollmentDao.findByCourseCode(code); model.setRowCount(0); for (Enrollment e : list) { addEnrollmentToTable(e); } showInfo("共加载 " + list.size() + " 名学生选修此课程"); } catch (Exception ex) { showError("查询失败:" + ex.getMessage()); } } /** * 刷新:重新加载所有选课记录 */ private void refreshTable() { model.setRowCount(0); try { List<Enrollment> all = enrollmentDao.findByStudentId(0); // 不支持直接 findAll? 手动查全部 // 这里模拟 findAll —— 如果数据库量大建议分页 String sql = "SELECT DISTINCT student_id FROM enrollments"; java.sql.Connection conn = util.DBConnection.getConnection(); java.sql.Statement stmt = conn.createStatement(); java.sql.ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { int sid = rs.getInt("student_id"); var list = enrollmentDao.findByStudentId(sid); for (Enrollment e : list) { addEnrollmentToTable(e); } } conn.close(); } catch (Exception ex) { showError("加载失败:" + ex.getMessage()); } } /** * 填充表单:从表格选中行 */ private void fillFormFromTable() { int row = table.getSelectedRow(); if (row < 0) return; txtStudentId.setText(model.getValueAt(row, 0).toString()); txtCourseCode.setText(model.getValueAt(row, 1).toString()); txtEnrollmentTime.setText(model.getValueAt(row, 2).toString()); Object gradeVal = model.getValueAt(row, 3); txtGrade.setText(gradeVal == null || "null".equals(gradeVal) ? "" : gradeVal.toString()); cmbStatus.setSelectedItem(model.getValueAt(row, 5)); chkMakeUpExam.setSelected("✅".equals(model.getValueAt(row, 6))); txtComment.setText(model.getValueAt(row, 7) == null ? "" : model.getValueAt(row, 7).toString()); } /** * 清空表单 */ private void clearForm() { txtStudentId.setText(""); txtCourseCode.setText(""); txtEnrollmentTime.setText(""); txtGrade.setText(""); lblGradeLevel.setText("N/A"); cmbStatus.setSelectedIndex(0); chkMakeUpExam.setSelected(false); txtComment.setText(""); } // ==================== 工具方法 ==================== /** * 从表单读取数据构建 Enrollment 对象 */ /*private LocalDateTime parseDateTime(String text, String field) throws Exception { try { return LocalDateTime.parse(text); } catch (Exception e) { throw new Exception(field + "格式应为 yyyy-MM-dd HH:mm:ss,当前输入:" + text); } }*/ /** * 安全解析字符串为 LocalDateTime * 支持多种常见格式,自动补全缺失的时间部分(如只有日期时,默认时间为 00:00:00) * * @param text 输入的时间字符串 * @param field 字段名称(用于错误提示) * @return 解析成功的 LocalDateTime 对象 * @throws Exception 如果所有格式都无法匹配,抛出带详细信息的异常 */ private LocalDateTime parseDateTime(String text, String field) throws Exception { if (text == null || text.trim().isEmpty()) { throw new Exception(field + "不能为空"); } text = text.trim(); // 定义支持的格式模式 String[] patterns = { "yyyy-MM-dd HH:mm:ss", // 2025-04-05 14:30:00 "yyyy/MM/dd HH:mm:ss", // 2025/04/05 14:30:00 "yyyy-MM-dd HH:mm", // 2025-04-05 14:30 "yyyy/MM/dd HH:mm", // 2025/04/05 14:30 "yyyy-MM-dd", // 2025-04-05 → 默认时间 00:00:00 "yyyy/MM/dd" // 2025/04/05 }; // 尝试每一种格式 for (String pattern : patterns) { try { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); LocalDateTime dateTime = LocalDateTime.parse(text, formatter); // 如果格式中不含时间(只有日期),我们已经通过 parse 得到的是当天 00:00:00,无需额外处理 return dateTime; } catch (DateTimeParseException ignored) { // 继续尝试下一个格式 } } // 所有格式都失败了,给出友好错误提示 throw new Exception( field + "格式不正确。支持的格式示例:" + "\n 2025-04-05 14:30:00" + "\n 2025/04/05 14:30:00" + "\n 2025-04-05 14:30" + "\n 2025-04-05" + "\n当前输入:" + text ); } private Enrollment getFormEnrollment() throws Exception { Enrollment e = new Enrollment(); e.setStudentId(parseInt(txtStudentId.getText(), "学生ID")); e.setCourseCode(txtCourseCode.getText().trim()); if (e.getCourseCode().isEmpty()) throw new IllegalArgumentException("课程代码不能为空"); String timeStr = txtEnrollmentTime.getText().trim(); e.setEnrollmentTime(timeStr.isEmpty() ? LocalDateTime.now() : parseDateTime(timeStr, "选课时间")); String gradeText = txtGrade.getText().trim(); if (!gradeText.isEmpty()) { double grade = parseDouble(gradeText, "成绩"); e.setGrade(grade); e.CalculateGradeLevel(grade); e.setStatus("已评分"); } else { e.setGrade(null); e.CalculateGradeLevel(null); e.setStatus((String) cmbStatus.getSelectedItem()); } e.setMakeUpExam(chkMakeUpExam.isSelected()); e.setComment(txtComment.getText().trim()); return e; } /** * 将单个选课加入表格 */ private void addEnrollmentToTable(Enrollment e) { model.addRow(new Object[]{ e.getStudentId(), e.getCourseCode(), e.getEnrollmentTime(), formatDouble(e.getGrade()), e.getGradeLevel(), e.getStatus(), e.isMakeUpExam() ? "✅" : "❌", e.getComment() }); } /** * 安全解析整数 */ private int parseInt(String text, String field) throws NumberFormatException { if (text == null || text.trim().isEmpty()) throw new NumberFormatException(field + "不能为空"); return Integer.parseInt(text.trim()); } /** * 安全解析双精度 */ private Double parseDouble(String text, String field) throws NumberFormatException { if (text == null || text.trim().isEmpty()) return null; double val = Double.parseDouble(text.trim()); if (val < 0 || val > 100) throw new IllegalArgumentException(field + "应在 0~100 之间"); return val; } /** * 格式化成绩显示 */ private String formatDouble(Double d) { return d == null ? "未评分" : String.format("%.1f", d); } /** * 手动计算等级(同步前端显示) */ private void updateGradeLevel() { try { String text = txtGrade.getText().trim(); if (text.isEmpty()) { lblGradeLevel.setText("N/A"); return; } double grade = Double.parseDouble(text); lblGradeLevel.setText(getGradeLevel(grade)); } catch (Exception e) { lblGradeLevel.setText("错误"); } } /** * 获取等级(A/B/C/D/F) */ private String getGradeLevel(Double grade) { if (grade == null) return "N/A"; return switch ((int)(grade / 10)) { case 10, 9 -> "A"; case 8 -> "B"; case 7 -> "C"; case 6 -> "D"; default -> "F"; }; } /** * 显示错误消息 */ private void showError(String message) { JOptionPane.showMessageDialog(this, message, "错误", JOptionPane.ERROR_MESSAGE); } /** * 显示提示信息 */ private void showInfo(String message) { JOptionPane.showMessageDialog(this, message, "提示", JOptionPane.INFORMATION_MESSAGE); } } 这段代码应该放在哪’
最新发布
11-21
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值