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/MainFrame.java

558 lines
20 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 javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MainFrame extends JFrame {
private User_service userService;
private Exam_service examService;
private CardLayout cardLayout;
private JPanel mainPanel;
// 登录面板组件
private JTextField loginEmailField;
private JPasswordField loginPasswordField;
// 注册面板组件
private JTextField regEmailField;
private JTextField regCodeField;
private JPasswordField regPasswordField;
private JPasswordField regConfirmPasswordField;
// 考试面板组件
private JLabel questionLabel;
private JRadioButton[] optionButtons;
private ButtonGroup optionGroup;
private JLabel questionNumberLabel;
private JLabel examInfoLabel;
// 结果面板组件
private JLabel resultLabel;
public MainFrame() {
userService = new User_service();
examService = new Exam_service();
initializeUI();
}
private void initializeUI() {
setTitle("数学学习软件");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
setLocationRelativeTo(null);
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
createLoginPanel();
createRegisterPanel();
createGradeSelectionPanel();
createExamPanel();
createResultPanel();
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.RIGHT));
loginEmailField = new JTextField();
formPanel.add(loginEmailField);
formPanel.add(new JLabel("密码:", JLabel.RIGHT));
loginPasswordField = new JPasswordField();
formPanel.add(loginPasswordField);
panel.add(formPanel, BorderLayout.CENTER);
// 按钮区域
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton loginButton = createStyledButton("登录", new Color(70, 130, 180));
loginButton.addActionListener(e -> login());
buttonPanel.add(loginButton);
JButton registerButton = createStyledButton("注册账号", new Color(60, 179, 113));
registerButton.addActionListener(e -> showRegisterPanel());
buttonPanel.add(registerButton);
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.RIGHT));
regEmailField = new JTextField();
formPanel.add(regEmailField);
formPanel.add(new JLabel("验证码:", JLabel.RIGHT));
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.RIGHT));
regPasswordField = new JPasswordField();
formPanel.add(regPasswordField);
formPanel.add(new JLabel("确认密码:", JLabel.RIGHT));
regConfirmPasswordField = new JPasswordField();
formPanel.add(regConfirmPasswordField);
panel.add(formPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton registerButton = createStyledButton("注册", new Color(60, 179, 113));
registerButton.addActionListener(e -> register());
buttonPanel.add(registerButton);
JButton backButton = createStyledButton("返回登录", new Color(192, 192, 192));
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("小学", new Color(255, 182, 193));
primaryButton.addActionListener(e -> startExam(0, "小学"));
gradePanel.add(primaryButton);
JButton juniorButton = createGradeButton("初中", new Color(135, 206, 250));
juniorButton.addActionListener(e -> startExam(1, "初中"));
gradePanel.add(juniorButton);
JButton seniorButton = createGradeButton("高中", new Color(152, 251, 152));
seniorButton.addActionListener(e -> startExam(2, "高中"));
gradePanel.add(seniorButton);
panel.add(gradePanel, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton changePasswordButton = createStyledButton("修改密码", new Color(255, 165, 0));
changePasswordButton.addActionListener(e -> showPasswordChangePanel());
bottomPanel.add(changePasswordButton);
JButton logoutButton = createStyledButton("退出登录", new Color(220, 20, 60));
logoutButton.addActionListener(e -> logout());
bottomPanel.add(logoutButton);
panel.add(bottomPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "GradeSelection");
}
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));
examInfoLabel = new JLabel("", JLabel.RIGHT);
examInfoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
topPanel.add(questionNumberLabel, BorderLayout.WEST);
topPanel.add(examInfoLabel, BorderLayout.EAST);
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();
String[] optionLabels = {"A. ", "B. ", "C. ", "D. "};
for (int i = 0; i < 4; i++) {
JPanel optionPanel = new JPanel(new BorderLayout());
optionButtons[i] = new JRadioButton();
optionButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 16));
optionGroup.add(optionButtons[i]);
JLabel optionLabel = new JLabel(optionLabels[i]);
optionLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
optionLabel.setPreferredSize(new Dimension(30, 25));
optionPanel.add(optionLabel, BorderLayout.WEST);
optionPanel.add(optionButtons[i], BorderLayout.CENTER);
optionsPanel.add(optionPanel);
}
questionPanel.add(optionsPanel, BorderLayout.CENTER);
panel.add(questionPanel, BorderLayout.CENTER);
// 提交按钮
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton submitButton = createStyledButton("提交答案", new Color(70, 130, 180));
submitButton.addActionListener(e -> submitAnswer());
bottomPanel.add(submitButton);
panel.add(bottomPanel, 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 continueButton = createStyledButton("继续做题", new Color(60, 179, 113));
continueButton.addActionListener(e -> showGradeSelectionPanel());
JButton exitButton = createStyledButton("退出程序", new Color(220, 20, 60));
exitButton.addActionListener(e -> System.exit(0));
buttonPanel.add(continueButton);
buttonPanel.add(exitButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "Result");
}
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));
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("确认修改", new Color(60, 179, 113));
changeButton.addActionListener(e -> {
String oldPassword = new String(oldPasswordField.getPassword());
String newPassword = new String(newPasswordField.getPassword());
String confirmPassword = new String(confirmPasswordField.getPassword());
changePassword(oldPassword, newPassword, confirmPassword);
});
buttonPanel.add(changeButton);
JButton backButton = createStyledButton("返回", new Color(192, 192, 192));
backButton.addActionListener(e -> showGradeSelectionPanel());
buttonPanel.add(backButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "PasswordChange");
}
// 工具方法:创建样式化按钮
private JButton createStyledButton(String text, Color bgColor) {
JButton button = new JButton(text);
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setBackground(bgColor);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
return button;
}
// 工具方法:创建年级选择按钮
private JButton createGradeButton(String text, Color bgColor) {
JButton button = new JButton(text);
button.setFont(new Font("微软雅黑", Font.BOLD, 18));
button.setBackground(bgColor);
button.setForeground(Color.BLACK);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createEmptyBorder(20, 0, 20, 0));
return button;
}
// 界面显示方法
private void showLoginPanel() {
loginEmailField.setText("");
loginPasswordField.setText("");
cardLayout.show(mainPanel, "Login");
}
private void showRegisterPanel() {
regEmailField.setText("");
regCodeField.setText("");
regPasswordField.setText("");
regConfirmPasswordField.setText("");
cardLayout.show(mainPanel, "Register");
}
private void showGradeSelectionPanel() {
cardLayout.show(mainPanel, "GradeSelection");
}
private void showPasswordChangePanel() {
cardLayout.show(mainPanel, "PasswordChange");
}
// 业务逻辑方法
private void login() {
String email = loginEmailField.getText().trim();
String password = new String(loginPasswordField.getPassword());
if (email.isEmpty() || password.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入邮箱和密码");
return;
}
if (userService.login(email, password)) {
showGradeSelectionPanel();
} else {
JOptionPane.showMessageDialog(this, "登录失败,请检查邮箱和密码");
}
}
private void sendVerificationCode() {
String email = regEmailField.getText().trim();
if (email.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入邮箱地址");
return;
}
if (userService.sendVerificationCode(email)) {
JOptionPane.showMessageDialog(this, "验证码已发送到您的邮箱,请查收");
} else {
JOptionPane.showMessageDialog(this, "验证码发送失败,请检查邮箱地址或稍后重试");
}
}
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());
if (email.isEmpty() || code.isEmpty() || password.isEmpty()) {
JOptionPane.showMessageDialog(this, "请填写所有字段");
return;
}
if (!password.equals(confirmPassword)) {
JOptionPane.showMessageDialog(this, "两次输入的密码不一致");
return;
}
if (userService.completeRegistration(email, code, password)) {
JOptionPane.showMessageDialog(this, "注册成功,请登录");
showLoginPanel();
} else {
JOptionPane.showMessageDialog(this, "注册失败,请检查验证码和密码格式\n密码要求6-10位包含大小写字母和数字");
}
}
private void startExam(int gradeLevel, String gradeName) {
String input = JOptionPane.showInputDialog(this,
"请输入" + gradeName + "题目数量:", "题目数量", JOptionPane.QUESTION_MESSAGE);
if (input == null) return; // 用户取消
try {
int count = Integer.parseInt(input.trim());
if (count <= 0) {
JOptionPane.showMessageDialog(this, "题目数量必须大于0");
return;
}
if (count > 100) {
JOptionPane.showMessageDialog(this, "题目数量不能超过100");
return;
}
examService.startExam(gradeLevel, count);
showNextQuestion();
cardLayout.show(mainPanel, "Exam");
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "请输入有效的数字");
}
}
private void showNextQuestion() {
Question question = examService.getCurrentQuestion();
if (question != null) {
questionNumberLabel.setText(String.format("第 %d 题 / 共 %d 题",
examService.getCurrentQuestionNumber(),
examService.getTotalQuestions()));
examInfoLabel.setText(getGradeName(question.getGradeLevel()) + "数学题");
questionLabel.setText("<html><div style='text-align: center;'>" + question.getQuestionText() + "</div></html>");
java.util.List<String> options = question.getOptions();
String[] optionLetters = {"A", "B", "C", "D"};
for (int i = 0; i < 4; i++) {
optionButtons[i].setText(optionLetters[i] + ". " + options.get(i));
}
optionGroup.clearSelection();
}
}
private String getGradeName(int gradeLevel) {
switch (gradeLevel) {
case 0: return "小学";
case 1: return "初中";
case 2: return "高中";
default: return "未知";
}
}
private void submitAnswer() {
int selectedOption = -1;
for (int i = 0; i < 4; i++) {
if (optionButtons[i].isSelected()) {
selectedOption = i;
break;
}
}
if (selectedOption == -1) {
JOptionPane.showMessageDialog(this, "请选择一个答案");
return;
}
examService.submitAnswer(selectedOption);
if (examService.hasNextQuestion()) {
showNextQuestion();
} else {
showResult();
}
}
private void showResult() {
ExamResult result = examService.getExamResult();
String gradeName = getGradeName(result.getGradeLevel());
String resultText = String.format(
"<html><div style='text-align: center;'>" +
"<h2>%s数学测试完成</h2>" +
"<h3>%s</h3>" +
"<p>正确题数: %d / %d</p>" +
"<p>得分: %.1f</p>" +
"</div></html>",
gradeName, result.toString(), result.getCorrectAnswers(),
result.getTotalQuestions(), result.getScore()
);
resultLabel.setText(resultText);
cardLayout.show(mainPanel, "Result");
}
private void changePassword(String oldPassword, String newPassword, String confirmPassword) {
if (oldPassword.isEmpty() || newPassword.isEmpty() || confirmPassword.isEmpty()) {
JOptionPane.showMessageDialog(this, "请填写所有字段");
return;
}
if (!newPassword.equals(confirmPassword)) {
JOptionPane.showMessageDialog(this, "两次输入的新密码不一致");
return;
}
if (userService.changePassword(oldPassword, newPassword)) {
JOptionPane.showMessageDialog(this, "密码修改成功");
showGradeSelectionPanel();
} else {
JOptionPane.showMessageDialog(this, "密码修改失败,请检查原密码和新密码格式\n新密码要求6-10位包含大小写字母和数字");
}
}
private void logout() {
userService.logout();
showLoginPanel();
}
public static void main(String[] args) {
// 设置系统样式
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel());
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(() -> {
MainFrame frame = new MainFrame();
frame.setVisible(true);
});
}
}