From dba7308800d28ce01e4409767be8648f60720009 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=A8=E6=8D=B7?= <2747764757@qq.com>
Date: Sat, 11 Oct 2025 22:26:11 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9MathLearningApp.java?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/MathLearningApp.java | 1549 ++++++++++++++++++++------------------
1 file changed, 818 insertions(+), 731 deletions(-)
diff --git a/src/MathLearningApp.java b/src/MathLearningApp.java
index 48a28b6..1298f76 100644
--- a/src/MathLearningApp.java
+++ b/src/MathLearningApp.java
@@ -6,7 +6,12 @@ public class MathLearningApp {
private JFrame mainFrame;
private UserManager userManager;
private QuizController quizController;
- private UserManager.User currentUser;
+
+ // 使用新的数据模型
+ private ViewData viewData;
+ private AppController appController;
+ private ViewBuilder viewBuilder;
+ private EventHandlers eventHandlers;
private static final String SYSTEM_EMAIL_HOST = "smtp.qq.com";
private static final String SYSTEM_EMAIL_PORT = "587";
@@ -31,835 +36,917 @@ public class MathLearningApp {
mainFrame.setSize(500, 550);
mainFrame.setLocationRelativeTo(null);
+ // 初始化MVC组件
+ initializeMVCComponents();
+
showLoginView();
mainFrame.setVisible(true);
}
- // 登录界面 - 完全保持不变
- private void showLoginView() {
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
-
- JLabel titleLabel = new JLabel("数学学习软件 - 登录");
- titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
- titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel inputPanel = new JPanel();
- inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
- inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel emailPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel emailLabel = new JLabel("邮箱:");
- JTextField emailField = new JTextField(20);
- emailField.setPreferredSize(new Dimension(200, 30));
- emailPanel.add(emailLabel);
- emailPanel.add(emailField);
-
- JPanel passwordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel passwordLabel = new JLabel("密码:");
- JPasswordField passwordField = new JPasswordField(20);
- passwordField.setPreferredSize(new Dimension(200, 30));
- passwordPanel.add(passwordLabel);
- passwordPanel.add(passwordField);
-
- inputPanel.add(emailPanel);
- inputPanel.add(Box.createVerticalStrut(15));
- inputPanel.add(passwordPanel);
-
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout());
- buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JButton loginButton = new JButton("登录");
- loginButton.setBackground(new Color(76, 175, 80));
- loginButton.setForeground(Color.WHITE);
- loginButton.setPreferredSize(new Dimension(120, 35));
- loginButton.setOpaque(true);
- loginButton.setBorderPainted(false);
- loginButton.setFocusPainted(false);
-
- JButton registerButton = new JButton("前往注册");
- registerButton.setBackground(new Color(33, 150, 243));
- registerButton.setForeground(Color.WHITE);
- registerButton.setPreferredSize(new Dimension(120, 35));
- registerButton.setOpaque(true);
- registerButton.setBorderPainted(false);
- registerButton.setFocusPainted(false);
-
- buttonPanel.add(loginButton);
- buttonPanel.add(Box.createHorizontalStrut(20));
- buttonPanel.add(registerButton);
-
- JLabel messageLabel = new JLabel(" ");
- messageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
- messageLabel.setForeground(Color.RED);
-
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(titleLabel);
- mainPanel.add(Box.createVerticalStrut(30));
- mainPanel.add(inputPanel);
- mainPanel.add(Box.createVerticalStrut(30));
- mainPanel.add(buttonPanel);
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(messageLabel);
-
- // 初始化管理器
+ private void initializeMVCComponents() {
userManager = new UserManager(SYSTEM_EMAIL_HOST, SYSTEM_EMAIL_PORT,
SYSTEM_EMAIL_USERNAME, SYSTEM_EMAIL_PASSWORD);
quizController = new QuizController();
- loginButton.addActionListener(e -> {
- String email = emailField.getText();
- String password = new String(passwordField.getPassword());
+ viewData = new ViewData();
+ appController = new AppController();
+ viewBuilder = new ViewBuilder();
+ eventHandlers = new EventHandlers();
+ }
+
+ // ==================== 重构后的界面方法 ====================
- if (userManager.login(email, password)) {
- currentUser = userManager.getCurrentUser();
- messageLabel.setText("登录成功!");
- messageLabel.setForeground(Color.GREEN);
+ private void showLoginView() {
+ JPanel loginPanel = viewBuilder.buildLoginView((email, password) -> {
+ if (appController.handleLogin(email, password)) {
showMainView();
} else {
- messageLabel.setText("登录失败,请检查邮箱和密码!");
- messageLabel.setForeground(Color.RED);
+ // 错误处理可以在ViewBuilder中处理
+ JOptionPane.showMessageDialog(mainFrame, "登录失败,请检查邮箱和密码!", "错误", JOptionPane.ERROR_MESSAGE);
}
- });
+ }, () -> showRegisterView());
- registerButton.addActionListener(e -> showRegisterView());
+ mainFrame.setContentPane(loginPanel);
+ mainFrame.revalidate();
+ mainFrame.repaint();
+ }
+
+ private void showRegisterView() {
+ JPanel registerPanel = viewBuilder.buildRegisterView(
+ (username, email) -> appController.handleSendVerificationCode(username, email),
+ (username, email, code, password, confirmPassword) ->
+ appController.handleRegister(username, email, code, password, confirmPassword),
+ () -> showLoginView()
+ );
+
+ mainFrame.setContentPane(registerPanel);
+ mainFrame.revalidate();
+ mainFrame.repaint();
+ }
+
+ private void showMainView() {
+ JPanel mainPanel = viewBuilder.buildMainView(
+ (difficulty) -> showQuestionCountView(difficulty),
+ () -> showChangePasswordView(),
+ () -> appController.handleLogout()
+ );
mainFrame.setContentPane(mainPanel);
mainFrame.revalidate();
mainFrame.repaint();
}
- // 注册界面 - 完全保持不变
- private void showRegisterView() {
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- mainPanel.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 25));
-
- JLabel titleLabel = new JLabel("用户注册");
- titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
- titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel inputPanel = new JPanel();
- inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
- inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel usernamePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel usernameLabel = new JLabel("用户名:");
- JTextField usernameField = new JTextField(20);
- usernameField.setPreferredSize(new Dimension(200, 30));
- usernamePanel.add(usernameLabel);
- usernamePanel.add(usernameField);
-
- JPanel emailPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel emailLabel = new JLabel("邮箱:");
- JTextField emailField = new JTextField(20);
- emailField.setPreferredSize(new Dimension(200, 30));
- emailPanel.add(emailLabel);
- emailPanel.add(emailField);
-
- JPanel codePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel codeLabel = new JLabel("验证码:");
- JTextField codeField = new JTextField(15);
- codeField.setPreferredSize(new Dimension(120, 30));
- codeField.setEnabled(false);
-
- JButton sendCodeButton = new JButton("发送验证码");
- sendCodeButton.setBackground(new Color(255, 152, 0));
- sendCodeButton.setForeground(Color.WHITE);
- sendCodeButton.setPreferredSize(new Dimension(120, 30));
- sendCodeButton.setOpaque(true);
- sendCodeButton.setBorderPainted(false);
- sendCodeButton.setFocusPainted(false);
-
- codePanel.add(codeLabel);
- codePanel.add(codeField);
- codePanel.add(Box.createHorizontalStrut(10));
- codePanel.add(sendCodeButton);
-
- JPanel passwordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel passwordLabel = new JLabel("密码:");
- JPasswordField passwordField = new JPasswordField(20);
- passwordField.setPreferredSize(new Dimension(200, 30));
- passwordField.setEnabled(false);
- passwordPanel.add(passwordLabel);
- passwordPanel.add(passwordField);
-
- JPanel confirmPasswordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel confirmPasswordLabel = new JLabel("确认密码:");
- JPasswordField confirmPasswordField = new JPasswordField(20);
- confirmPasswordField.setPreferredSize(new Dimension(200, 30));
- confirmPasswordField.setEnabled(false);
- confirmPasswordPanel.add(confirmPasswordLabel);
- confirmPasswordPanel.add(confirmPasswordField);
-
- inputPanel.add(usernamePanel);
- inputPanel.add(Box.createVerticalStrut(15));
- inputPanel.add(emailPanel);
- inputPanel.add(Box.createVerticalStrut(15));
- inputPanel.add(codePanel);
- inputPanel.add(Box.createVerticalStrut(15));
- inputPanel.add(passwordPanel);
- inputPanel.add(Box.createVerticalStrut(15));
- inputPanel.add(confirmPasswordPanel);
-
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout());
- buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JButton registerButton = new JButton("注册");
- registerButton.setBackground(new Color(76, 175, 80));
- registerButton.setForeground(Color.WHITE);
- registerButton.setPreferredSize(new Dimension(120, 35));
- registerButton.setEnabled(false);
- registerButton.setOpaque(true);
- registerButton.setBorderPainted(false);
- registerButton.setFocusPainted(false);
-
- JButton backButton = new JButton("返回登录");
- backButton.setBackground(new Color(158, 158, 158));
- backButton.setForeground(Color.WHITE);
- backButton.setPreferredSize(new Dimension(120, 35));
- backButton.setOpaque(true);
- backButton.setBorderPainted(false);
- backButton.setFocusPainted(false);
-
- buttonPanel.add(registerButton);
- buttonPanel.add(Box.createHorizontalStrut(20));
- buttonPanel.add(backButton);
-
- JLabel messageLabel = new JLabel(" ");
- messageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
- messageLabel.setForeground(Color.RED);
-
- mainPanel.add(Box.createVerticalStrut(10));
- mainPanel.add(titleLabel);
- mainPanel.add(Box.createVerticalStrut(25));
- mainPanel.add(inputPanel);
- mainPanel.add(Box.createVerticalStrut(25));
- mainPanel.add(buttonPanel);
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(messageLabel);
-
- sendCodeButton.addActionListener(e -> {
- String username = usernameField.getText().trim();
- String userEmail = emailField.getText().trim();
-
- if (username.isEmpty()) {
- messageLabel.setText("请输入用户名!");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ private void showQuestionCountView(String difficulty) {
+ JPanel countPanel = viewBuilder.buildQuestionCountView(difficulty,
+ (count) -> {
+ if (appController.handleStartQuiz(difficulty, count)) {
+ showQuizView();
+ } else {
+ JOptionPane.showMessageDialog(mainFrame, "题目数量必须在10-30之间!", "错误", JOptionPane.ERROR_MESSAGE);
+ }
+ },
+ () -> showMainView()
+ );
- if (userEmail.isEmpty()) {
- messageLabel.setText("请输入邮箱地址!");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ mainFrame.setContentPane(countPanel);
+ mainFrame.revalidate();
+ mainFrame.repaint();
+ }
- if (!isValidEmail(userEmail)) {
- messageLabel.setText("邮箱格式错误!请输入有效的邮箱地址。");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ private void showQuizView() {
+ QuizController.Question currentQuestion = quizController.getCurrentQuestion();
+ if (currentQuestion == null) {
+ showScoreView();
+ return;
+ }
- if (userManager.isUsernameExists(username)) {
- messageLabel.setText("用户名已存在,请选择其他用户名!");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ JPanel quizPanel = viewBuilder.buildQuizView(
+ quizController.getCurrentQuestionNumber(),
+ quizController.getTotalQuestions(),
+ currentQuestion,
+ (selectedAnswer) -> {
+ appController.handleAnswerSubmit(selectedAnswer);
+ if (quizController.hasNextQuestion()) {
+ quizController.nextQuestion();
+ showQuizView(); // 刷新界面显示下一题
+ } else {
+ showScoreView();
+ }
+ }
+ );
- if (userManager.isUserExists(userEmail)) {
- messageLabel.setText("该邮箱已被注册,请使用其他邮箱!");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ mainFrame.setContentPane(quizPanel);
+ mainFrame.revalidate();
+ mainFrame.repaint();
+ mainFrame.setSize(550, 500);
+ mainFrame.setLocationRelativeTo(null);
+ }
+
+ private void showScoreView() {
+ int score = quizController.getScore();
+ int total = quizController.getTotalQuestions();
+ double percentage = quizController.getPercentage();
- sendCodeButton.setEnabled(false);
- sendCodeButton.setText("发送中...");
+ JPanel scorePanel = viewBuilder.buildScoreView(score, total, percentage,
+ () -> showMainView()
+ );
- new Thread(() -> {
- String code = userManager.generateAndSendVerificationCode(userEmail);
+ mainFrame.setContentPane(scorePanel);
+ mainFrame.revalidate();
+ mainFrame.repaint();
+ }
- SwingUtilities.invokeLater(() -> {
- if (code != null) {
- messageLabel.setText("验证码已发送到您的邮箱: " + userEmail + "
请查看邮件并输入验证码");
- messageLabel.setForeground(Color.GREEN);
+ private void showChangePasswordView() {
+ JPanel changePasswordPanel = viewBuilder.buildChangePasswordView(
+ (oldPassword, newPassword, confirmPassword) ->
+ appController.handleChangePassword(oldPassword, newPassword, confirmPassword),
+ () -> showMainView()
+ );
- codeField.setEnabled(true);
- passwordField.setEnabled(true);
- confirmPasswordField.setEnabled(true);
- registerButton.setEnabled(true);
- } else {
- messageLabel.setText("验证码发送失败,请检查邮箱地址或稍后重试!");
- messageLabel.setForeground(Color.RED);
- sendCodeButton.setEnabled(true);
- sendCodeButton.setText("发送验证码");
- }
- });
- }).start();
- });
+ mainFrame.setContentPane(changePasswordPanel);
+ mainFrame.revalidate();
+ mainFrame.repaint();
+ }
+
+ private boolean isValidEmail(String email) {
+ String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
+ return email != null && email.matches(emailRegex);
+ }
+
+ // =========================================================================
+ // MVC 架构内部类
+ // =========================================================================
+
+ /**
+ * 数据模型 - 负责管理视图数据
+ */
+ private class ViewData {
+ private UserManager.User currentUser;
+ private String currentMessage;
+ private Color messageColor;
+
+ public UserManager.User getCurrentUser() {
+ return currentUser;
+ }
+
+ public void setCurrentUser(UserManager.User user) {
+ this.currentUser = user;
+ }
+
+ public String getCurrentMessage() {
+ return currentMessage;
+ }
+
+ public void setCurrentMessage(String message, Color color) {
+ this.currentMessage = message;
+ this.messageColor = color;
+ }
- registerButton.addActionListener(e -> {
- String username = usernameField.getText().trim();
- String email = emailField.getText().trim();
- String code = codeField.getText().trim();
- String password = new String(passwordField.getPassword());
- String confirmPassword = new String(confirmPasswordField.getPassword());
-
- if (username.isEmpty()) {
- messageLabel.setText("请输入用户名!");
- messageLabel.setForeground(Color.RED);
- return;
+ public Color getMessageColor() {
+ return messageColor;
+ }
+ }
+
+ /**
+ * 应用控制器 - 处理所有业务逻辑
+ */
+ private class AppController {
+ public boolean handleLogin(String email, String password) {
+ if (userManager.login(email, password)) {
+ viewData.setCurrentUser(userManager.getCurrentUser());
+ return true;
}
+ return false;
+ }
- if (email.isEmpty()) {
- messageLabel.setText("请输入邮箱地址!");
- messageLabel.setForeground(Color.RED);
- return;
+ public boolean handleSendVerificationCode(String username, String email) {
+ if (username.isEmpty() || email.isEmpty()) {
+ return false;
}
- if (code.isEmpty()) {
- messageLabel.setText("请输入验证码!");
- messageLabel.setForeground(Color.RED);
- return;
+ if (userManager.isUsernameExists(username)) {
+ return false;
}
- if (password.isEmpty()) {
- messageLabel.setText("请输入密码!");
- messageLabel.setForeground(Color.RED);
- return;
+ if (userManager.isUserExists(email)) {
+ return false;
}
+ String code = userManager.generateAndSendVerificationCode(email);
+ return code != null;
+ }
+
+ public boolean handleRegister(String username, String email, String code,
+ String password, String confirmPassword) {
if (!password.equals(confirmPassword)) {
- messageLabel.setText("两次输入的密码不一致!");
- messageLabel.setForeground(Color.RED);
- return;
+ return false;
}
if (!userManager.isValidPassword(password)) {
- messageLabel.setText("密码不符合要求:
- 长度必须在6-10位之间
- 必须包含大写字母、小写字母和数字");
- messageLabel.setForeground(Color.RED);
- return;
+ return false;
}
- if (userManager.registerUser(username, email, code, password)) {
- messageLabel.setText("注册成功!请返回登录");
- messageLabel.setForeground(Color.GREEN);
- registerButton.setEnabled(false);
- sendCodeButton.setEnabled(false);
- } else {
- messageLabel.setText("注册失败!请检查:
- 验证码是否正确
- 密码是否符合要求
- 邮箱或用户名是否已注册");
- messageLabel.setForeground(Color.RED);
+ return userManager.registerUser(username, email, code, password);
+ }
+
+ public boolean handleStartQuiz(String difficulty, int count) {
+ if (count >= 10 && count <= 30) {
+ quizController.startNewQuiz(difficulty, count);
+ return true;
}
- });
+ return false;
+ }
- backButton.addActionListener(e -> showLoginView());
+ public void handleAnswerSubmit(int selectedAnswer) {
+ quizController.submitAnswer(selectedAnswer);
+ }
- mainFrame.setContentPane(mainPanel);
- mainFrame.revalidate();
- mainFrame.repaint();
- }
+ public boolean handleChangePassword(String oldPassword, String newPassword, String confirmPassword) {
+ if (!newPassword.equals(confirmPassword)) {
+ return false;
+ }
- // 主界面 - 完全保持不变
- private void showMainView() {
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- mainPanel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
-
- String welcomeText = currentUser != null ?
- "欢迎 " + currentUser.getUsername() + " 使用数学学习软件!" :
- "欢迎使用数学学习软件!";
-
- JLabel welcomeLabel = new JLabel(welcomeText);
- welcomeLabel.setFont(new Font("微软雅黑", Font.BOLD, 22));
- welcomeLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JLabel instructionLabel = new JLabel("请选择题目难度:");
- instructionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
- instructionLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
- buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JButton primaryBtn = createDifficultyButton("小学", new Color(76, 175, 80));
- JButton middleBtn = createDifficultyButton("初中", new Color(33, 150, 243));
- JButton highBtn = createDifficultyButton("高中", new Color(255, 152, 0));
-
- buttonPanel.add(primaryBtn);
- buttonPanel.add(Box.createVerticalStrut(15));
- buttonPanel.add(middleBtn);
- buttonPanel.add(Box.createVerticalStrut(15));
- buttonPanel.add(highBtn);
-
- JPanel functionPanel = new JPanel();
- functionPanel.setLayout(new FlowLayout());
- functionPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JButton changePasswordBtn = new JButton("修改密码");
- changePasswordBtn.setBackground(new Color(96, 125, 139));
- changePasswordBtn.setForeground(Color.WHITE);
- changePasswordBtn.setPreferredSize(new Dimension(120, 35));
- changePasswordBtn.setOpaque(true);
- changePasswordBtn.setBorderPainted(false);
- changePasswordBtn.setFocusPainted(false);
-
- JButton logoutBtn = new JButton("退出登录");
- logoutBtn.setBackground(new Color(244, 67, 54));
- logoutBtn.setForeground(Color.WHITE);
- logoutBtn.setPreferredSize(new Dimension(120, 35));
- logoutBtn.setOpaque(true);
- logoutBtn.setBorderPainted(false);
- logoutBtn.setFocusPainted(false);
-
- functionPanel.add(changePasswordBtn);
- functionPanel.add(Box.createHorizontalStrut(20));
- functionPanel.add(logoutBtn);
-
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(welcomeLabel);
- mainPanel.add(Box.createVerticalStrut(10));
- mainPanel.add(instructionLabel);
- mainPanel.add(Box.createVerticalStrut(30));
- mainPanel.add(buttonPanel);
- mainPanel.add(Box.createVerticalStrut(30));
- mainPanel.add(functionPanel);
-
- changePasswordBtn.addActionListener(e -> showChangePasswordView());
- logoutBtn.addActionListener(e -> {
+ if (!userManager.isValidPassword(newPassword)) {
+ return false;
+ }
+
+ return userManager.changePassword(oldPassword, newPassword);
+ }
+
+ public void handleLogout() {
userManager.logout();
- currentUser = null;
+ viewData.setCurrentUser(null);
showLoginView();
- });
-
- mainFrame.setContentPane(mainPanel);
- mainFrame.revalidate();
- mainFrame.repaint();
+ }
}
- private JButton createDifficultyButton(String text, Color color) {
- JButton button = new JButton(text);
- button.setBackground(color);
- button.setForeground(Color.WHITE);
- button.setFont(new Font("微软雅黑", Font.BOLD, 16));
- button.setPreferredSize(new Dimension(140, 45));
- button.setMaximumSize(new Dimension(140, 45));
- button.setAlignmentX(Component.CENTER_ALIGNMENT);
- button.setOpaque(true);
- button.setBorderPainted(false);
- button.setFocusPainted(false);
-
- button.addActionListener(e -> showQuestionCountView(text));
- return button;
- }
+ /**
+ * 视图构建器 - 负责构建所有界面组件
+ */
+ private class ViewBuilder {
+ public JPanel buildLoginView(LoginListener loginListener, Runnable backToLogin) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
+
+ // 标题
+ JLabel titleLabel = new JLabel("数学学习软件 - 登录");
+ titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
+ titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ // 输入面板
+ JPanel inputPanel = new JPanel();
+ inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
+ inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JTextField emailField = new JTextField(20);
+ emailField.setPreferredSize(new Dimension(200, 30));
+
+ JPasswordField passwordField = new JPasswordField(20);
+ passwordField.setPreferredSize(new Dimension(200, 30));
+
+ JPanel emailPanel = createLabelFieldPanel("邮箱:", emailField);
+ JPanel passwordPanel = createLabelFieldPanel("密码:", passwordField);
+
+ inputPanel.add(emailPanel);
+ inputPanel.add(Box.createVerticalStrut(15));
+ inputPanel.add(passwordPanel);
+
+ // 按钮面板
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout());
+ buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JButton loginButton = createStyledButton("登录", new Color(76, 175, 80), 120, 35);
+ JButton registerButton = createStyledButton("前往注册", new Color(33, 150, 243), 120, 35);
+
+ loginButton.addActionListener(e -> {
+ String email = emailField.getText();
+ String password = new String(passwordField.getPassword());
+ loginListener.onLogin(email, password);
+ });
+
+ registerButton.addActionListener(e -> backToLogin.run());
+
+ buttonPanel.add(loginButton);
+ buttonPanel.add(Box.createHorizontalStrut(20));
+ buttonPanel.add(registerButton);
+
+ // 组装主面板
+ panel.add(Box.createVerticalStrut(20));
+ panel.add(titleLabel);
+ panel.add(Box.createVerticalStrut(30));
+ panel.add(inputPanel);
+ panel.add(Box.createVerticalStrut(30));
+ panel.add(buttonPanel);
+
+ return panel;
+ }
- // 输入题目数量界面 - 完全保持不变
- private void showQuestionCountView(String difficulty) {
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- mainPanel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
-
- JLabel titleLabel = new JLabel("准备生成" + difficulty + "数学题目");
- titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
- titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JLabel instructionLabel = new JLabel("请输入题目数量 (10-30):");
- instructionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
- instructionLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel inputPanel = new JPanel();
- inputPanel.setLayout(new FlowLayout());
- inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JTextField countField = new JTextField(10);
- countField.setPreferredSize(new Dimension(100, 30));
- inputPanel.add(countField);
-
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout());
- buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JButton startButton = new JButton("开始答题");
- startButton.setBackground(new Color(76, 175, 80));
- startButton.setForeground(Color.WHITE);
- startButton.setPreferredSize(new Dimension(120, 35));
- startButton.setOpaque(true);
- startButton.setBorderPainted(false);
- startButton.setFocusPainted(false);
-
- JButton backButton = new JButton("返回");
- backButton.setBackground(new Color(158, 158, 158));
- backButton.setForeground(Color.WHITE);
- backButton.setPreferredSize(new Dimension(120, 35));
- backButton.setOpaque(true);
- backButton.setBorderPainted(false);
- backButton.setFocusPainted(false);
-
- buttonPanel.add(startButton);
- buttonPanel.add(Box.createHorizontalStrut(20));
- buttonPanel.add(backButton);
-
- JLabel messageLabel = new JLabel(" ");
- messageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
- messageLabel.setForeground(Color.RED);
-
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(titleLabel);
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(instructionLabel);
- mainPanel.add(Box.createVerticalStrut(15));
- mainPanel.add(inputPanel);
- mainPanel.add(Box.createVerticalStrut(25));
- mainPanel.add(buttonPanel);
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(messageLabel);
-
- startButton.addActionListener(e -> {
- try {
- int count = Integer.parseInt(countField.getText());
- if (count >= 10 && count <= 30) {
- messageLabel.setText("正在生成题目,请稍候...");
- messageLabel.setForeground(Color.BLUE);
- mainFrame.revalidate();
- mainFrame.repaint();
-
- SwingWorker worker = new SwingWorker() {
- @Override
- protected Void doInBackground() throws Exception {
- quizController.startNewQuiz(difficulty, count);
- return null;
- }
+ public JPanel buildRegisterView(SendCodeListener sendCodeListener, RegisterListener registerListener, Runnable backAction) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBorder(BorderFactory.createEmptyBorder(25, 25, 25, 25));
+
+ JLabel titleLabel = new JLabel("用户注册");
+ titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
+ titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JPanel inputPanel = new JPanel();
+ inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
+ inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JTextField usernameField = new JTextField(20);
+ JTextField emailField = new JTextField(20);
+ JTextField codeField = new JTextField(15);
+ JPasswordField passwordField = new JPasswordField(20);
+ JPasswordField confirmPasswordField = new JPasswordField(20);
+
+ // 初始禁用状态
+ codeField.setEnabled(false);
+ passwordField.setEnabled(false);
+ confirmPasswordField.setEnabled(false);
+
+ JButton sendCodeButton = createStyledButton("发送验证码", new Color(255, 152, 0), 120, 30);
+ JButton registerButton = createStyledButton("注册", new Color(76, 175, 80), 120, 35);
+ registerButton.setEnabled(false); // 初始禁用注册按钮
+ JButton backButton = createStyledButton("返回登录", new Color(158, 158, 158), 120, 35);
+
+ // 添加消息标签
+ JLabel messageLabel = new JLabel(" ");
+ messageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ messageLabel.setForeground(Color.RED);
+
+ // 构建各个输入行
+ JPanel usernamePanel = createLabelFieldPanel("用户名:", usernameField);
+ JPanel emailPanel = createLabelFieldPanel("邮箱:", emailField);
+
+ JPanel codePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ codePanel.add(new JLabel("验证码:"));
+ codePanel.add(codeField);
+ codePanel.add(Box.createHorizontalStrut(10));
+ codePanel.add(sendCodeButton);
+
+ JPanel passwordPanel = createLabelFieldPanel("密码:", passwordField);
+ JPanel confirmPasswordPanel = createLabelFieldPanel("确认密码:", confirmPasswordField);
+
+ inputPanel.add(usernamePanel);
+ inputPanel.add(Box.createVerticalStrut(15));
+ inputPanel.add(emailPanel);
+ inputPanel.add(Box.createVerticalStrut(15));
+ inputPanel.add(codePanel);
+ inputPanel.add(Box.createVerticalStrut(15));
+ inputPanel.add(passwordPanel);
+ inputPanel.add(Box.createVerticalStrut(15));
+ inputPanel.add(confirmPasswordPanel);
+
+ // 按钮面板
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout());
+ buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ buttonPanel.add(registerButton);
+ buttonPanel.add(Box.createHorizontalStrut(20));
+ buttonPanel.add(backButton);
+
+ // 发送验证码事件处理
+ sendCodeButton.addActionListener(e -> {
+ String username = usernameField.getText().trim();
+ String email = emailField.getText().trim();
+
+ // 客户端验证
+ if (username.isEmpty()) {
+ messageLabel.setText("请输入用户名!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (email.isEmpty()) {
+ messageLabel.setText("请输入邮箱地址!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (!isValidEmail(email)) {
+ messageLabel.setText("邮箱格式错误!请输入有效的邮箱地址。");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
- @Override
- protected void done() {
- showQuizView();
+ // 检查用户名是否已存在
+ if (userManager.isUsernameExists(username)) {
+ messageLabel.setText("用户名已存在,请选择其他用户名!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ // 检查邮箱是否已被注册
+ if (userManager.isUserExists(email)) {
+ messageLabel.setText("该邮箱已被注册,请使用其他邮箱!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ // 禁用发送按钮,显示发送中状态
+ sendCodeButton.setEnabled(false);
+ sendCodeButton.setText("发送中...");
+ messageLabel.setText("正在发送验证码,请稍候...");
+ messageLabel.setForeground(Color.BLUE);
+
+ // 在新线程中发送验证码,避免阻塞UI
+ new Thread(() -> {
+ boolean success = sendCodeListener.onSendCode(username, email);
+
+ SwingUtilities.invokeLater(() -> {
+ if (success) {
+ messageLabel.setText("验证码已发送到您的邮箱: " + email + "
请查看邮件并输入验证码");
+ messageLabel.setForeground(Color.GREEN);
+
+ // 启用相关输入框
+ codeField.setEnabled(true);
+ passwordField.setEnabled(true);
+ confirmPasswordField.setEnabled(true);
+ registerButton.setEnabled(true);
+ } else {
+ messageLabel.setText("验证码发送失败,请检查邮箱地址或稍后重试!");
+ messageLabel.setForeground(Color.RED);
}
- };
- worker.execute();
+
+ // 恢复发送按钮状态
+ sendCodeButton.setEnabled(true);
+ sendCodeButton.setText("发送验证码");
+ });
+ }).start();
+ });
+
+ // 注册事件处理
+ registerButton.addActionListener(e -> {
+ String username = usernameField.getText().trim();
+ String email = emailField.getText().trim();
+ String code = codeField.getText().trim();
+ String password = new String(passwordField.getPassword());
+ String confirmPassword = new String(confirmPasswordField.getPassword());
+
+ // 客户端验证
+ if (username.isEmpty()) {
+ messageLabel.setText("请输入用户名!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (email.isEmpty()) {
+ messageLabel.setText("请输入邮箱地址!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (code.isEmpty()) {
+ messageLabel.setText("请输入验证码!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (password.isEmpty()) {
+ messageLabel.setText("请输入密码!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (!password.equals(confirmPassword)) {
+ messageLabel.setText("两次输入的密码不一致!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (!userManager.isValidPassword(password)) {
+ messageLabel.setText("密码不符合要求:
- 长度必须在6-10位之间
- 必须包含大写字母、小写字母和数字");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
+
+ // 调用注册逻辑
+ boolean success = registerListener.onRegister(username, email, code, password, confirmPassword);
+
+ if (success) {
+ messageLabel.setText("注册成功!请返回登录");
+ messageLabel.setForeground(Color.GREEN);
+ registerButton.setEnabled(false);
+ sendCodeButton.setEnabled(false);
} else {
- messageLabel.setText("题目数量必须在10-30之间!");
+ messageLabel.setText("注册失败!请检查:
- 验证码是否正确
- 密码是否符合要求
- 邮箱或用户名是否已注册");
messageLabel.setForeground(Color.RED);
}
- } catch (NumberFormatException ex) {
- messageLabel.setText("请输入有效的数字!");
- messageLabel.setForeground(Color.RED);
- }
- });
+ });
- backButton.addActionListener(e -> showMainView());
+ backButton.addActionListener(e -> backAction.run());
- mainFrame.setContentPane(mainPanel);
- mainFrame.revalidate();
- mainFrame.repaint();
- }
+ // 组装主面板
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(titleLabel);
+ panel.add(Box.createVerticalStrut(25));
+ panel.add(inputPanel);
+ panel.add(Box.createVerticalStrut(15));
+ panel.add(messageLabel); // 添加消息标签
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(buttonPanel);
- // 答题界面 - 完全保持不变
- private void showQuizView() {
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BorderLayout());
- mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
+ return panel;
+ }
- QuizController.Question currentQuestion = quizController.getCurrentQuestion();
- if (currentQuestion == null) {
- showScoreView();
- return;
+ public JPanel buildMainView(DifficultySelectListener difficultyListener,
+ Runnable changePasswordAction, Runnable logoutAction) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
+
+ String welcomeText = viewData.getCurrentUser() != null ?
+ "欢迎 " + viewData.getCurrentUser().getUsername() + " 使用数学学习软件!" :
+ "欢迎使用数学学习软件!";
+
+ JLabel welcomeLabel = new JLabel(welcomeText);
+ welcomeLabel.setFont(new Font("微软雅黑", Font.BOLD, 22));
+ welcomeLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JLabel instructionLabel = new JLabel("请选择题目难度:");
+ instructionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+ instructionLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ // 难度按钮面板
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
+ buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JButton primaryBtn = createDifficultyButton("小学", new Color(76, 175, 80));
+ JButton middleBtn = createDifficultyButton("初中", new Color(33, 150, 243));
+ JButton highBtn = createDifficultyButton("高中", new Color(255, 152, 0));
+
+ primaryBtn.addActionListener(e -> difficultyListener.onDifficultySelected("小学"));
+ middleBtn.addActionListener(e -> difficultyListener.onDifficultySelected("初中"));
+ highBtn.addActionListener(e -> difficultyListener.onDifficultySelected("高中"));
+
+ buttonPanel.add(primaryBtn);
+ buttonPanel.add(Box.createVerticalStrut(15));
+ buttonPanel.add(middleBtn);
+ buttonPanel.add(Box.createVerticalStrut(15));
+ buttonPanel.add(highBtn);
+
+ // 功能按钮面板
+ JPanel functionPanel = new JPanel();
+ functionPanel.setLayout(new FlowLayout());
+ functionPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JButton changePasswordBtn = createStyledButton("修改密码", new Color(96, 125, 139), 120, 35);
+ JButton logoutBtn = createStyledButton("退出登录", new Color(244, 67, 54), 120, 35);
+
+ changePasswordBtn.addActionListener(e -> changePasswordAction.run());
+ logoutBtn.addActionListener(e -> logoutAction.run());
+
+ functionPanel.add(changePasswordBtn);
+ functionPanel.add(Box.createHorizontalStrut(20));
+ functionPanel.add(logoutBtn);
+
+ // 组装主面板
+ panel.add(Box.createVerticalStrut(20));
+ panel.add(welcomeLabel);
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(instructionLabel);
+ panel.add(Box.createVerticalStrut(30));
+ panel.add(buttonPanel);
+ panel.add(Box.createVerticalStrut(30));
+ panel.add(functionPanel);
+
+ return panel;
}
- JPanel infoPanel = new JPanel();
- infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
- infoPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 20, 10));
+ public JPanel buildQuestionCountView(String difficulty, CountSubmitListener countListener, Runnable backAction) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
+
+ JLabel titleLabel = new JLabel("准备生成" + difficulty + "数学题目");
+ titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
+ titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JLabel instructionLabel = new JLabel("请输入题目数量 (10-30):");
+ instructionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
+ instructionLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JPanel inputPanel = new JPanel();
+ inputPanel.setLayout(new FlowLayout());
+ inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JTextField countField = new JTextField(10);
+ countField.setPreferredSize(new Dimension(100, 30));
+ inputPanel.add(countField);
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout());
+ buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
- JLabel questionNumberLabel = new JLabel();
- questionNumberLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
+ JButton startButton = createStyledButton("开始答题", new Color(76, 175, 80), 120, 35);
+ JButton backButton = createStyledButton("返回", new Color(158, 158, 158), 120, 35);
- JLabel questionContentLabel = new JLabel();
- questionContentLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
- questionContentLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
+ startButton.addActionListener(e -> {
+ try {
+ int count = Integer.parseInt(countField.getText());
+ countListener.onCountSubmit(count);
+ } catch (NumberFormatException ex) {
+ JOptionPane.showMessageDialog(mainFrame, "请输入有效的数字!", "错误", JOptionPane.ERROR_MESSAGE);
+ }
+ });
- infoPanel.add(questionNumberLabel);
- infoPanel.add(Box.createVerticalStrut(15));
- infoPanel.add(questionContentLabel);
+ backButton.addActionListener(e -> backAction.run());
- JPanel optionsPanel = new JPanel();
- optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS));
- optionsPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
+ buttonPanel.add(startButton);
+ buttonPanel.add(Box.createHorizontalStrut(20));
+ buttonPanel.add(backButton);
- ButtonGroup answerGroup = new ButtonGroup();
- JRadioButton[] optionButtons = new JRadioButton[4];
+ panel.add(Box.createVerticalStrut(20));
+ panel.add(titleLabel);
+ panel.add(Box.createVerticalStrut(20));
+ panel.add(instructionLabel);
+ panel.add(Box.createVerticalStrut(15));
+ panel.add(inputPanel);
+ panel.add(Box.createVerticalStrut(25));
+ panel.add(buttonPanel);
- for (int i = 0; i < 4; i++) {
- optionButtons[i] = new JRadioButton();
- optionButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 14));
- optionButtons[i].setActionCommand(String.valueOf(i));
- answerGroup.add(optionButtons[i]);
- optionsPanel.add(optionButtons[i]);
- optionsPanel.add(Box.createVerticalStrut(12));
+ return panel;
}
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout());
- buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 10, 10, 10));
-
- JButton submitButton = new JButton("提交答案");
- submitButton.setBackground(new Color(76, 175, 80));
- submitButton.setForeground(Color.WHITE);
- submitButton.setPreferredSize(new Dimension(140, 40));
- submitButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
- submitButton.setOpaque(true);
- submitButton.setBorderPainted(false);
- submitButton.setFocusPainted(false);
-
- buttonPanel.add(submitButton);
-
- JLabel messageLabel = new JLabel(" ");
- messageLabel.setForeground(Color.RED);
- messageLabel.setHorizontalAlignment(SwingConstants.CENTER);
- messageLabel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 5));
-
- updateQuestionDisplay(questionNumberLabel, questionContentLabel, optionButtons);
-
- submitButton.addActionListener(e -> {
- ButtonModel selectedModel = answerGroup.getSelection();
- if (selectedModel == null) {
- messageLabel.setText("请选择一个答案!");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ public JPanel buildQuizView(int currentNumber, int totalQuestions, QuizController.Question question, AnswerSubmitListener answerListener) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
- int selectedIndex = Integer.parseInt(selectedModel.getActionCommand());
- quizController.submitAnswer(selectedIndex);
- answerGroup.clearSelection();
- messageLabel.setText("");
+ // 信息面板
+ JPanel infoPanel = new JPanel();
+ infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
+ infoPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 20, 10));
- if (quizController.hasNextQuestion()) {
- quizController.nextQuestion();
- updateQuestionDisplay(questionNumberLabel, questionContentLabel, optionButtons);
- } else {
- showScoreView();
+ JLabel questionNumberLabel = new JLabel("第 " + currentNumber + " 题 / 共 " + totalQuestions + " 题");
+ questionNumberLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
+
+ JLabel questionContentLabel = new JLabel("" + question.getContent() + "");
+ questionContentLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+ questionContentLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
+
+ infoPanel.add(questionNumberLabel);
+ infoPanel.add(Box.createVerticalStrut(15));
+ infoPanel.add(questionContentLabel);
+
+ // 选项面板
+ JPanel optionsPanel = new JPanel();
+ optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS));
+ optionsPanel.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
+
+ ButtonGroup answerGroup = new ButtonGroup();
+ JRadioButton[] optionButtons = new JRadioButton[4];
+
+ for (int i = 0; i < 4; i++) {
+ optionButtons[i] = new JRadioButton((char) ('A' + i) + ". " + question.getOptions()[i]);
+ optionButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 14));
+ optionButtons[i].setActionCommand(String.valueOf(i));
+ answerGroup.add(optionButtons[i]);
+ optionsPanel.add(optionButtons[i]);
+ optionsPanel.add(Box.createVerticalStrut(12));
}
- });
- JScrollPane scrollPane = new JScrollPane(optionsPanel);
- scrollPane.setBorder(BorderFactory.createEmptyBorder());
- scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
- scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ // 提交按钮
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout());
+ buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 10, 10, 10));
- mainPanel.add(infoPanel, BorderLayout.NORTH);
- mainPanel.add(scrollPane, BorderLayout.CENTER);
+ JButton submitButton = createStyledButton("提交答案", new Color(76, 175, 80), 140, 40);
+ submitButton.setFont(new Font("微软雅黑", Font.BOLD, 14));
- JPanel bottomPanel = new JPanel(new BorderLayout());
- bottomPanel.add(buttonPanel, BorderLayout.NORTH);
- bottomPanel.add(messageLabel, BorderLayout.SOUTH);
+ submitButton.addActionListener(e -> {
+ ButtonModel selectedModel = answerGroup.getSelection();
+ if (selectedModel == null) {
+ JOptionPane.showMessageDialog(mainFrame, "请选择一个答案!", "提示", JOptionPane.WARNING_MESSAGE);
+ return;
+ }
+ int selectedIndex = Integer.parseInt(selectedModel.getActionCommand());
+ answerListener.onAnswerSubmit(selectedIndex);
+ });
- mainPanel.add(bottomPanel, BorderLayout.SOUTH);
+ buttonPanel.add(submitButton);
- mainFrame.setContentPane(mainPanel);
- mainFrame.revalidate();
- mainFrame.repaint();
- mainFrame.setSize(550, 500);
- mainFrame.setLocationRelativeTo(null);
- }
+ JScrollPane scrollPane = new JScrollPane(optionsPanel);
+ scrollPane.setBorder(BorderFactory.createEmptyBorder());
+ scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- private void updateQuestionDisplay(JLabel numberLabel, JLabel contentLabel, JRadioButton[] optionButtons) {
- QuizController.Question current = quizController.getCurrentQuestion();
- if (current != null) {
- numberLabel.setText("第 " + quizController.getCurrentQuestionNumber() +
- " 题 / 共 " + quizController.getTotalQuestions() + " 题");
- contentLabel.setText("" + current.getContent() + "");
+ panel.add(infoPanel, BorderLayout.NORTH);
+ panel.add(scrollPane, BorderLayout.CENTER);
+ panel.add(buttonPanel, BorderLayout.SOUTH);
- String[] options = current.getOptions();
- for (int i = 0; i < 4; i++) {
- optionButtons[i].setText((char) ('A' + i) + ". " + options[i]);
+ return panel;
+ }
+
+ public JPanel buildScoreView(int score, int total, double percentage, Runnable continueAction) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
+
+ JLabel titleLabel = new JLabel("答题完成!");
+ titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
+ titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JLabel scoreLabel = new JLabel("得分: " + score + "/" + total);
+ scoreLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
+ scoreLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JLabel percentageLabel = new JLabel("正确率: " + String.format("%.1f", percentage) + "%");
+ percentageLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+ percentageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ if (percentage >= 80) {
+ percentageLabel.setForeground(new Color(76, 175, 80));
+ } else if (percentage >= 60) {
+ percentageLabel.setForeground(new Color(255, 152, 0));
+ } else {
+ percentageLabel.setForeground(new Color(244, 67, 54));
}
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout());
+ buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JButton continueButton = createStyledButton("继续做题", new Color(76, 175, 80), 120, 35);
+
+ continueButton.addActionListener(e -> continueAction.run());
+
+ buttonPanel.add(continueButton);
+
+ panel.add(Box.createVerticalStrut(20));
+ panel.add(titleLabel);
+ panel.add(Box.createVerticalStrut(30));
+ panel.add(scoreLabel);
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(percentageLabel);
+ panel.add(Box.createVerticalStrut(40));
+ panel.add(buttonPanel);
+
+ return panel;
}
- }
- // 分数界面 - 完全保持不变
- private void showScoreView() {
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- mainPanel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
+ public JPanel buildChangePasswordView(PasswordChangeListener changeListener, Runnable backAction) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
+
+ JLabel titleLabel = new JLabel("修改密码");
+ titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
+ titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JPanel inputPanel = new JPanel();
+ inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
+ inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JPasswordField oldPasswordField = new JPasswordField(20);
+ JPasswordField newPasswordField = new JPasswordField(20);
+ JPasswordField confirmPasswordField = new JPasswordField(20);
+
+ JPanel oldPasswordPanel = createLabelFieldPanel("原密码:", oldPasswordField);
+ JPanel newPasswordPanel = createLabelFieldPanel("新密码:", newPasswordField);
+ JPanel confirmPasswordPanel = createLabelFieldPanel("确认密码:", confirmPasswordField);
+
+ inputPanel.add(oldPasswordPanel);
+ inputPanel.add(Box.createVerticalStrut(15));
+ inputPanel.add(newPasswordPanel);
+ inputPanel.add(Box.createVerticalStrut(15));
+ inputPanel.add(confirmPasswordPanel);
+
+ // 添加消息标签
+ JLabel messageLabel = new JLabel(" ");
+ messageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ messageLabel.setForeground(Color.RED);
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout());
+ buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ JButton submitButton = createStyledButton("确认修改", new Color(76, 175, 80), 120, 35);
+ JButton backButton = createStyledButton("返回", new Color(158, 158, 158), 120, 35);
+
+ submitButton.addActionListener(e -> {
+ String oldPassword = new String(oldPasswordField.getPassword());
+ String newPassword = new String(newPasswordField.getPassword());
+ String confirmPassword = new String(confirmPasswordField.getPassword());
+
+ // 客户端验证
+ if (oldPassword.isEmpty() || newPassword.isEmpty() || confirmPassword.isEmpty()) {
+ messageLabel.setText("请填写所有密码字段!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
- JLabel titleLabel = new JLabel("答题完成!");
- titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
- titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ if (!newPassword.equals(confirmPassword)) {
+ messageLabel.setText("两次输入的新密码不一致!");
+ messageLabel.setForeground(Color.RED);
+ return;
+ }
- int score = quizController.getScore();
- int total = quizController.getTotalQuestions();
- double percentage = quizController.getPercentage();
+ // 调用控制器处理密码修改
+ boolean success = changeListener.onPasswordChange(oldPassword, newPassword, confirmPassword);
+
+ if (success) {
+ messageLabel.setText("密码修改成功!");
+ messageLabel.setForeground(Color.GREEN);
+ // 清空密码框
+ oldPasswordField.setText("");
+ newPasswordField.setText("");
+ confirmPasswordField.setText("");
+ } else {
+ messageLabel.setText("密码修改失败!请检查原密码是否正确,新密码是否符合要求。");
+ messageLabel.setForeground(Color.RED);
+ }
+ });
+
+ backButton.addActionListener(e -> backAction.run());
- JLabel scoreLabel = new JLabel("得分: " + score + "/" + total);
- scoreLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
- scoreLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ buttonPanel.add(submitButton);
+ buttonPanel.add(Box.createHorizontalStrut(20));
+ buttonPanel.add(backButton);
- JLabel percentageLabel = new JLabel("正确率: " + String.format("%.1f", percentage) + "%");
- percentageLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
- percentageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(titleLabel);
+ panel.add(Box.createVerticalStrut(25));
+ panel.add(inputPanel);
+ panel.add(Box.createVerticalStrut(15));
+ panel.add(messageLabel); // 添加消息标签到面板
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(buttonPanel);
- if (percentage >= 80) {
- percentageLabel.setForeground(new Color(76, 175, 80));
- } else if (percentage >= 60) {
- percentageLabel.setForeground(new Color(255, 152, 0));
- } else {
- percentageLabel.setForeground(new Color(244, 67, 54));
+ return panel;
}
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout());
- buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JButton continueButton = new JButton("继续做题");
- continueButton.setBackground(new Color(76, 175, 80));
- continueButton.setForeground(Color.WHITE);
- continueButton.setPreferredSize(new Dimension(120, 35));
- continueButton.setOpaque(true);
- continueButton.setBorderPainted(false);
- continueButton.setFocusPainted(false);
-
- JButton exitButton = new JButton("退出");
- exitButton.setBackground(new Color(158, 158, 158));
- exitButton.setForeground(Color.WHITE);
- exitButton.setPreferredSize(new Dimension(120, 35));
- exitButton.setOpaque(true);
- exitButton.setBorderPainted(false);
- exitButton.setFocusPainted(false);
-
- buttonPanel.add(continueButton);
- buttonPanel.add(Box.createHorizontalStrut(20));
- buttonPanel.add(exitButton);
-
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(titleLabel);
- mainPanel.add(Box.createVerticalStrut(30));
- mainPanel.add(scoreLabel);
- mainPanel.add(Box.createVerticalStrut(10));
- mainPanel.add(percentageLabel);
- mainPanel.add(Box.createVerticalStrut(40));
- mainPanel.add(buttonPanel);
-
- continueButton.addActionListener(e -> showMainView());
- exitButton.addActionListener(e -> showMainView());
+ // ==================== 辅助方法 ====================
- mainFrame.setContentPane(mainPanel);
- mainFrame.revalidate();
- mainFrame.repaint();
+ private JPanel createLabelFieldPanel(String labelText, JComponent field) {
+ JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ panel.add(new JLabel(labelText));
+ panel.add(field);
+ return panel;
+ }
+
+ private JButton createStyledButton(String text, Color color, int width, int height) {
+ JButton button = new JButton(text);
+ button.setBackground(color);
+ button.setForeground(Color.WHITE);
+ button.setPreferredSize(new Dimension(width, height));
+ button.setOpaque(true);
+ button.setBorderPainted(false);
+ button.setFocusPainted(false);
+ return button;
+ }
+
+ private JButton createDifficultyButton(String text, Color color) {
+ JButton button = createStyledButton(text, color, 140, 45);
+ button.setFont(new Font("微软雅黑", Font.BOLD, 16));
+ button.setMaximumSize(new Dimension(140, 45));
+ button.setAlignmentX(Component.CENTER_ALIGNMENT);
+ return button;
+ }
}
- // 修改密码界面 - 完全保持不变
- private void showChangePasswordView() {
- JPanel mainPanel = new JPanel();
- mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
-
- JLabel titleLabel = new JLabel("修改密码");
- titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
- titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel inputPanel = new JPanel();
- inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS));
- inputPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JPanel oldPasswordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel oldPasswordLabel = new JLabel("原密码:");
- JPasswordField oldPasswordField = new JPasswordField(20);
- oldPasswordField.setPreferredSize(new Dimension(200, 30));
- oldPasswordPanel.add(oldPasswordLabel);
- oldPasswordPanel.add(oldPasswordField);
-
- JPanel newPasswordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel newPasswordLabel = new JLabel("新密码:");
- JPasswordField newPasswordField = new JPasswordField(20);
- newPasswordField.setPreferredSize(new Dimension(200, 30));
- newPasswordPanel.add(newPasswordLabel);
- newPasswordPanel.add(newPasswordField);
-
- JPanel confirmPasswordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- JLabel confirmPasswordLabel = new JLabel("确认密码:");
- JPasswordField confirmPasswordField = new JPasswordField(20);
- confirmPasswordField.setPreferredSize(new Dimension(200, 30));
- confirmPasswordPanel.add(confirmPasswordLabel);
- confirmPasswordPanel.add(confirmPasswordField);
-
- inputPanel.add(oldPasswordPanel);
- inputPanel.add(Box.createVerticalStrut(15));
- inputPanel.add(newPasswordPanel);
- inputPanel.add(Box.createVerticalStrut(15));
- inputPanel.add(confirmPasswordPanel);
-
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout());
- buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-
- JButton submitButton = new JButton("确认修改");
- submitButton.setBackground(new Color(76, 175, 80));
- submitButton.setForeground(Color.WHITE);
- submitButton.setPreferredSize(new Dimension(120, 35));
- submitButton.setOpaque(true);
- submitButton.setBorderPainted(false);
- submitButton.setFocusPainted(false);
-
- JButton backButton = new JButton("返回");
- backButton.setBackground(new Color(158, 158, 158));
- backButton.setForeground(Color.WHITE);
- backButton.setPreferredSize(new Dimension(120, 35));
- backButton.setOpaque(true);
- backButton.setBorderPainted(false);
- backButton.setFocusPainted(false);
-
- buttonPanel.add(submitButton);
- buttonPanel.add(Box.createHorizontalStrut(20));
- buttonPanel.add(backButton);
-
- JLabel messageLabel = new JLabel(" ");
- messageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
- messageLabel.setForeground(Color.RED);
-
- mainPanel.add(Box.createVerticalStrut(10));
- mainPanel.add(titleLabel);
- mainPanel.add(Box.createVerticalStrut(25));
- mainPanel.add(inputPanel);
- mainPanel.add(Box.createVerticalStrut(25));
- mainPanel.add(buttonPanel);
- mainPanel.add(Box.createVerticalStrut(20));
- mainPanel.add(messageLabel);
-
- submitButton.addActionListener(e -> {
- String oldPassword = new String(oldPasswordField.getPassword());
- String newPassword = new String(newPasswordField.getPassword());
- String confirmPassword = new String(confirmPasswordField.getPassword());
+ /**
+ * 事件处理器 - 负责管理事件监听
+ */
+ private class EventHandlers {
+ // 可以在这里添加复杂的事件处理逻辑
+ // 目前事件处理直接在内联监听器中实现
+ }
- if (!newPassword.equals(confirmPassword)) {
- messageLabel.setText("两次输入的新密码不一致!");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ // =========================================================================
+ // 监听器接口定义
+ // =========================================================================
- if (!userManager.isValidPassword(newPassword)) {
- messageLabel.setText("密码不符合要求:
- 长度必须在6-10位之间
- 必须包含大写字母、小写字母和数字");
- messageLabel.setForeground(Color.RED);
- return;
- }
+ private interface LoginListener {
+ void onLogin(String email, String password);
+ }
- if (userManager.changePassword(oldPassword, newPassword)) {
- messageLabel.setText("密码修改成功!");
- messageLabel.setForeground(Color.GREEN);
- } else {
- messageLabel.setText("密码修改失败!请检查原密码是否正确,新密码是否符合要求。");
- messageLabel.setForeground(Color.RED);
- }
- });
+ private interface SendCodeListener {
+ boolean onSendCode(String username, String email);
+ }
- backButton.addActionListener(e -> showMainView());
+ private interface RegisterListener {
+ boolean onRegister(String username, String email, String code, String password, String confirmPassword);
+ }
- mainFrame.setContentPane(mainPanel);
- mainFrame.revalidate();
- mainFrame.repaint();
+ private interface DifficultySelectListener {
+ void onDifficultySelected(String difficulty);
}
- private boolean isValidEmail(String email) {
- String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
- return email != null && email.matches(emailRegex);
+ private interface CountSubmitListener {
+ void onCountSubmit(int count);
+ }
+
+ private interface AnswerSubmitListener {
+ void onAnswerSubmit(int answer);
+ }
+
+ private interface PasswordChangeListener {
+ boolean onPasswordChange(String oldPassword, String newPassword, String confirmPassword);
}
}
\ No newline at end of file