|
|
|
|
@ -0,0 +1,983 @@
|
|
|
|
|
import javax.swing.*;
|
|
|
|
|
import java.awt.*;
|
|
|
|
|
import java.awt.event.ActionEvent;
|
|
|
|
|
import java.awt.event.ActionListener;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
// 邮件功能暂时使用模拟实现,不需要真实的邮件库
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.nio.file.*;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 带UI的小初高数学学习软件 - 主程序
|
|
|
|
|
* 基于原有命令行版本改写的GUI版本
|
|
|
|
|
*/
|
|
|
|
|
public class MathLearningApp extends JFrame {
|
|
|
|
|
private CardLayout cardLayout;
|
|
|
|
|
private JPanel mainPanel;
|
|
|
|
|
|
|
|
|
|
// 用户管理
|
|
|
|
|
private Map<String, RegisteredUser> registeredUsers;
|
|
|
|
|
private RegisteredUser currentUser;
|
|
|
|
|
|
|
|
|
|
// 题目管理
|
|
|
|
|
private MathQuestionGenerator questionGenerator;
|
|
|
|
|
private List<MultipleChoiceQuestion> currentQuestions;
|
|
|
|
|
private int currentQuestionIndex;
|
|
|
|
|
private int correctAnswers;
|
|
|
|
|
private String currentDifficulty;
|
|
|
|
|
|
|
|
|
|
// 界面组件
|
|
|
|
|
private JTextField emailField;
|
|
|
|
|
private JTextField verificationCodeField;
|
|
|
|
|
private JPasswordField passwordField;
|
|
|
|
|
private JPasswordField confirmPasswordField;
|
|
|
|
|
private JPasswordField oldPasswordField;
|
|
|
|
|
private JLabel questionLabel;
|
|
|
|
|
private ButtonGroup answerGroup;
|
|
|
|
|
private JRadioButton[] answerButtons;
|
|
|
|
|
private JLabel scoreLabel;
|
|
|
|
|
|
|
|
|
|
public MathLearningApp() {
|
|
|
|
|
initializeData();
|
|
|
|
|
initializeGUI();
|
|
|
|
|
loadUserData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 初始化数据
|
|
|
|
|
*/
|
|
|
|
|
private void initializeData() {
|
|
|
|
|
registeredUsers = new HashMap<>();
|
|
|
|
|
questionGenerator = new MathQuestionGenerator();
|
|
|
|
|
currentQuestions = new ArrayList<>();
|
|
|
|
|
currentQuestionIndex = 0;
|
|
|
|
|
correctAnswers = 0;
|
|
|
|
|
answerButtons = new JRadioButton[4];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 初始化GUI界面
|
|
|
|
|
*/
|
|
|
|
|
private void initializeGUI() {
|
|
|
|
|
setTitle("小初高数学学习软件");
|
|
|
|
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
|
|
|
setSize(800, 600);
|
|
|
|
|
setLocationRelativeTo(null);
|
|
|
|
|
|
|
|
|
|
cardLayout = new CardLayout();
|
|
|
|
|
mainPanel = new JPanel(cardLayout);
|
|
|
|
|
|
|
|
|
|
// 创建各个界面
|
|
|
|
|
createWelcomePanel();
|
|
|
|
|
createRegisterPanel();
|
|
|
|
|
createLoginPanel();
|
|
|
|
|
createPasswordSetupPanel();
|
|
|
|
|
createDifficultySelectionPanel();
|
|
|
|
|
createQuestionPanel();
|
|
|
|
|
createScorePanel();
|
|
|
|
|
createPasswordChangePanel();
|
|
|
|
|
|
|
|
|
|
add(mainPanel);
|
|
|
|
|
|
|
|
|
|
// 显示欢迎界面
|
|
|
|
|
cardLayout.show(mainPanel, "WELCOME");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建欢迎界面
|
|
|
|
|
*/
|
|
|
|
|
private void createWelcomePanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 创建渐变背景
|
|
|
|
|
GradientPaint gradient = new GradientPaint(0, 0, new Color(135, 206, 250),
|
|
|
|
|
0, getHeight(), new Color(240, 248, 255));
|
|
|
|
|
g2.setPaint(gradient);
|
|
|
|
|
g2.fillRect(0, 0, getWidth(), getHeight());
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 标题面板
|
|
|
|
|
JPanel titlePanel = new JPanel();
|
|
|
|
|
titlePanel.setOpaque(false);
|
|
|
|
|
titlePanel.setBorder(BorderFactory.createEmptyBorder(80, 0, 50, 0));
|
|
|
|
|
|
|
|
|
|
JLabel titleLabel = new JLabel("小初高数学学习软件", JLabel.CENTER);
|
|
|
|
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 36));
|
|
|
|
|
titleLabel.setForeground(new Color(25, 25, 112));
|
|
|
|
|
|
|
|
|
|
JLabel subtitleLabel = new JLabel("让数学学习变得更有趣", JLabel.CENTER);
|
|
|
|
|
subtitleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
|
|
|
subtitleLabel.setForeground(new Color(70, 130, 180));
|
|
|
|
|
subtitleLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
titlePanel.setLayout(new BoxLayout(titlePanel, BoxLayout.Y_AXIS));
|
|
|
|
|
titlePanel.add(titleLabel);
|
|
|
|
|
titlePanel.add(subtitleLabel);
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonPanel = new JPanel();
|
|
|
|
|
buttonPanel.setOpaque(false);
|
|
|
|
|
buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 30, 20));
|
|
|
|
|
|
|
|
|
|
JButton registerButton = createStyledButton("用户注册", new Color(60, 179, 113));
|
|
|
|
|
JButton loginButton = createStyledButton("用户登录", new Color(70, 130, 180));
|
|
|
|
|
|
|
|
|
|
registerButton.addActionListener(e -> cardLayout.show(mainPanel, "REGISTER"));
|
|
|
|
|
loginButton.addActionListener(e -> cardLayout.show(mainPanel, "LOGIN"));
|
|
|
|
|
|
|
|
|
|
buttonPanel.add(registerButton);
|
|
|
|
|
buttonPanel.add(loginButton);
|
|
|
|
|
|
|
|
|
|
// 底部信息
|
|
|
|
|
JLabel footerLabel = new JLabel("© 2025 数学学习软件 - 专业的数学学习平台", JLabel.CENTER);
|
|
|
|
|
footerLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
|
|
|
|
|
footerLabel.setForeground(new Color(100, 100, 100));
|
|
|
|
|
footerLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 30, 0));
|
|
|
|
|
|
|
|
|
|
panel.add(titlePanel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(buttonPanel, BorderLayout.CENTER);
|
|
|
|
|
panel.add(footerLabel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "WELCOME");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建注册界面
|
|
|
|
|
*/
|
|
|
|
|
private void createRegisterPanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 创建渐变背景
|
|
|
|
|
GradientPaint gradient = new GradientPaint(0, 0, new Color(250, 250, 250),
|
|
|
|
|
0, getHeight(), new Color(240, 248, 255));
|
|
|
|
|
g2.setPaint(gradient);
|
|
|
|
|
g2.fillRect(0, 0, getWidth(), getHeight());
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 标题面板
|
|
|
|
|
JPanel titlePanel = new JPanel();
|
|
|
|
|
titlePanel.setOpaque(false);
|
|
|
|
|
titlePanel.setBorder(BorderFactory.createEmptyBorder(40, 0, 30, 0));
|
|
|
|
|
|
|
|
|
|
JLabel titleLabel = new JLabel("用户注册", JLabel.CENTER);
|
|
|
|
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 28));
|
|
|
|
|
titleLabel.setForeground(new Color(25, 25, 112));
|
|
|
|
|
|
|
|
|
|
JLabel subtitleLabel = new JLabel("请填写您的邮箱信息完成注册", JLabel.CENTER);
|
|
|
|
|
subtitleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
subtitleLabel.setForeground(new Color(100, 100, 100));
|
|
|
|
|
subtitleLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
titlePanel.setLayout(new BoxLayout(titlePanel, BoxLayout.Y_AXIS));
|
|
|
|
|
titlePanel.add(titleLabel);
|
|
|
|
|
titlePanel.add(subtitleLabel);
|
|
|
|
|
|
|
|
|
|
// 表单面板 - 添加卡片样式
|
|
|
|
|
JPanel formContainer = new JPanel();
|
|
|
|
|
formContainer.setOpaque(false);
|
|
|
|
|
formContainer.setBorder(BorderFactory.createEmptyBorder(20, 50, 20, 50));
|
|
|
|
|
|
|
|
|
|
JPanel formPanel = new JPanel(new GridBagLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 卡片阴影
|
|
|
|
|
g2.setColor(new Color(0, 0, 0, 20));
|
|
|
|
|
g2.fillRoundRect(5, 5, getWidth()-5, getHeight()-5, 20, 20);
|
|
|
|
|
|
|
|
|
|
// 卡片背景
|
|
|
|
|
g2.setColor(Color.WHITE);
|
|
|
|
|
g2.fillRoundRect(0, 0, getWidth()-5, getHeight()-5, 20, 20);
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
formPanel.setBorder(BorderFactory.createEmptyBorder(30, 40, 30, 40));
|
|
|
|
|
|
|
|
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
|
|
|
|
gbc.insets = new Insets(15, 10, 15, 10);
|
|
|
|
|
|
|
|
|
|
// 邮箱输入
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.EAST;
|
|
|
|
|
JLabel emailLabel = new JLabel("邮箱地址:");
|
|
|
|
|
emailLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
|
|
|
|
emailLabel.setForeground(new Color(70, 70, 70));
|
|
|
|
|
formPanel.add(emailLabel, gbc);
|
|
|
|
|
|
|
|
|
|
gbc.gridx = 1; gbc.anchor = GridBagConstraints.WEST;
|
|
|
|
|
emailField = new JTextField(20);
|
|
|
|
|
emailField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
emailField.setBorder(BorderFactory.createCompoundBorder(
|
|
|
|
|
BorderFactory.createLineBorder(new Color(200, 200, 200), 1),
|
|
|
|
|
BorderFactory.createEmptyBorder(8, 12, 8, 12)
|
|
|
|
|
));
|
|
|
|
|
formPanel.add(emailField, gbc);
|
|
|
|
|
|
|
|
|
|
// 发送验证码按钮
|
|
|
|
|
gbc.gridx = 2;
|
|
|
|
|
JButton sendCodeButton = createStyledButton("发送验证码", new Color(255, 140, 0));
|
|
|
|
|
sendCodeButton.addActionListener(this::sendVerificationCode);
|
|
|
|
|
formPanel.add(sendCodeButton, gbc);
|
|
|
|
|
|
|
|
|
|
// 验证码输入
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 1; gbc.anchor = GridBagConstraints.EAST;
|
|
|
|
|
JLabel codeLabel = new JLabel("验证码:");
|
|
|
|
|
codeLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
|
|
|
|
codeLabel.setForeground(new Color(70, 70, 70));
|
|
|
|
|
formPanel.add(codeLabel, gbc);
|
|
|
|
|
|
|
|
|
|
gbc.gridx = 1; gbc.anchor = GridBagConstraints.WEST;
|
|
|
|
|
verificationCodeField = new JTextField(20);
|
|
|
|
|
verificationCodeField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
verificationCodeField.setBorder(BorderFactory.createCompoundBorder(
|
|
|
|
|
BorderFactory.createLineBorder(new Color(200, 200, 200), 1),
|
|
|
|
|
BorderFactory.createEmptyBorder(8, 12, 8, 12)
|
|
|
|
|
));
|
|
|
|
|
formPanel.add(verificationCodeField, gbc);
|
|
|
|
|
|
|
|
|
|
formContainer.add(formPanel);
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 30));
|
|
|
|
|
buttonPanel.setOpaque(false);
|
|
|
|
|
|
|
|
|
|
JButton registerButton = createStyledButton("注册", new Color(60, 179, 113));
|
|
|
|
|
JButton backButton = createStyledButton("返回", new Color(128, 128, 128));
|
|
|
|
|
|
|
|
|
|
registerButton.addActionListener(this::handleRegister);
|
|
|
|
|
backButton.addActionListener(e -> cardLayout.show(mainPanel, "WELCOME"));
|
|
|
|
|
|
|
|
|
|
buttonPanel.add(registerButton);
|
|
|
|
|
buttonPanel.add(backButton);
|
|
|
|
|
|
|
|
|
|
panel.add(titlePanel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(formContainer, BorderLayout.CENTER);
|
|
|
|
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "REGISTER");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建登录界面
|
|
|
|
|
*/
|
|
|
|
|
private void createLoginPanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 创建渐变背景
|
|
|
|
|
GradientPaint gradient = new GradientPaint(0, 0, new Color(250, 250, 250),
|
|
|
|
|
0, getHeight(), new Color(240, 248, 255));
|
|
|
|
|
g2.setPaint(gradient);
|
|
|
|
|
g2.fillRect(0, 0, getWidth(), getHeight());
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 标题面板
|
|
|
|
|
JPanel titlePanel = new JPanel();
|
|
|
|
|
titlePanel.setOpaque(false);
|
|
|
|
|
titlePanel.setBorder(BorderFactory.createEmptyBorder(60, 0, 40, 0));
|
|
|
|
|
|
|
|
|
|
JLabel titleLabel = new JLabel("用户登录", JLabel.CENTER);
|
|
|
|
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 28));
|
|
|
|
|
titleLabel.setForeground(new Color(25, 25, 112));
|
|
|
|
|
|
|
|
|
|
JLabel subtitleLabel = new JLabel("请输入您的账户信息", JLabel.CENTER);
|
|
|
|
|
subtitleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
subtitleLabel.setForeground(new Color(100, 100, 100));
|
|
|
|
|
subtitleLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
titlePanel.setLayout(new BoxLayout(titlePanel, BoxLayout.Y_AXIS));
|
|
|
|
|
titlePanel.add(titleLabel);
|
|
|
|
|
titlePanel.add(subtitleLabel);
|
|
|
|
|
|
|
|
|
|
// 表单面板 - 添加卡片样式
|
|
|
|
|
JPanel formContainer = new JPanel();
|
|
|
|
|
formContainer.setOpaque(false);
|
|
|
|
|
formContainer.setBorder(BorderFactory.createEmptyBorder(20, 80, 20, 80));
|
|
|
|
|
|
|
|
|
|
JPanel formPanel = new JPanel(new GridBagLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 卡片阴影
|
|
|
|
|
g2.setColor(new Color(0, 0, 0, 20));
|
|
|
|
|
g2.fillRoundRect(5, 5, getWidth()-5, getHeight()-5, 20, 20);
|
|
|
|
|
|
|
|
|
|
// 卡片背景
|
|
|
|
|
g2.setColor(Color.WHITE);
|
|
|
|
|
g2.fillRoundRect(0, 0, getWidth()-5, getHeight()-5, 20, 20);
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
formPanel.setBorder(BorderFactory.createEmptyBorder(40, 50, 40, 50));
|
|
|
|
|
|
|
|
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
|
|
|
|
gbc.insets = new Insets(20, 10, 20, 10);
|
|
|
|
|
|
|
|
|
|
// 用户名(邮箱)输入
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.EAST;
|
|
|
|
|
JLabel emailLabel = new JLabel("用户名(邮箱):");
|
|
|
|
|
emailLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
|
|
|
|
emailLabel.setForeground(new Color(70, 70, 70));
|
|
|
|
|
formPanel.add(emailLabel, gbc);
|
|
|
|
|
|
|
|
|
|
gbc.gridx = 1; gbc.anchor = GridBagConstraints.WEST;
|
|
|
|
|
JTextField loginEmailField = new JTextField(25);
|
|
|
|
|
loginEmailField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
loginEmailField.setBorder(BorderFactory.createCompoundBorder(
|
|
|
|
|
BorderFactory.createLineBorder(new Color(200, 200, 200), 1),
|
|
|
|
|
BorderFactory.createEmptyBorder(10, 15, 10, 15)
|
|
|
|
|
));
|
|
|
|
|
formPanel.add(loginEmailField, gbc);
|
|
|
|
|
|
|
|
|
|
// 密码输入
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 1; gbc.anchor = GridBagConstraints.EAST;
|
|
|
|
|
JLabel passwordLabel = new JLabel("密码:");
|
|
|
|
|
passwordLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
|
|
|
|
passwordLabel.setForeground(new Color(70, 70, 70));
|
|
|
|
|
formPanel.add(passwordLabel, gbc);
|
|
|
|
|
|
|
|
|
|
gbc.gridx = 1; gbc.anchor = GridBagConstraints.WEST;
|
|
|
|
|
JPasswordField loginPasswordField = new JPasswordField(25);
|
|
|
|
|
loginPasswordField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
loginPasswordField.setBorder(BorderFactory.createCompoundBorder(
|
|
|
|
|
BorderFactory.createLineBorder(new Color(200, 200, 200), 1),
|
|
|
|
|
BorderFactory.createEmptyBorder(10, 15, 10, 15)
|
|
|
|
|
));
|
|
|
|
|
formPanel.add(loginPasswordField, gbc);
|
|
|
|
|
|
|
|
|
|
formContainer.add(formPanel);
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 40));
|
|
|
|
|
buttonPanel.setOpaque(false);
|
|
|
|
|
|
|
|
|
|
JButton loginButton = createStyledButton("登录", new Color(70, 130, 180));
|
|
|
|
|
JButton backButton = createStyledButton("返回", new Color(128, 128, 128));
|
|
|
|
|
|
|
|
|
|
loginButton.addActionListener(e -> handleLogin(loginEmailField.getText(),
|
|
|
|
|
new String(loginPasswordField.getPassword())));
|
|
|
|
|
backButton.addActionListener(e -> cardLayout.show(mainPanel, "WELCOME"));
|
|
|
|
|
|
|
|
|
|
buttonPanel.add(loginButton);
|
|
|
|
|
buttonPanel.add(backButton);
|
|
|
|
|
|
|
|
|
|
panel.add(titlePanel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(formContainer, BorderLayout.CENTER);
|
|
|
|
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "LOGIN");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建密码设置界面
|
|
|
|
|
*/
|
|
|
|
|
private void createPasswordSetupPanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 创建渐变背景
|
|
|
|
|
GradientPaint gradient = new GradientPaint(0, 0, new Color(250, 250, 250),
|
|
|
|
|
0, getHeight(), new Color(240, 248, 255));
|
|
|
|
|
g2.setPaint(gradient);
|
|
|
|
|
g2.fillRect(0, 0, getWidth(), getHeight());
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 标题面板
|
|
|
|
|
JPanel titlePanel = new JPanel();
|
|
|
|
|
titlePanel.setOpaque(false);
|
|
|
|
|
titlePanel.setBorder(BorderFactory.createEmptyBorder(50, 0, 30, 0));
|
|
|
|
|
|
|
|
|
|
JLabel titleLabel = new JLabel("设置密码", JLabel.CENTER);
|
|
|
|
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 28));
|
|
|
|
|
titleLabel.setForeground(new Color(25, 25, 112));
|
|
|
|
|
|
|
|
|
|
JLabel subtitleLabel = new JLabel("请为您的账户设置安全密码", JLabel.CENTER);
|
|
|
|
|
subtitleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
subtitleLabel.setForeground(new Color(100, 100, 100));
|
|
|
|
|
subtitleLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
// 提示信息
|
|
|
|
|
JLabel hintLabel = new JLabel("<html><center>密码要求:6-10位,必须包含大小写字母和数字</center></html>", JLabel.CENTER);
|
|
|
|
|
hintLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
|
|
|
|
|
hintLabel.setForeground(new Color(150, 150, 150));
|
|
|
|
|
hintLabel.setBorder(BorderFactory.createEmptyBorder(15, 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
titlePanel.setLayout(new BoxLayout(titlePanel, BoxLayout.Y_AXIS));
|
|
|
|
|
titlePanel.add(titleLabel);
|
|
|
|
|
titlePanel.add(subtitleLabel);
|
|
|
|
|
titlePanel.add(hintLabel);
|
|
|
|
|
|
|
|
|
|
// 表单面板 - 添加卡片样式
|
|
|
|
|
JPanel formContainer = new JPanel();
|
|
|
|
|
formContainer.setOpaque(false);
|
|
|
|
|
formContainer.setBorder(BorderFactory.createEmptyBorder(30, 80, 30, 80));
|
|
|
|
|
|
|
|
|
|
JPanel formPanel = new JPanel(new GridBagLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 卡片阴影
|
|
|
|
|
g2.setColor(new Color(0, 0, 0, 20));
|
|
|
|
|
g2.fillRoundRect(5, 5, getWidth()-5, getHeight()-5, 20, 20);
|
|
|
|
|
|
|
|
|
|
// 卡片背景
|
|
|
|
|
g2.setColor(Color.WHITE);
|
|
|
|
|
g2.fillRoundRect(0, 0, getWidth()-5, getHeight()-5, 20, 20);
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
formPanel.setBorder(BorderFactory.createEmptyBorder(40, 50, 40, 50));
|
|
|
|
|
|
|
|
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
|
|
|
|
gbc.insets = new Insets(20, 10, 20, 10);
|
|
|
|
|
|
|
|
|
|
// 密码输入
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.EAST;
|
|
|
|
|
JLabel passwordLabel = new JLabel("输入密码:");
|
|
|
|
|
passwordLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
|
|
|
|
passwordLabel.setForeground(new Color(70, 70, 70));
|
|
|
|
|
formPanel.add(passwordLabel, gbc);
|
|
|
|
|
|
|
|
|
|
gbc.gridx = 1; gbc.anchor = GridBagConstraints.WEST;
|
|
|
|
|
passwordField = new JPasswordField(25);
|
|
|
|
|
passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
passwordField.setBorder(BorderFactory.createCompoundBorder(
|
|
|
|
|
BorderFactory.createLineBorder(new Color(200, 200, 200), 1),
|
|
|
|
|
BorderFactory.createEmptyBorder(10, 15, 10, 15)
|
|
|
|
|
));
|
|
|
|
|
formPanel.add(passwordField, gbc);
|
|
|
|
|
|
|
|
|
|
// 确认密码
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 1; gbc.anchor = GridBagConstraints.EAST;
|
|
|
|
|
JLabel confirmLabel = new JLabel("确认密码:");
|
|
|
|
|
confirmLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
|
|
|
|
confirmLabel.setForeground(new Color(70, 70, 70));
|
|
|
|
|
formPanel.add(confirmLabel, gbc);
|
|
|
|
|
|
|
|
|
|
gbc.gridx = 1; gbc.anchor = GridBagConstraints.WEST;
|
|
|
|
|
confirmPasswordField = new JPasswordField(25);
|
|
|
|
|
confirmPasswordField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
confirmPasswordField.setBorder(BorderFactory.createCompoundBorder(
|
|
|
|
|
BorderFactory.createLineBorder(new Color(200, 200, 200), 1),
|
|
|
|
|
BorderFactory.createEmptyBorder(10, 15, 10, 15)
|
|
|
|
|
));
|
|
|
|
|
formPanel.add(confirmPasswordField, gbc);
|
|
|
|
|
|
|
|
|
|
formContainer.add(formPanel);
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 40));
|
|
|
|
|
buttonPanel.setOpaque(false);
|
|
|
|
|
|
|
|
|
|
JButton setPasswordButton = createStyledButton("设置密码", new Color(60, 179, 113));
|
|
|
|
|
setPasswordButton.addActionListener(this::handlePasswordSetup);
|
|
|
|
|
buttonPanel.add(setPasswordButton);
|
|
|
|
|
|
|
|
|
|
panel.add(titlePanel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(formContainer, BorderLayout.CENTER);
|
|
|
|
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "PASSWORD_SETUP");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建难度选择界面
|
|
|
|
|
*/
|
|
|
|
|
private void createDifficultySelectionPanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout()) {
|
|
|
|
|
@Override
|
|
|
|
|
protected void paintComponent(Graphics g) {
|
|
|
|
|
Graphics2D g2 = (Graphics2D) g.create();
|
|
|
|
|
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
|
|
// 创建渐变背景
|
|
|
|
|
GradientPaint gradient = new GradientPaint(0, 0, new Color(240, 248, 255),
|
|
|
|
|
0, getHeight(), new Color(230, 240, 250));
|
|
|
|
|
g2.setPaint(gradient);
|
|
|
|
|
g2.fillRect(0, 0, getWidth(), getHeight());
|
|
|
|
|
|
|
|
|
|
g2.dispose();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 标题面板
|
|
|
|
|
JPanel titlePanel = new JPanel();
|
|
|
|
|
titlePanel.setOpaque(false);
|
|
|
|
|
titlePanel.setBorder(BorderFactory.createEmptyBorder(60, 0, 40, 0));
|
|
|
|
|
|
|
|
|
|
JLabel titleLabel = new JLabel("选择学习难度", JLabel.CENTER);
|
|
|
|
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 32));
|
|
|
|
|
titleLabel.setForeground(new Color(25, 25, 112));
|
|
|
|
|
|
|
|
|
|
JLabel subtitleLabel = new JLabel("选择适合您的数学学习级别", JLabel.CENTER);
|
|
|
|
|
subtitleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
|
|
|
subtitleLabel.setForeground(new Color(70, 130, 180));
|
|
|
|
|
subtitleLabel.setBorder(BorderFactory.createEmptyBorder(15, 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
titlePanel.setLayout(new BoxLayout(titlePanel, BoxLayout.Y_AXIS));
|
|
|
|
|
titlePanel.add(titleLabel);
|
|
|
|
|
titlePanel.add(subtitleLabel);
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonContainer = new JPanel();
|
|
|
|
|
buttonContainer.setOpaque(false);
|
|
|
|
|
buttonContainer.setBorder(BorderFactory.createEmptyBorder(20, 80, 40, 80));
|
|
|
|
|
|
|
|
|
|
JPanel buttonPanel = new JPanel(new GridLayout(3, 1, 0, 25));
|
|
|
|
|
buttonPanel.setOpaque(false);
|
|
|
|
|
|
|
|
|
|
JButton elementaryButton = createLargeDifficultyButton("小学数学", new Color(255, 182, 193));
|
|
|
|
|
JButton middleButton = createLargeDifficultyButton("初中数学", new Color(173, 216, 230));
|
|
|
|
|
JButton highButton = createLargeDifficultyButton("高中数学", new Color(221, 160, 221));
|
|
|
|
|
|
|
|
|
|
elementaryButton.addActionListener(e -> selectDifficulty("小学"));
|
|
|
|
|
middleButton.addActionListener(e -> selectDifficulty("初中"));
|
|
|
|
|
highButton.addActionListener(e -> selectDifficulty("高中"));
|
|
|
|
|
|
|
|
|
|
buttonPanel.add(elementaryButton);
|
|
|
|
|
buttonPanel.add(middleButton);
|
|
|
|
|
buttonPanel.add(highButton);
|
|
|
|
|
|
|
|
|
|
buttonContainer.add(buttonPanel);
|
|
|
|
|
|
|
|
|
|
// 底部面板
|
|
|
|
|
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 30, 30));
|
|
|
|
|
bottomPanel.setOpaque(false);
|
|
|
|
|
|
|
|
|
|
JButton changePasswordButton = createStyledButton("修改密码", new Color(255, 140, 0));
|
|
|
|
|
JButton logoutButton = createStyledButton("退出登录", new Color(220, 20, 60));
|
|
|
|
|
|
|
|
|
|
changePasswordButton.addActionListener(e -> cardLayout.show(mainPanel, "PASSWORD_CHANGE"));
|
|
|
|
|
logoutButton.addActionListener(e -> {
|
|
|
|
|
currentUser = null;
|
|
|
|
|
cardLayout.show(mainPanel, "WELCOME");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
bottomPanel.add(changePasswordButton);
|
|
|
|
|
bottomPanel.add(logoutButton);
|
|
|
|
|
|
|
|
|
|
panel.add(titlePanel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(buttonContainer, BorderLayout.CENTER);
|
|
|
|
|
panel.add(bottomPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "DIFFICULTY_SELECTION");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建答题界面
|
|
|
|
|
*/
|
|
|
|
|
private void createQuestionPanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout());
|
|
|
|
|
panel.setBackground(Color.WHITE);
|
|
|
|
|
|
|
|
|
|
// 顶部信息面板
|
|
|
|
|
JPanel topPanel = new JPanel(new BorderLayout());
|
|
|
|
|
topPanel.setBackground(Color.WHITE);
|
|
|
|
|
topPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
|
|
|
|
|
|
|
|
|
JLabel progressLabel = new JLabel("", JLabel.LEFT);
|
|
|
|
|
progressLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
|
|
|
|
|
|
|
|
|
JLabel difficultyLabel = new JLabel("", JLabel.RIGHT);
|
|
|
|
|
difficultyLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
|
|
|
|
|
|
|
|
|
topPanel.add(progressLabel, BorderLayout.WEST);
|
|
|
|
|
topPanel.add(difficultyLabel, BorderLayout.EAST);
|
|
|
|
|
|
|
|
|
|
// 题目面板
|
|
|
|
|
JPanel questionPanel = new JPanel(new BorderLayout());
|
|
|
|
|
questionPanel.setBackground(Color.WHITE);
|
|
|
|
|
questionPanel.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40));
|
|
|
|
|
|
|
|
|
|
questionLabel = new JLabel("", JLabel.CENTER);
|
|
|
|
|
questionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
|
|
|
|
|
questionLabel.setBorder(BorderFactory.createEmptyBorder(20, 0, 30, 0));
|
|
|
|
|
|
|
|
|
|
// 选项面板
|
|
|
|
|
JPanel optionsPanel = new JPanel(new GridLayout(4, 1, 0, 15));
|
|
|
|
|
optionsPanel.setBackground(Color.WHITE);
|
|
|
|
|
|
|
|
|
|
answerGroup = new ButtonGroup();
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
answerButtons[i] = new JRadioButton();
|
|
|
|
|
answerButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
|
|
|
answerButtons[i].setBackground(Color.WHITE);
|
|
|
|
|
answerGroup.add(answerButtons[i]);
|
|
|
|
|
optionsPanel.add(answerButtons[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
questionPanel.add(questionLabel, BorderLayout.NORTH);
|
|
|
|
|
questionPanel.add(optionsPanel, BorderLayout.CENTER);
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonPanel = new JPanel(new FlowLayout());
|
|
|
|
|
buttonPanel.setBackground(Color.WHITE);
|
|
|
|
|
|
|
|
|
|
JButton submitButton = createStyledButton("提交答案", new Color(70, 130, 180));
|
|
|
|
|
submitButton.addActionListener(this::handleAnswerSubmit);
|
|
|
|
|
buttonPanel.add(submitButton);
|
|
|
|
|
|
|
|
|
|
panel.add(topPanel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(questionPanel, BorderLayout.CENTER);
|
|
|
|
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "QUESTION");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建评分界面
|
|
|
|
|
*/
|
|
|
|
|
private void createScorePanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout());
|
|
|
|
|
panel.setBackground(new Color(240, 248, 255));
|
|
|
|
|
|
|
|
|
|
// 标题
|
|
|
|
|
JLabel titleLabel = new JLabel("答题结果", JLabel.CENTER);
|
|
|
|
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
|
|
|
|
|
titleLabel.setBorder(BorderFactory.createEmptyBorder(50, 0, 30, 0));
|
|
|
|
|
|
|
|
|
|
// 分数显示
|
|
|
|
|
scoreLabel = new JLabel("", JLabel.CENTER);
|
|
|
|
|
scoreLabel.setFont(new Font("微软雅黑", Font.BOLD, 36));
|
|
|
|
|
scoreLabel.setForeground(new Color(70, 130, 180));
|
|
|
|
|
scoreLabel.setBorder(BorderFactory.createEmptyBorder(30, 0, 50, 0));
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonPanel = new JPanel(new FlowLayout());
|
|
|
|
|
buttonPanel.setBackground(new Color(240, 248, 255));
|
|
|
|
|
|
|
|
|
|
JButton continueButton = createStyledButton("继续做题", new Color(60, 179, 113));
|
|
|
|
|
JButton exitButton = createStyledButton("退出", new Color(220, 20, 60));
|
|
|
|
|
|
|
|
|
|
continueButton.addActionListener(e -> cardLayout.show(mainPanel, "DIFFICULTY_SELECTION"));
|
|
|
|
|
exitButton.addActionListener(e -> {
|
|
|
|
|
currentUser = null;
|
|
|
|
|
cardLayout.show(mainPanel, "WELCOME");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
buttonPanel.add(continueButton);
|
|
|
|
|
buttonPanel.add(exitButton);
|
|
|
|
|
|
|
|
|
|
panel.add(titleLabel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(scoreLabel, BorderLayout.CENTER);
|
|
|
|
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "SCORE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建密码修改界面
|
|
|
|
|
*/
|
|
|
|
|
private void createPasswordChangePanel() {
|
|
|
|
|
JPanel panel = new JPanel(new BorderLayout());
|
|
|
|
|
panel.setBackground(Color.WHITE);
|
|
|
|
|
|
|
|
|
|
// 标题
|
|
|
|
|
JLabel titleLabel = new JLabel("修改密码", JLabel.CENTER);
|
|
|
|
|
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
|
|
|
|
|
titleLabel.setBorder(BorderFactory.createEmptyBorder(30, 0, 30, 0));
|
|
|
|
|
|
|
|
|
|
// 表单面板
|
|
|
|
|
JPanel formPanel = new JPanel(new GridBagLayout());
|
|
|
|
|
formPanel.setBackground(Color.WHITE);
|
|
|
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
|
|
|
|
gbc.insets = new Insets(10, 10, 10, 10);
|
|
|
|
|
|
|
|
|
|
// 原密码
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 0;
|
|
|
|
|
formPanel.add(new JLabel("原密码:"), gbc);
|
|
|
|
|
gbc.gridx = 1;
|
|
|
|
|
oldPasswordField = new JPasswordField(20);
|
|
|
|
|
formPanel.add(oldPasswordField, gbc);
|
|
|
|
|
|
|
|
|
|
// 新密码
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 1;
|
|
|
|
|
formPanel.add(new JLabel("新密码:"), gbc);
|
|
|
|
|
gbc.gridx = 1;
|
|
|
|
|
JPasswordField newPasswordField = new JPasswordField(20);
|
|
|
|
|
formPanel.add(newPasswordField, gbc);
|
|
|
|
|
|
|
|
|
|
// 确认新密码
|
|
|
|
|
gbc.gridx = 0; gbc.gridy = 2;
|
|
|
|
|
formPanel.add(new JLabel("确认新密码:"), gbc);
|
|
|
|
|
gbc.gridx = 1;
|
|
|
|
|
JPasswordField confirmNewPasswordField = new JPasswordField(20);
|
|
|
|
|
formPanel.add(confirmNewPasswordField, gbc);
|
|
|
|
|
|
|
|
|
|
// 按钮面板
|
|
|
|
|
JPanel buttonPanel = new JPanel(new FlowLayout());
|
|
|
|
|
buttonPanel.setBackground(Color.WHITE);
|
|
|
|
|
|
|
|
|
|
JButton changeButton = createStyledButton("修改密码", new Color(60, 179, 113));
|
|
|
|
|
JButton backButton = createStyledButton("返回", new Color(128, 128, 128));
|
|
|
|
|
|
|
|
|
|
changeButton.addActionListener(e -> handlePasswordChange(
|
|
|
|
|
new String(oldPasswordField.getPassword()),
|
|
|
|
|
new String(newPasswordField.getPassword()),
|
|
|
|
|
new String(confirmNewPasswordField.getPassword())
|
|
|
|
|
));
|
|
|
|
|
backButton.addActionListener(e -> cardLayout.show(mainPanel, "DIFFICULTY_SELECTION"));
|
|
|
|
|
|
|
|
|
|
buttonPanel.add(changeButton);
|
|
|
|
|
buttonPanel.add(backButton);
|
|
|
|
|
|
|
|
|
|
panel.add(titleLabel, BorderLayout.NORTH);
|
|
|
|
|
panel.add(formPanel, BorderLayout.CENTER);
|
|
|
|
|
panel.add(buttonPanel, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
|
|
mainPanel.add(panel, "PASSWORD_CHANGE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建样式化按钮
|
|
|
|
|
*/
|
|
|
|
|
private JButton createStyledButton(String text, Color backgroundColor) {
|
|
|
|
|
return MathLearningAppMethods.createStyledButton(text, backgroundColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 创建大型难度选择按钮
|
|
|
|
|
*/
|
|
|
|
|
private JButton createLargeDifficultyButton(String text, Color backgroundColor) {
|
|
|
|
|
return MathLearningAppMethods.createLargeDifficultyButton(text, backgroundColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 发送验证码
|
|
|
|
|
*/
|
|
|
|
|
private void sendVerificationCode(ActionEvent e) {
|
|
|
|
|
MathLearningAppMethods.sendVerificationCode(e, emailField, registeredUsers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理用户注册
|
|
|
|
|
*/
|
|
|
|
|
private void handleRegister(ActionEvent e) {
|
|
|
|
|
if (MathLearningAppMethods.handleRegister(emailField, verificationCodeField,
|
|
|
|
|
registeredUsers, cardLayout, mainPanel)) {
|
|
|
|
|
// 清空输入框
|
|
|
|
|
emailField.setText("");
|
|
|
|
|
verificationCodeField.setText("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理密码设置
|
|
|
|
|
*/
|
|
|
|
|
private void handlePasswordSetup(ActionEvent e) {
|
|
|
|
|
if (MathLearningAppMethods.handlePasswordSetup(passwordField, confirmPasswordField,
|
|
|
|
|
registeredUsers, cardLayout, mainPanel)) {
|
|
|
|
|
// 设置当前用户
|
|
|
|
|
for (RegisteredUser user : registeredUsers.values()) {
|
|
|
|
|
if (user.isVerified() && user.getPassword() != null) {
|
|
|
|
|
currentUser = user;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 清空密码框
|
|
|
|
|
passwordField.setText("");
|
|
|
|
|
confirmPasswordField.setText("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理用户登录
|
|
|
|
|
*/
|
|
|
|
|
private void handleLogin(String email, String password) {
|
|
|
|
|
RegisteredUser user = MathLearningAppMethods.handleLogin(email, password,
|
|
|
|
|
registeredUsers, cardLayout, mainPanel);
|
|
|
|
|
if (user != null) {
|
|
|
|
|
currentUser = user;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理密码修改
|
|
|
|
|
*/
|
|
|
|
|
private void handlePasswordChange(String oldPassword, String newPassword, String confirmNewPassword) {
|
|
|
|
|
if (MathLearningAppMethods.handlePasswordChange(oldPassword, newPassword, confirmNewPassword, currentUser)) {
|
|
|
|
|
// 清空密码框
|
|
|
|
|
oldPasswordField.setText("");
|
|
|
|
|
cardLayout.show(mainPanel, "DIFFICULTY_SELECTION");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 选择难度并输入题目数量
|
|
|
|
|
*/
|
|
|
|
|
private void selectDifficulty(String difficulty) {
|
|
|
|
|
currentDifficulty = difficulty;
|
|
|
|
|
|
|
|
|
|
String input = JOptionPane.showInputDialog(this,
|
|
|
|
|
"请输入需要生成的题目数量(建议10-30题):",
|
|
|
|
|
"题目数量",
|
|
|
|
|
JOptionPane.QUESTION_MESSAGE);
|
|
|
|
|
|
|
|
|
|
if (input != null && !input.trim().isEmpty()) {
|
|
|
|
|
try {
|
|
|
|
|
int count = Integer.parseInt(input.trim());
|
|
|
|
|
if (count > 0 && count <= 50) {
|
|
|
|
|
generateQuestions(difficulty, count);
|
|
|
|
|
} else {
|
|
|
|
|
JOptionPane.showMessageDialog(this, "请输入1-50之间的数字!", "错误", JOptionPane.ERROR_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
JOptionPane.showMessageDialog(this, "请输入有效的数字!", "错误", JOptionPane.ERROR_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成题目并开始答题
|
|
|
|
|
*/
|
|
|
|
|
private void generateQuestions(String difficulty, int count) {
|
|
|
|
|
currentQuestions = MathLearningAppMethods.generateQuestions(difficulty, count, questionGenerator);
|
|
|
|
|
currentQuestionIndex = 0;
|
|
|
|
|
correctAnswers = 0;
|
|
|
|
|
|
|
|
|
|
if (!currentQuestions.isEmpty()) {
|
|
|
|
|
showCurrentQuestion();
|
|
|
|
|
cardLayout.show(mainPanel, "QUESTION");
|
|
|
|
|
} else {
|
|
|
|
|
JOptionPane.showMessageDialog(this, "生成题目失败!", "错误", JOptionPane.ERROR_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示当前题目
|
|
|
|
|
*/
|
|
|
|
|
private void showCurrentQuestion() {
|
|
|
|
|
if (currentQuestionIndex < currentQuestions.size()) {
|
|
|
|
|
MultipleChoiceQuestion question = currentQuestions.get(currentQuestionIndex);
|
|
|
|
|
|
|
|
|
|
// 更新进度信息
|
|
|
|
|
JPanel topPanel = (JPanel) ((JPanel) mainPanel.getComponent(5)).getComponent(0);
|
|
|
|
|
JLabel progressLabel = (JLabel) topPanel.getComponent(0);
|
|
|
|
|
JLabel difficultyLabel = (JLabel) topPanel.getComponent(1);
|
|
|
|
|
|
|
|
|
|
progressLabel.setText("第 " + (currentQuestionIndex + 1) + " 题 / 共 " + currentQuestions.size() + " 题");
|
|
|
|
|
difficultyLabel.setText(currentDifficulty + "难度");
|
|
|
|
|
|
|
|
|
|
// 更新题目内容
|
|
|
|
|
questionLabel.setText("<html><center>" + question.getQuestion() + "</center></html>");
|
|
|
|
|
|
|
|
|
|
// 更新选项 - 关键修改:清除之前的选择
|
|
|
|
|
answerGroup.clearSelection(); // 清除单选按钮组的选择
|
|
|
|
|
|
|
|
|
|
String[] options = question.getOptions();
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
answerButtons[i].setText((char)('A' + i) + ". " + options[i]);
|
|
|
|
|
answerButtons[i].setSelected(false); // 确保每个按钮都是未选中状态
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重置按钮状态
|
|
|
|
|
for (JRadioButton button : answerButtons) {
|
|
|
|
|
button.setSelected(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理答案提交
|
|
|
|
|
*/
|
|
|
|
|
private void handleAnswerSubmit(ActionEvent e) {
|
|
|
|
|
// 检查是否选择了答案
|
|
|
|
|
int selectedAnswer = -1;
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
if (answerButtons[i].isSelected()) {
|
|
|
|
|
selectedAnswer = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selectedAnswer == -1) {
|
|
|
|
|
JOptionPane.showMessageDialog(this, "请选择一个答案!", "提示", JOptionPane.WARNING_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查答案是否正确
|
|
|
|
|
MultipleChoiceQuestion currentQuestion = currentQuestions.get(currentQuestionIndex);
|
|
|
|
|
if (currentQuestion.isCorrect(selectedAnswer)) {
|
|
|
|
|
correctAnswers++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移动到下一题或显示结果
|
|
|
|
|
currentQuestionIndex++;
|
|
|
|
|
if (currentQuestionIndex < currentQuestions.size()) {
|
|
|
|
|
showCurrentQuestion();
|
|
|
|
|
} else {
|
|
|
|
|
showScore();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示分数
|
|
|
|
|
*/
|
|
|
|
|
private void showScore() {
|
|
|
|
|
int totalQuestions = currentQuestions.size();
|
|
|
|
|
double percentage = (double) correctAnswers / totalQuestions * 100;
|
|
|
|
|
|
|
|
|
|
String scoreText = String.format("<html><center>答对 %d 题,共 %d 题<br/>正确率:%.1f%%</center></html>",
|
|
|
|
|
correctAnswers, totalQuestions, percentage);
|
|
|
|
|
scoreLabel.setText(scoreText);
|
|
|
|
|
|
|
|
|
|
cardLayout.show(mainPanel, "SCORE");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 加载用户数据
|
|
|
|
|
*/
|
|
|
|
|
private void loadUserData() {
|
|
|
|
|
MathLearningAppMethods.loadUserData(registeredUsers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 保存用户数据
|
|
|
|
|
*/
|
|
|
|
|
private void saveUserData() {
|
|
|
|
|
MathLearningAppMethods.saveUserData(registeredUsers);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
SwingUtilities.invokeLater(() -> {
|
|
|
|
|
// 直接启动程序,使用默认外观
|
|
|
|
|
new MathLearningApp().setVisible(true);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|