You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Math_Learning/src/View/MainFrame.java

731 lines
26 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package View;
import Service.User_service;
import Service.Exam_service;
import Base.Exam_result;
import Base.Question;
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class MainFrame extends JFrame {
private final User_service userService;
private Exam_service examService;
private CardLayout cardLayout;
private JPanel mainPanel;
private String currentUserId;
// UI组件字段
private JTextField loginIdField;
private JPasswordField loginPasswordField;
private JTextField regEmailField;
private JTextField regCodeField;
private JPasswordField regPasswordField;
private JPasswordField regConfirmPasswordField;
private JTextField regUserIdField;
private JLabel questionLabel;
private JRadioButton[] optionButtons;
private ButtonGroup optionGroup;
private JLabel questionNumberLabel;
private JButton prevButton;
private JButton nextButton;
private JButton submitButton;
private JLabel resultLabel;
public MainFrame() {
userService = new User_service();
initializeUI();
setTitle("数学学习系统");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
setLocationRelativeTo(null);
}
private void initializeUI() {
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
createLoginPanel();
createRegisterPanel();
createGradeSelectionPanel();
createExamPanel();
createResultPanel();
createWrongQuestionsPanel(); // 新增错题面板
createPasswordChangePanel();
add(mainPanel);
showLoginPanel();
}
private void createLoginPanel() {
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100));
JLabel titleLabel = new JLabel("数学学习系统", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
panel.add(titleLabel, BorderLayout.NORTH);
JPanel formPanel = new JPanel(new GridLayout(3, 2, 15, 15));
formPanel.setBorder(BorderFactory.createEmptyBorder(30, 50, 30, 50));
formPanel.add(new JLabel("用户名:", JLabel.CENTER));
loginIdField = new JTextField();
formPanel.add(loginIdField);
formPanel.add(new JLabel("密码:", JLabel.CENTER));
loginPasswordField = new JPasswordField();
formPanel.add(loginPasswordField);
panel.add(formPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton loginButton = createStyledButton("登录");
loginButton.addActionListener(e -> login());
buttonPanel.add(loginButton);
JButton registerButton = createStyledButton("注册账号");
registerButton.addActionListener(e -> showRegisterPanel());
buttonPanel.add(registerButton);
JButton exitButton = createStyledButton("退出");
exitButton.addActionListener(e -> exitchoice());
buttonPanel.add(exitButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "Login");
}
private void createRegisterPanel() {
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(30, 80, 30, 80));
JLabel titleLabel = new JLabel("用户注册", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
panel.add(titleLabel, BorderLayout.NORTH);
JPanel formPanel = new JPanel(new GridLayout(5, 2, 15, 15));
formPanel.setBorder(BorderFactory.createEmptyBorder(20, 50, 20, 50));
formPanel.add(new JLabel("邮箱:", JLabel.CENTER));
regEmailField = new JTextField();
formPanel.add(regEmailField);
formPanel.add(new JLabel("验证码:", JLabel.CENTER));
JPanel codePanel = new JPanel(new BorderLayout(5, 0));
regCodeField = new JTextField();
codePanel.add(regCodeField, BorderLayout.CENTER);
JButton sendCodeButton = new JButton("发送验证码");
sendCodeButton.setFont(new Font("微软雅黑", Font.PLAIN, 10));
sendCodeButton.addActionListener(e -> sendVerificationCode());
codePanel.add(sendCodeButton, BorderLayout.EAST);
formPanel.add(codePanel);
formPanel.add(new JLabel("密码:", JLabel.CENTER));
regPasswordField = new JPasswordField();
formPanel.add(regPasswordField);
formPanel.add(new JLabel("确认密码:", JLabel.CENTER));
regConfirmPasswordField = new JPasswordField();
formPanel.add(regConfirmPasswordField);
formPanel.add(new JLabel("用户名:", JLabel.CENTER));
regUserIdField = new JTextField();
formPanel.add(regUserIdField);
panel.add(formPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton registerButton = createStyledButton("注册");
registerButton.addActionListener(e -> register());
buttonPanel.add(registerButton);
JButton backButton = createStyledButton("返回登录");
backButton.addActionListener(e -> showLoginPanel());
buttonPanel.add(backButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "Register");
}
private void createGradeSelectionPanel() {
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100));
JLabel titleLabel = new JLabel("选择学习阶段", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
panel.add(titleLabel, BorderLayout.NORTH);
JPanel gradePanel = new JPanel(new GridLayout(4, 1, 20, 20));
gradePanel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100));
JButton primaryButton = createGradeButton("小学");
primaryButton.addActionListener(e -> startExam("小学"));
gradePanel.add(primaryButton);
JButton juniorButton = createGradeButton("初中");
juniorButton.addActionListener(e -> startExam("初中"));
gradePanel.add(juniorButton);
JButton seniorButton = createGradeButton("高中");
seniorButton.addActionListener(e -> startExam("高中"));
gradePanel.add(seniorButton);
panel.add(gradePanel, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton changePasswordButton = createStyledButton("修改密码");
changePasswordButton.addActionListener(e -> showPasswordChangePanel());
bottomPanel.add(changePasswordButton);
// 新增:删除账号按钮
JButton deleteAccountButton = createStyledButton("删除账号");
deleteAccountButton.setBackground(new Color(220, 20, 60)); // 红色背景提示危险操作
deleteAccountButton.addActionListener(e -> deleteAccount());
bottomPanel.add(deleteAccountButton);
JButton logoutButton = createStyledButton("退出登录");
logoutButton.addActionListener(e -> logout());
bottomPanel.add(logoutButton);
panel.add(bottomPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "GradeSelection");
}
// 新增:删除当前账号功能
private void deleteAccount() {
// 简单确认对话框
int result = JOptionPane.showConfirmDialog(
this,
"确定要删除当前账号吗?\n用户名" + currentUserId + "\n此操作不可恢复",
"确认删除账号",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE
);
if (result == JOptionPane.YES_OPTION) {
// 直接使用当前用户名作为邮箱(根据您的系统设计,用户名可能就是邮箱)
// 或者让用户输入邮箱确认
String userEmail = JOptionPane.showInputDialog(
this,
"请输入您的邮箱进行确认:",
"确认删除",
JOptionPane.QUESTION_MESSAGE
);
if (userEmail != null && !userEmail.trim().isEmpty()) {
// 调用User_service的Unregister函数删除账号
String deleteResult = userService.Unregister(userEmail.trim());
if (deleteResult.equals("删除成功")) {
JOptionPane.showMessageDialog(this, "账号删除成功!");
// 清除当前用户信息并返回登录界面
currentUserId = null;
examService = null;
showLoginPanel();
} else {
JOptionPane.showMessageDialog(this, "删除失败:" + deleteResult);
}
}
}
}
private void createExamPanel() {
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40));
// 顶部信息栏
JPanel topPanel = new JPanel(new BorderLayout());
questionNumberLabel = new JLabel("", JLabel.LEFT);
questionNumberLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
topPanel.add(questionNumberLabel, BorderLayout.WEST);
panel.add(topPanel, BorderLayout.NORTH);
// 题目区域
JPanel questionPanel = new JPanel(new BorderLayout(10, 20));
questionPanel.setBorder(BorderFactory.createEmptyBorder(30, 50, 30, 50));
questionLabel = new JLabel("", JLabel.CENTER);
questionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
questionPanel.add(questionLabel, BorderLayout.NORTH);
// 选项区域
JPanel optionsPanel = new JPanel(new GridLayout(4, 1, 10, 10));
optionsPanel.setBorder(BorderFactory.createEmptyBorder(20, 100, 20, 100));
optionButtons = new JRadioButton[4];
optionGroup = new ButtonGroup();
for (int i = 0; i < 4; i++) {
optionButtons[i] = new JRadioButton();
optionButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 16));
optionGroup.add(optionButtons[i]);
optionsPanel.add(optionButtons[i]);
}
questionPanel.add(optionsPanel, BorderLayout.CENTER);
panel.add(questionPanel, BorderLayout.CENTER);
// 导航按钮区域
JPanel navPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
prevButton = createStyledButton("上一题");
prevButton.addActionListener(e -> goToPreviousQuestion());
navPanel.add(prevButton);
nextButton = createStyledButton("下一题");
nextButton.addActionListener(e -> goToNextQuestion());
navPanel.add(nextButton);
submitButton = createStyledButton("提交试卷");
submitButton.addActionListener(e -> submitExam());
navPanel.add(submitButton);
panel.add(navPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "Exam");
}
private void createResultPanel() {
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100));
resultLabel = new JLabel("", JLabel.CENTER);
resultLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
panel.add(resultLabel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 30, 20));
// 新增查看错题按钮
JButton reviewButton = createStyledButton("查看错题");
reviewButton.addActionListener(e -> showWrongQuestions());
buttonPanel.add(reviewButton);
JButton continueButton = createStyledButton("继续做题");
continueButton.addActionListener(e -> showGradeSelectionPanel());
buttonPanel.add(continueButton);
JButton exitButton = createStyledButton("退出程序");
exitButton.addActionListener(e -> System.exit(0));
buttonPanel.add(exitButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "Result");
}
private void createWrongQuestionsPanel() {
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40));
// 标题
JLabel titleLabel = new JLabel("错题回顾", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
panel.add(titleLabel, BorderLayout.NORTH);
// 错题内容区域(使用滚动面板)
JTextArea wrongQuestionsArea = new JTextArea();
wrongQuestionsArea.setFont(new Font("微软雅黑", Font.PLAIN, 14));
wrongQuestionsArea.setEditable(false);
wrongQuestionsArea.setLineWrap(true);
wrongQuestionsArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(wrongQuestionsArea);
scrollPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
panel.add(scrollPane, BorderLayout.CENTER);
// 存储错题文本区域引用
panel.putClientProperty("wrongQuestionsArea", wrongQuestionsArea);
// 返回按钮
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton backButton = createStyledButton("返回成绩");
backButton.addActionListener(e -> showResultPanel());
bottomPanel.add(backButton);
panel.add(bottomPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "WrongQuestions");
}
private void createPasswordChangePanel() {
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100));
JLabel titleLabel = new JLabel("修改密码", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
panel.add(titleLabel, BorderLayout.NORTH);
JPanel formPanel = new JPanel(new GridLayout(4, 2, 15, 15));
formPanel.setBorder(BorderFactory.createEmptyBorder(30, 80, 30, 80));
formPanel.add(new JLabel("邮箱:", JLabel.RIGHT));
JTextField emailField = new JTextField();
formPanel.add(emailField);
formPanel.add(new JLabel("原密码:", JLabel.RIGHT));
JPasswordField oldPasswordField = new JPasswordField();
formPanel.add(oldPasswordField);
formPanel.add(new JLabel("新密码:", JLabel.RIGHT));
JPasswordField newPasswordField = new JPasswordField();
formPanel.add(newPasswordField);
formPanel.add(new JLabel("确认新密码:", JLabel.RIGHT));
JPasswordField confirmPasswordField = new JPasswordField();
formPanel.add(confirmPasswordField);
panel.add(formPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton changeButton = createStyledButton("确认修改");
changeButton.addActionListener(e -> {
String email = emailField.getText();
String oldPassword = new String(oldPasswordField.getPassword());
String newPassword = new String(newPasswordField.getPassword());
String confirmPassword = new String(confirmPasswordField.getPassword());
changePassword(email, oldPassword, newPassword, confirmPassword);
});
buttonPanel.add(changeButton);
JButton backButton = createStyledButton("返回");
backButton.addActionListener(e -> showGradeSelectionPanel());
buttonPanel.add(backButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "PasswordChange");
}
private JButton createStyledButton(String text) {
JButton button = new JButton(text);
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setFocusPainted(false);
button.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
return button;
}
private JButton createGradeButton(String text) {
JButton button = new JButton(text);
button.setFont(new Font("微软雅黑", Font.BOLD, 18));
button.setFocusPainted(false);
button.setBorder(BorderFactory.createEmptyBorder(20, 0, 20, 0));
return button;
}
// 界面显示方法
private void showLoginPanel() {
loginIdField.setText("");
loginPasswordField.setText("");
cardLayout.show(mainPanel, "Login");
}
private void showRegisterPanel() {
regEmailField.setText("");
regCodeField.setText("");
regPasswordField.setText("");
regConfirmPasswordField.setText("");
regUserIdField.setText("");
cardLayout.show(mainPanel, "Register");
}
private void showGradeSelectionPanel() {
cardLayout.show(mainPanel, "GradeSelection");
}
private void showPasswordChangePanel() {
cardLayout.show(mainPanel, "PasswordChange");
}
private void showExamPanel() {
cardLayout.show(mainPanel, "Exam");
}
private void showResultPanel() {
cardLayout.show(mainPanel, "Result");
}
private void showWrongQuestionsPanel() {
cardLayout.show(mainPanel, "WrongQuestions");
}
// 业务逻辑方法
private void login() {
String id = loginIdField.getText().trim();
String password = new String(loginPasswordField.getPassword());
if (id.isEmpty() || password.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入用户名和密码");
return;
}
String result = userService.login(id, password);
if (result.equals("登陆成功")) {
currentUserId = id;
showGradeSelectionPanel();
} else {
JOptionPane.showMessageDialog(this, result);
}
}
private void sendVerificationCode() {
String email = regEmailField.getText().trim();
if (email.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入邮箱地址");
return;
}
String result = userService.register(email);
JOptionPane.showMessageDialog(this, result);
}
private void register() {
String email = regEmailField.getText().trim();
String code = regCodeField.getText().trim();
String password = new String(regPasswordField.getPassword());
String confirmPassword = new String(regConfirmPasswordField.getPassword());
String userId = regUserIdField.getText().trim();
if (email.isEmpty() || code.isEmpty() || password.isEmpty() || userId.isEmpty()) {
JOptionPane.showMessageDialog(this, "请填写所有字段");
return;
}
if (!password.equals(confirmPassword)) {
JOptionPane.showMessageDialog(this, "两次输入的密码不一致");
return;
}
String result = userService.check_register(email, code, password, userId);
JOptionPane.showMessageDialog(this, result);
if (result.equals("注册成功")) {
showLoginPanel();
}
}
private void startExam(String gradeType) {
String input = JOptionPane.showInputDialog(this,
"请输入" + gradeType + "题目数量:", "题目数量", JOptionPane.QUESTION_MESSAGE);
if (input == null) return;
try {
int numQuestions = Integer.parseInt(input.trim());
if (numQuestions < 10 || numQuestions > 30) {
JOptionPane.showMessageDialog(this, "题目数量范围是10-30");
return;
}
examService = new Exam_service(numQuestions, gradeType, currentUserId);
showCurrentQuestion();
showExamPanel();
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "请输入有效的数字");
}
}
private void showCurrentQuestion() {
Question question = examService.get_now_question();
if (question != null) {
int currentIndex = examService.get_now_index();
int totalQuestions = examService.get_paper().size();
questionNumberLabel.setText(String.format("第 %d 题 / 共 %d 题",
currentIndex + 1, totalQuestions));
questionLabel.setText("<html><div style='text-align: center; font-size: 16px;'>" +
question.toString() + "</div></html>");
for (int i = 0; i < 4; i++) {
String optionText = question.getOptions(i);
optionButtons[i].setText((char)('A' + i) + ": " + optionText);
}
Integer userAnswer = examService.get_user_answer(currentIndex);
optionGroup.clearSelection();
if (userAnswer != null && userAnswer >= 0 && userAnswer < 4) {
optionButtons[userAnswer].setSelected(true);
}
updateNavigationButtons();
}
}
private void updateNavigationButtons() {
int currentIndex = examService.get_now_index();
int totalQuestions = examService.get_paper().size();
prevButton.setEnabled(currentIndex > 0);
nextButton.setEnabled(currentIndex < totalQuestions - 1);
submitButton.setEnabled(currentIndex == totalQuestions - 1);
}
private void goToPreviousQuestion() {
if (examService.pre_one()) {
showCurrentQuestion();
}
}
private void goToNextQuestion() {
int selectedOption = getSelectedOption();
if (selectedOption == -1) {
JOptionPane.showMessageDialog(this, "请选择一个答案");
return;
}
boolean hasNext = examService.next_one(selectedOption);
if (hasNext) {
showCurrentQuestion();
} else {
showExamResult();
}
}
private void submitExam() {
int selectedOption = getSelectedOption();
if (selectedOption == -1) {
JOptionPane.showMessageDialog(this, "请选择一个答案");
return;
}
examService.next_one(selectedOption);
showExamResult();
}
private int getSelectedOption() {
for (int i = 0; i < 4; i++) {
if (optionButtons[i].isSelected()) {
return i;
}
}
return -1;
}
private void showExamResult() {
Exam_result result = examService.calculate_result();
String resultText = String.format(
"<html><div style='text-align: center;'>" +
"<p>考试完成!</p>" +
"<p>%s数学测试</p>" +
"<p>总题数: %d</p>" +
"<p>答对题数: %d</p>" +
"<p>得分: %.1f</p>" +
"<p>用时: %s</p>" +
"<p>正确率: %s</p>" +
"</div></html>",
result.getExamType(),
result.getTotalQuestions(),
result.getCorrectAnswers(),
result.getScore(),
result.get_time(),
result.getCorrectRate()
);
resultLabel.setText(resultText);
showResultPanel();
}
// 新增:查看错题功能
// 修正:查看错题功能 - 简洁显示
private void showWrongQuestions() {
// 获取考试结果
Exam_result result = examService.calculate_result();
java.util.List<Integer> wrongQuestionIndices = result.getWrongQuestions();
if (wrongQuestionIndices.isEmpty()) {
JOptionPane.showMessageDialog(this, "恭喜!本次考试没有错题!");
return;
}
// 获取错题面板和文本区域
JPanel wrongQuestionsPanel = (JPanel) mainPanel.getComponent(5); // 第6个面板是错题面板
JTextArea wrongQuestionsArea = (JTextArea) ((JScrollPane) wrongQuestionsPanel.getComponent(1)).getViewport().getView();
// 构建错题显示内容
StringBuilder sb = new StringBuilder();
sb.append("本次考试共有 ").append(wrongQuestionIndices.size()).append(" 道错题:\n\n");
java.util.ArrayList<Question> paper = examService.get_paper();
for (int i = 0; i < wrongQuestionIndices.size(); i++) {
int questionIndex = wrongQuestionIndices.get(i);
Question question = paper.get(questionIndex);
// 只显示一个题号
sb.append("第 ").append(questionIndex + 1).append(" 题:");
sb.append(question.toString()).append("\n");
// 显示所有选项,在正确答案后打勾
sb.append("选项:\n");
for (int j = 0; j < 4; j++) {
char optionChar = (char) ('A' + j);
sb.append(" ").append(optionChar).append(". ").append(question.getOptions(j));
// 标记正确答案
if (question.getOptions(j).equals(question.getAnswer())) {
sb.append(" √");
}
// 标记用户选择的错误答案
Integer userAnswer = examService.get_user_answer(questionIndex);
if (userAnswer != null && userAnswer == j && !question.getOptions(j).equals(question.getAnswer())) {
sb.append(" X");
}
sb.append("\n");
}
sb.append("\n");
sb.append("-".repeat(50)).append("\n\n");
}
wrongQuestionsArea.setText(sb.toString());
showWrongQuestionsPanel();
}
private void changePassword(String email, String oldPassword, String newPassword, String confirmPassword) {
if (email.isEmpty() || oldPassword.isEmpty() || newPassword.isEmpty()) {
JOptionPane.showMessageDialog(this, "请填写所有字段");
return;
}
if (!newPassword.equals(confirmPassword)) {
JOptionPane.showMessageDialog(this, "两次输入的新密码不一致");
return;
}
String result = userService.change_pwd(email, oldPassword, newPassword);
JOptionPane.showMessageDialog(this, result);
if (result.equals("修改成功")) {
showGradeSelectionPanel();
}
}
private void logout() {
currentUserId = null;
examService = null;
showLoginPanel();
}
public void exitchoice(){
System.exit(0);
}
// 主函数
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new MainFrame().setVisible(true);
});
}
}