import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class MainFrame extends JFrame {
private final StudentDAO studentDAO = new StudentDAO();
private final User loginUser;
private DefaultTableModel tableModel;
private JTable studentTable;
private JTextField searchField, pageNumField;
private JLabel totalPageLabel;
private int currentPage = 1;
private String sortField = "student_id";
private String sortOrder = "ASC";
// 输入框
private JTextField studentIdField, nameField, genderField, ageField, classNameField;
private String photoPath = "";
private JLabel photoPreview;
private JPanel midPanel;
public MainFrame(User user) {
this.loginUser = user;
initFrame();
loadPageData();
}
private void initFrame() {
setTitle("学生信息管理系统 - " + loginUser.getUsername());
setSize(1200, 800);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setLayout(new BorderLayout(10, 10));
// 设置字体
Font font = new Font("微软雅黑", Font.PLAIN, 16);
Font btnFont = new Font("微软雅黑", Font.BOLD, 16);
// ====================== 顶部区域 ======================
JPanel topPanel = new JPanel(new BorderLayout(10, 10));
topPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
// 查询面板
JPanel searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
JLabel searchTypeLabel = new JLabel("查询类型:");
JComboBox<String> searchTypeBox = new JComboBox<>(new String[]{"学号", "姓名"});
JLabel keywordLabel = new JLabel("查询关键字:");
searchField = new JTextField(15);
JButton searchBtn = new JButton("查询");
JButton showAllBtn = new JButton("显示全部");
// 设置样式
searchTypeLabel.setFont(font);
keywordLabel.setFont(font);
searchTypeBox.setFont(font);
searchField.setFont(font);
searchBtn.setFont(btnFont);
showAllBtn.setFont(btnFont);
searchBtn.setPreferredSize(new Dimension(100, 35));
showAllBtn.setPreferredSize(new Dimension(100, 35));
searchBtn.setBackground(new Color(255, 193, 7));
showAllBtn.setBackground(new Color(255, 193, 7));
searchPanel.add(searchTypeLabel);
searchPanel.add(searchTypeBox);
searchPanel.add(keywordLabel);
searchPanel.add(searchField);
searchPanel.add(searchBtn);
searchPanel.add(showAllBtn);
// 多语言面板
JPanel langPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
JButton zhBtn = new JButton("中文");
JButton enBtn = new JButton("En");
zhBtn.setFont(btnFont);
enBtn.setFont(btnFont);
zhBtn.setPreferredSize(new Dimension(80, 35));
enBtn.setPreferredSize(new Dimension(80, 35));
langPanel.add(zhBtn);
langPanel.add(enBtn);
// 分页面板
JPanel pagePanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 5));
JLabel currentPageLabel = new JLabel("当前页:");
pageNumField = new JTextField(3);
pageNumField.setText("1");
totalPageLabel = new JLabel("总页数:1");
JButton prevBtn = new JButton("上一页");
JButton nextBtn = new JButton("下一页");
currentPageLabel.setFont(font);
totalPageLabel.setFont(font);
pageNumField.setFont(font);
prevBtn.setFont(btnFont);
nextBtn.setFont(btnFont);
prevBtn.setPreferredSize(new Dimension(100, 35));
nextBtn.setPreferredSize(new Dimension(100, 35));
pagePanel.add(currentPageLabel);
pagePanel.add(pageNumField);
pagePanel.add(totalPageLabel);
pagePanel.add(prevBtn);
pagePanel.add(nextBtn);
topPanel.add(searchPanel, BorderLayout.WEST);
topPanel.add(langPanel, BorderLayout.CENTER);
topPanel.add(pagePanel, BorderLayout.EAST);
// ====================== 中间区域 ======================
midPanel = new JPanel(new BorderLayout(10, 10));
midPanel.setBorder(BorderFactory.createEmptyBorder(0, 20, 10, 20));
// 按钮面板
JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
JButton addBtn = new JButton("添加学生");
JButton deleteBtn = new JButton("删除选中");
JButton updateBtn = new JButton("修改学生");
JButton uploadPhotoBtn = new JButton("上传照片");
JButton importBtn = new JButton("Excel导入");
JButton exportBtn = new JButton("Excel导出");
JButton backupBtn = new JButton("数据备份");
JButton restoreBtn = new JButton("数据恢复");
// 按钮样式
JButton[] btns = {addBtn, deleteBtn, updateBtn, uploadPhotoBtn, importBtn, exportBtn, backupBtn, restoreBtn};
Color[] colors = {
new Color(76, 175, 80), new Color(244, 67, 54), new Color(33, 150, 243),
new Color(156, 39, 176), new Color(255, 152, 0), new Color(0, 188, 212),
new Color(139, 195, 74), new Color(255, 87, 34)
};
for (int i = 0; i < btns.length; i++) {
btns[i].setFont(btnFont);
btns[i].setPreferredSize(new Dimension(120, 40));
btns[i].setBackground(colors[i]);
btns[i].setForeground(Color.WHITE);
btnPanel.add(btns[i]);
}
// 普通用户隐藏管理员功能
if (loginUser.getRole().equals("user")) {
addBtn.setVisible(false);
deleteBtn.setVisible(false);
updateBtn.setVisible(false);
uploadPhotoBtn.setVisible(false);
backupBtn.setVisible(false);
restoreBtn.setVisible(false);
}
// 输入面板
JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
inputPanel.setBorder(BorderFactory.createTitledBorder("学生信息"));
// 创建输入框
studentIdField = new JTextField(10);
nameField = new JTextField(10);
genderField = new JTextField(6);
ageField = new JTextField(6);
classNameField = new JTextField(10);
photoPreview = new JLabel();
photoPreview.setPreferredSize(new Dimension(80, 100));
photoPreview.setBorder(BorderFactory.createLineBorder(Color.GRAY));
// 添加标签和输入框
inputPanel.add(new JLabel("学号:"));
inputPanel.add(studentIdField);
inputPanel.add(new JLabel("姓名:"));
inputPanel.add(nameField);
inputPanel.add(new JLabel("性别:"));
inputPanel.add(genderField);
inputPanel.add(new JLabel("年龄:"));
inputPanel.add(ageField);
inputPanel.add(new JLabel("班级:"));
inputPanel.add(classNameField);
inputPanel.add(new JLabel("照片预览:"));
inputPanel.add(photoPreview);
// 设置字体
Component[] components = inputPanel.getComponents();
for (Component comp : components) {
if (comp instanceof JTextField) {
comp.setFont(font);
} else if (comp instanceof JLabel) {
comp.setFont(font);
}
}
midPanel.add(btnPanel, BorderLayout.NORTH);
midPanel.add(inputPanel, BorderLayout.CENTER);
// ====================== 底部表格区域 ======================
String[] tableHeaders = {"学号", "姓名", "性别", "年龄", "班级", "照片路径"};
tableModel = new DefaultTableModel(tableHeaders, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
studentTable = new JTable(tableModel);
studentTable.setFont(new Font("微软雅黑", Font.PLAIN, 14));
studentTable.setRowHeight(35);
studentTable.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 16));
JScrollPane scrollPane = new JScrollPane(studentTable);
// ====================== 组装窗口 ======================
add(topPanel, BorderLayout.NORTH);
add(midPanel, BorderLayout.CENTER);
add(scrollPane, BorderLayout.SOUTH);
// ====================== 绑定事件 ======================
// 查询按钮
searchBtn.addActionListener(e -> {
String keyword = searchField.getText().trim();
String type = (String) searchTypeBox.getSelectedItem();
List<Student> list = studentDAO.searchStudents(keyword, type);
refreshTable(list);
});
// 显示全部按钮
showAllBtn.addActionListener(e -> {
currentPage = 1;
pageNumField.setText("1");
loadPageData();
});
// 多语言切换
zhBtn.addActionListener(e -> switchToChinese(searchTypeLabel, keywordLabel, currentPageLabel, totalPageLabel));
enBtn.addActionListener(e -> switchToEnglish(searchTypeLabel, keywordLabel, currentPageLabel, totalPageLabel));
// 分页按钮
prevBtn.addActionListener(e -> {
if (currentPage > 1) {
currentPage--;
pageNumField.setText(String.valueOf(currentPage));
loadPageData();
} else {
JOptionPane.showMessageDialog(this, "已经是第一页了!");
}
});
nextBtn.addActionListener(e -> {
if (currentPage < getTotalPage()) {
currentPage++;
pageNumField.setText(String.valueOf(currentPage));
loadPageData();
} else {
JOptionPane.showMessageDialog(this, "已经是最后一页了!");
}
});
// 页码跳转
pageNumField.addActionListener(e -> {
try {
int page = Integer.parseInt(pageNumField.getText().trim());
if (page >= 1 && page <= getTotalPage()) {
currentPage = page;
loadPageData();
} else {
JOptionPane.showMessageDialog(this, "页码超出范围!总页数:" + getTotalPage());
}
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "请输入数字!");
}
});
// 表格排序
studentTable.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int column = studentTable.getTableHeader().columnAtPoint(e.getPoint());
if (column == 0) {
sortField = "student_id";
} else if (column == 1) {
sortField = "name";
} else {
return;
}
sortOrder = sortOrder.equals("ASC") ? "DESC" : "ASC";
loadPageData();
}
});
// 表格点击事件
studentTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int row = studentTable.getSelectedRow();
if (row != -1) {
studentIdField.setText((String) tableModel.getValueAt(row, 0));
nameField.setText((String) tableModel.getValueAt(row, 1));
genderField.setText((String) tableModel.getValueAt(row, 2));
ageField.setText(tableModel.getValueAt(row, 3).toString());
classNameField.setText((String) tableModel.getValueAt(row, 4));
photoPath = (String) tableModel.getValueAt(row, 5);
// 显示照片
if (photoPath != null && !photoPath.isEmpty()) {
File file = new File(photoPath);
if (file.exists()) {
ImageIcon icon = new ImageIcon(photoPath);
Image img = icon.getImage().getScaledInstance(80, 100, Image.SCALE_SMOOTH);
photoPreview.setIcon(new ImageIcon(img));
} else {
photoPreview.setIcon(null);
photoPreview.setText("图片丢失");
}
} else {
photoPreview.setIcon(null);
}
}
}
});
// 功能按钮事件
addBtn.addActionListener(e -> addStudent());
deleteBtn.addActionListener(e -> batchDeleteStudents());
updateBtn.addActionListener(e -> updateStudent());
uploadPhotoBtn.addActionListener(e -> uploadPhoto());
importBtn.addActionListener(e -> importExcel());
exportBtn.addActionListener(e -> exportExcel());
backupBtn.addActionListener(e -> backupDB());
restoreBtn.addActionListener(e -> restoreDB());
}
// ====================== 核心方法 ======================
private void loadPageData() {
List<Student> list = studentDAO.getStudentsByPage(currentPage, sortField, sortOrder);
refreshTable(list);
totalPageLabel.setText("总页数:" + getTotalPage());
}
private void refreshTable(List<Student> list) {
tableModel.setRowCount(0);
for (Student s : list) {
tableModel.addRow(new Object[]{
s.getStudentId(),
s.getName(),
s.getGender(),
s.getAge(),
s.getClassName(),
s.getPhotoPath()
});
}
}
private int getTotalPage() {
int total = studentDAO.getTotalStudentCount();
return (int) Math.ceil(total / 10.0);
}
private void addStudent() {
try {
String id = studentIdField.getText().trim();
String name = nameField.getText().trim();
String gender = genderField.getText().trim();
int age = Integer.parseInt(ageField.getText().trim());
String className = classNameField.getText().trim();
if (id.isEmpty() || name.isEmpty() || gender.isEmpty() || className.isEmpty()) {
JOptionPane.showMessageDialog(this, "请填写完整信息!");
return;
}
if (studentDAO.addStudent(new Student(id, name, gender, age, className, photoPath))) {
JOptionPane.showMessageDialog(this, "添加成功!");
clearInput();
loadPageData();
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "年龄请输入数字!");
}
}
private void batchDeleteStudents() {
int[] selectedRows = studentTable.getSelectedRows();
if (selectedRows.length == 0) {
JOptionPane.showMessageDialog(this, "请选中要删除的学生!");
return;
}
int confirm = JOptionPane.showConfirmDialog(this,
"确定要删除选中的" + selectedRows.length + "条数据吗?",
"确认删除", JOptionPane.YES_NO_OPTION);
if (confirm != JOptionPane.YES_OPTION) {
return;
}
List<String> studentIds = new ArrayList<>();
for (int row : selectedRows) {
studentIds.add((String) tableModel.getValueAt(row, 0));
}
if (studentDAO.batchDeleteStudents(studentIds)) {
JOptionPane.showMessageDialog(this, "删除成功!");
loadPageData();
}
}
private void updateStudent() {
try {
String id = studentIdField.getText().trim();
String name = nameField.getText().trim();
String gender = genderField.getText().trim();
int age = Integer.parseInt(ageField.getText().trim());
String className = classNameField.getText().trim();
if (id.isEmpty() || name.isEmpty() || gender.isEmpty() || className.isEmpty()) {
JOptionPane.showMessageDialog(this, "请填写完整信息!");
return;
}
if (studentDAO.getStudentById(id) == null) {
JOptionPane.showMessageDialog(this, "学号不存在!");
return;
}
if (studentDAO.updateStudent(new Student(id, name, gender, age, className, photoPath))) {
JOptionPane.showMessageDialog(this, "修改成功!");
clearInput();
loadPageData();
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "年龄请输入数字!");
}
}
private void uploadPhoto() {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter(
"图片文件", "jpg", "png", "jpeg"));
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
photoPath = chooser.getSelectedFile().getAbsolutePath();
ImageIcon icon = new ImageIcon(photoPath);
Image img = icon.getImage().getScaledInstance(80, 100, Image.SCALE_SMOOTH);
photoPreview.setIcon(new ImageIcon(img));
}
}
// ====================== Excel导入功能(已修复) ======================
private void importExcel() {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter(
"Excel文件 (*.xlsx)", "xlsx"));
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
String filePath = chooser.getSelectedFile().getAbsolutePath();
// 创建进度对话框
JDialog progressDialog = new JDialog(this, "正在导入", true);
progressDialog.setSize(300, 100);
progressDialog.setLocationRelativeTo(this);
JLabel progressLabel = new JLabel("正在导入Excel数据,请稍候...", JLabel.CENTER);
progressDialog.add(progressLabel);
// 在新线程中执行导入,避免界面卡住
new Thread(() -> {
SwingUtilities.invokeLater(() -> progressDialog.setVisible(true));
try {
// 1. 读取Excel文件
List<Student> excelData = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(filePath);
Workbook workbook = new XSSFWorkbook(fis)) {
Sheet sheet = workbook.getSheetAt(0);
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null || row.getCell(0) == null) continue;
try {
String studentId = getCellValue(row.getCell(0));
String name = getCellValue(row.getCell(1));
String gender = getCellValue(row.getCell(2));
String ageStr = getCellValue(row.getCell(3));
String className = getCellValue(row.getCell(4));
String photoPath = row.getCell(5) != null ? getCellValue(row.getCell(5)) : "";
if (studentId == null || studentId.trim().isEmpty()) {
continue;
}
int age = 18;
try {
age = Integer.parseInt(ageStr);
} catch (Exception e) {
// 使用默认年龄
}
if (gender == null || gender.trim().isEmpty()) {
gender = "男";
}
if (className == null || className.trim().isEmpty()) {
className = "计算机234班";
}
excelData.add(new Student(studentId.trim(), name.trim(),
gender.trim(), age,
className.trim(), photoPath.trim()));
} catch (Exception e) {
System.out.println("跳过第 " + (i+1) + " 行:" + e.getMessage());
}
}
}
// 2. 导入到数据库
int success = 0;
for (Student student : excelData) {
if (studentDAO.addStudent(student)) {
success++;
}
}
// 3. 关闭进度对话框
SwingUtilities.invokeLater(() -> {
progressDialog.setVisible(false);
// 4. 显示结果并刷新表格
String result = String.format("导入完成!\n成功导入:%d条\n读取总行数:%d条",
success, excelData.size());
JOptionPane.showMessageDialog(MainFrame.this, result);
// 关键:刷新表格!!!
loadPageData();
// 同时更新总页数显示
totalPageLabel.setText("总页数:" + getTotalPage());
});
} catch (Exception e) {
SwingUtilities.invokeLater(() -> {
progressDialog.setVisible(false);
JOptionPane.showMessageDialog(MainFrame.this,
"导入失败!\n错误:" + e.getMessage());
});
e.printStackTrace();
}
}).start();
}
}
// Excel单元格值获取辅助方法
private String getCellValue(Cell cell) {
if (cell == null) return "";
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue().toString();
} else {
double num = cell.getNumericCellValue();
if (num == (int) num) {
return String.valueOf((int) num);
} else {
return String.valueOf(num);
}
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
default:
return "";
}
}
private void exportExcel() {
List<Student> list = studentDAO.getAllStudents();
if (list.isEmpty()) {
JOptionPane.showMessageDialog(this, "没有数据可导出!");
return;
}
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter(
"Excel文件 (*.xlsx)", "xlsx"));
if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
String filePath = chooser.getSelectedFile().getAbsolutePath();
ToolUtil.exportExcel(list, filePath);
}
}
private void backupDB() {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter(
"SQL文件 (*.sql)", "sql"));
if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
String filePath = chooser.getSelectedFile().getAbsolutePath();
ToolUtil.backupDB(filePath);
}
}
private void restoreDB() {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter(
"SQL文件 (*.sql)", "sql"));
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
ToolUtil.restoreDB(chooser.getSelectedFile().getAbsolutePath());
loadPageData();
}
}
private void clearInput() {
studentIdField.setText("");
nameField.setText("");
genderField.setText("");
ageField.setText("");
classNameField.setText("");
photoPath = "";
photoPreview.setIcon(null);
}
private void switchToChinese(JLabel... labels) {
setTitle("学生信息管理系统");
if (labels.length > 0) labels[0].setText("查询类型:");
if (labels.length > 1) labels[1].setText("查询关键字:");
if (labels.length > 2) labels[2].setText("当前页:");
if (labels.length > 3) labels[3].setText("总页数:");
}
private void switchToEnglish(JLabel... labels) {
setTitle("Student Information Management System");
if (labels.length > 0) labels[0].setText("Search Type:");
if (labels.length > 1) labels[1].setText("Keyword:");
if (labels.length > 2) labels[2].setText("Current Page:");
if (labels.length > 3) labels[3].setText("Total Pages:");
}
}检查该代码是否有误
最新发布