parent
997acd73ec
commit
e2e0d99656
@ -1,97 +0,0 @@
|
||||
// src/main/java/com/wsf/mathapp/App.java
|
||||
package com.wsf.mathapp;
|
||||
|
||||
import com.wsf.mathapp.controller.LoginController;
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
|
||||
public class App extends Application {
|
||||
|
||||
private Stage primaryStage;
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws IOException {
|
||||
this.primaryStage = primaryStage;
|
||||
this.primaryStage.setTitle("数学学习软件");
|
||||
|
||||
showLoginScene();
|
||||
}
|
||||
|
||||
public void showLoginScene() throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/wsf/mathapp/view/fxml/login.fxml"));
|
||||
Parent root = loader.load();
|
||||
LoginController controller = loader.getController();
|
||||
controller.setApp(this);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
scene.getStylesheets().add(getClass().getResource("/com/wsf/mathapp/view/css/styles.css").toExternalForm());
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.show();
|
||||
}
|
||||
|
||||
public void showRegisterScene() throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/wsf/mathapp/view/fxml/register.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
scene.getStylesheets().add(getClass().getResource("/com/wsf/mathapp/view/css/styles.css").toExternalForm());
|
||||
primaryStage.setScene(scene);
|
||||
}
|
||||
|
||||
public void showSetPasswordScene(String email) throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/wsf/mathapp/view/fxml/set_password.fxml"));
|
||||
Parent root = loader.load();
|
||||
// Pass email to SetPasswordController if needed
|
||||
// SetPasswordController controller = loader.getController();
|
||||
// controller.setEmail(email);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
scene.getStylesheets().add(getClass().getResource("/com/wsf/mathapp/view/css/styles.css").toExternalForm());
|
||||
primaryStage.setScene(scene);
|
||||
}
|
||||
|
||||
public void showGradeSelectionScene() throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/wsf/mathapp/view/fxml/grade_selection.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
scene.getStylesheets().add(getClass().getResource("/com/wsf/mathapp/view/css/styles.css").toExternalForm());
|
||||
primaryStage.setScene(scene);
|
||||
}
|
||||
|
||||
public void showQuestionScene(java.util.List<com.wsf.mathapp.model.Question> questions) throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/wsf/mathapp/view/fxml/question.fxml"));
|
||||
Parent root = loader.load();
|
||||
com.wsf.mathapp.controller.QuestionController controller = loader.getController();
|
||||
controller.setApp(this);
|
||||
controller.setQuestions(questions);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
scene.getStylesheets().add(getClass().getResource("/com/wsf/mathapp/view/css/styles.css").toExternalForm());
|
||||
primaryStage.setScene(scene);
|
||||
}
|
||||
|
||||
public void showResultScene(com.wsf.mathapp.model.QuizResult result) throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/wsf/mathapp/view/fxml/result.fxml"));
|
||||
Parent root = loader.load();
|
||||
com.wsf.mathapp.controller.ResultController controller = loader.getController();
|
||||
controller.setApp(this);
|
||||
controller.setResult(result);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
scene.getStylesheets().add(getClass().getResource("/com/wsf/mathapp/view/css/styles.css").toExternalForm());
|
||||
primaryStage.setScene(scene);
|
||||
}
|
||||
|
||||
public Stage getPrimaryStage() {
|
||||
return primaryStage;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.wsf.mathapp;
|
||||
|
||||
import com.wsf.mathapp.controller.SceneManager;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class Main extends Application {
|
||||
@Override
|
||||
public void start(Stage primaryStage) {
|
||||
SceneManager sceneManager = new SceneManager(primaryStage);
|
||||
sceneManager.showLoginView();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.PasswordField?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/17.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.wsf.mathapp.controller.LoginController">
|
||||
<children>
|
||||
<Label text="登录" />
|
||||
<TextField fx:id="emailField" promptText="邮箱" />
|
||||
<PasswordField fx:id="passwordField" promptText="密码" />
|
||||
<Button fx:id="loginButton" onAction="#handleLogin" text="登录" />
|
||||
<Button fx:id="registerButton" onAction="#handleRegister" text="注册" />
|
||||
<Label fx:id="messageLabel" textFill="RED" />
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
@ -1,75 +0,0 @@
|
||||
// src/main/java/com/wsf/mathapp/controller/LoginController.java
|
||||
package com.wsf.mathapp.controller;
|
||||
|
||||
import com.wsf.mathapp.App;
|
||||
import com.wsf.mathapp.model.User;
|
||||
import com.wsf.mathapp.service.BackendService; // 需要后端实现
|
||||
import com.wsf.mathapp.util.ValidationUtils;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
public class LoginController {
|
||||
|
||||
@FXML private TextField emailField;
|
||||
@FXML private PasswordField passwordField;
|
||||
@FXML private Button loginButton;
|
||||
@FXML private Button registerButton;
|
||||
@FXML private Label messageLabel;
|
||||
|
||||
private App app;
|
||||
private BackendService backendService; // 需要注入后端服务实现
|
||||
|
||||
public void setApp(App app) {
|
||||
this.app = app;
|
||||
// 示例:注入后端服务实现
|
||||
// this.backendService = new MyBackendServiceImpl(); // 你需要后端同学提供实现
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleLogin() {
|
||||
String email = emailField.getText().trim();
|
||||
String password = passwordField.getText();
|
||||
|
||||
// 1. 验证邮箱格式 (需求:对注册邮箱进行格式校验)
|
||||
if (!ValidationUtils.isValidEmail(email)) {
|
||||
messageLabel.setText("请输入有效的邮箱地址");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 验证密码是否为空 (需求:不输入密码也能直接进入主功能页面 -> 修复)
|
||||
if (password.isEmpty()) {
|
||||
messageLabel.setText("请输入密码");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 调用后端服务进行登录
|
||||
User user = backendService.loginUser(email, password);
|
||||
if (user != null) {
|
||||
messageLabel.setText("登录成功");
|
||||
try {
|
||||
// 登录成功后跳转到年级选择界面
|
||||
app.showGradeSelectionScene();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
messageLabel.setText("界面跳转失败");
|
||||
}
|
||||
} else {
|
||||
// 4. 登录失败,显示错误信息 (需求:无法使用已注册用户登陆)
|
||||
messageLabel.setText("邮箱或密码错误");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleRegister() {
|
||||
try {
|
||||
// 点击注册按钮,跳转到注册界面
|
||||
app.showRegisterScene();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
messageLabel.setText("界面跳转失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package com.wsf.mathapp.controller;
|
||||
|
||||
import com.wsf.mathapp.view.*;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class SceneManager {
|
||||
private Stage primaryStage;
|
||||
private LoginView loginView;
|
||||
private RegisterView registerView;
|
||||
private MainMenuView mainMenuView;
|
||||
private LevelSelectionView levelSelectionView;
|
||||
private QuestionCountView questionCountView;
|
||||
private QuizView quizView;
|
||||
private ResultView resultView;
|
||||
|
||||
public SceneManager(Stage primaryStage) {
|
||||
this.primaryStage = primaryStage;
|
||||
this.primaryStage.setTitle("数学学习软件");
|
||||
this.primaryStage.setResizable(false);
|
||||
|
||||
// 初始化所有视图
|
||||
this.loginView = new LoginView(this);
|
||||
this.registerView = new RegisterView(this);
|
||||
this.mainMenuView = new MainMenuView(this);
|
||||
this.levelSelectionView = new LevelSelectionView(this);
|
||||
this.questionCountView = new QuestionCountView(this);
|
||||
this.quizView = new QuizView(this);
|
||||
this.resultView = new ResultView(this);
|
||||
}
|
||||
|
||||
public void showLoginView() {
|
||||
primaryStage.setScene(loginView.getScene());
|
||||
primaryStage.show();
|
||||
}
|
||||
|
||||
public void showRegisterView() {
|
||||
primaryStage.setScene(registerView.getScene());
|
||||
}
|
||||
|
||||
public void showMainMenuView() {
|
||||
primaryStage.setScene(mainMenuView.getScene());
|
||||
}
|
||||
|
||||
public void showLevelSelectionView() {
|
||||
primaryStage.setScene(levelSelectionView.getScene());
|
||||
}
|
||||
|
||||
public void showQuestionCountView() {
|
||||
primaryStage.setScene(questionCountView.getScene());
|
||||
}
|
||||
|
||||
public void showQuizView() {
|
||||
primaryStage.setScene(quizView.getScene());
|
||||
}
|
||||
|
||||
public void showResultView(double score) {
|
||||
resultView.setScore(score);
|
||||
primaryStage.setScene(resultView.getScene());
|
||||
}
|
||||
|
||||
// Getter methods for views
|
||||
public LoginView getLoginView() { return loginView; }
|
||||
public RegisterView getRegisterView() { return registerView; }
|
||||
public MainMenuView getMainMenuView() { return mainMenuView; }
|
||||
public LevelSelectionView getLevelSelectionView() { return levelSelectionView; }
|
||||
public QuestionCountView getQuestionCountView() { return questionCountView; }
|
||||
public QuizView getQuizView() { return quizView; }
|
||||
public ResultView getResultView() { return resultView; }
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.wsf.mathapp.service;
|
||||
|
||||
import com.ybw.mathapp.service.ChoiceGenerator;
|
||||
import com.ybw.mathapp.service.PrimarySchoolGenerator;
|
||||
import com.ybw.mathapp.service.JuniorHighGenerator;
|
||||
import com.ybw.mathapp.service.SeniorHighGenerator;
|
||||
import com.ybw.mathapp.service.QuestionGenerator;
|
||||
import java.util.List;
|
||||
|
||||
public class QuestionService {
|
||||
|
||||
public QuestionGenerator createGenerator(String level) {
|
||||
switch (level) {
|
||||
case "小学":
|
||||
return new PrimarySchoolGenerator();
|
||||
case "初中":
|
||||
return new JuniorHighGenerator();
|
||||
case "高中":
|
||||
return new SeniorHighGenerator();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<ChoiceGenerator.MultipleChoiceQuestion> generateQuestions(String level, int count) {
|
||||
QuestionGenerator generator = createGenerator(level);
|
||||
if (generator == null) {
|
||||
throw new IllegalArgumentException("不支持的题目级别: " + level);
|
||||
}
|
||||
|
||||
ChoiceGenerator choiceGenerator = new ChoiceGenerator(generator);
|
||||
return choiceGenerator.generateMultipleChoiceQuestions(count);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.wsf.mathapp.service;
|
||||
|
||||
import com.ybw.mathapp.util.LoginFileUtils;
|
||||
|
||||
public class UserService {
|
||||
|
||||
public boolean register(String email, String password, String confirmPassword) {
|
||||
// 验证邮箱格式
|
||||
if (!isValidEmail(email)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查邮箱是否已注册
|
||||
if (LoginFileUtils.isEmailRegistered(email)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证密码格式和匹配
|
||||
if (!isValidPassword(password, confirmPassword)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建用户并保存
|
||||
com.ybw.mathapp.entity.User user = new com.ybw.mathapp.entity.User(email, password);
|
||||
LoginFileUtils.saveUser(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean login(String email, String password) {
|
||||
return LoginFileUtils.validateUser(email, password);
|
||||
}
|
||||
|
||||
public boolean changePassword(String email, String oldPassword, String newPassword, String confirmPassword) {
|
||||
// 验证旧密码
|
||||
if (!LoginFileUtils.validateUser(email, oldPassword)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证新密码格式和匹配
|
||||
if (!isValidPassword(newPassword, confirmPassword)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新密码逻辑
|
||||
return updateUserPassword(email, newPassword);
|
||||
}
|
||||
|
||||
private boolean updateUserPassword(String email, String newPassword) {
|
||||
// 实现密码更新逻辑
|
||||
// 这里需要扩展后端的LoginFileUtils来支持密码更新
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidEmail(String email) {
|
||||
if (email == null || email.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return email.contains("@") && email.contains(".");
|
||||
}
|
||||
|
||||
private boolean isValidPassword(String password, String confirmPassword) {
|
||||
if (password == null || password.length() < 6 || password.length() > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证密码格式:必须包含大小写字母和数字
|
||||
boolean hasLower = false, hasUpper = false, hasDigit = false;
|
||||
for (char c : password.toCharArray()) {
|
||||
if (Character.isLowerCase(c)) hasLower = true;
|
||||
if (Character.isUpperCase(c)) hasUpper = true;
|
||||
if (Character.isDigit(c)) hasDigit = true;
|
||||
}
|
||||
|
||||
if (!hasLower || !hasUpper || !hasDigit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证两次输入是否一致
|
||||
return password.equals(confirmPassword);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.wsf.mathapp.view;
|
||||
|
||||
import com.wsf.mathapp.controller.SceneManager;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Font;
|
||||
|
||||
public class LevelSelectionView {
|
||||
private Scene scene;
|
||||
private SceneManager sceneManager;
|
||||
|
||||
public LevelSelectionView(SceneManager sceneManager) {
|
||||
this.sceneManager = sceneManager;
|
||||
createScene();
|
||||
}
|
||||
|
||||
private void createScene() {
|
||||
VBox root = new VBox(20);
|
||||
root.setPadding(new Insets(40));
|
||||
root.setAlignment(Pos.CENTER);
|
||||
|
||||
Label titleLabel = new Label("选择题目级别");
|
||||
titleLabel.setFont(Font.font(24));
|
||||
|
||||
Button primaryButton = new Button("小学题目");
|
||||
primaryButton.setStyle("-fx-background-color: #4CAF50; -fx-text-fill: white; -fx-font-size: 14px;");
|
||||
primaryButton.setPrefSize(200, 50);
|
||||
|
||||
Button juniorButton = new Button("初中题目");
|
||||
juniorButton.setStyle("-fx-background-color: #2196F3; -fx-text-fill: white; -fx-font-size: 14px;");
|
||||
juniorButton.setPrefSize(200, 50);
|
||||
|
||||
Button seniorButton = new Button("高中题目");
|
||||
seniorButton.setStyle("-fx-background-color: #9C27B0; -fx-text-fill: white; -fx-font-size: 14px;");
|
||||
seniorButton.setPrefSize(200, 50);
|
||||
|
||||
Button backButton = new Button("返回");
|
||||
backButton.setStyle("-fx-background-color: #757575; -fx-text-fill: white;");
|
||||
backButton.setPrefSize(200, 40);
|
||||
|
||||
primaryButton.setOnAction(e -> {
|
||||
String selectedLevel = "小学";
|
||||
sceneManager.getQuestionCountView().setLevel(selectedLevel);
|
||||
sceneManager.showQuestionCountView();
|
||||
});
|
||||
|
||||
juniorButton.setOnAction(e -> {
|
||||
String selectedLevel = "初中";
|
||||
sceneManager.getQuestionCountView().setLevel(selectedLevel);
|
||||
sceneManager.showQuestionCountView();
|
||||
});
|
||||
|
||||
seniorButton.setOnAction(e -> {
|
||||
String selectedLevel = "高中";
|
||||
sceneManager.getQuestionCountView().setLevel(selectedLevel);
|
||||
sceneManager.showQuestionCountView();
|
||||
});
|
||||
|
||||
backButton.setOnAction(e -> {
|
||||
sceneManager.showMainMenuView();
|
||||
});
|
||||
|
||||
root.getChildren().addAll(
|
||||
titleLabel, primaryButton, juniorButton, seniorButton, backButton
|
||||
);
|
||||
|
||||
scene = new Scene(root, 400, 500);
|
||||
}
|
||||
|
||||
public Scene getScene() {
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.wsf.mathapp.view;
|
||||
|
||||
import com.wsf.mathapp.controller.SceneManager;
|
||||
import com.wsf.mathapp.service.UserService;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Font;
|
||||
|
||||
public class LoginView {
|
||||
private Scene scene;
|
||||
private SceneManager sceneManager;
|
||||
private UserService userService;
|
||||
|
||||
public LoginView(SceneManager sceneManager) {
|
||||
this.sceneManager = sceneManager;
|
||||
this.userService = new UserService();
|
||||
createScene();
|
||||
}
|
||||
|
||||
private void createScene() {
|
||||
VBox root = new VBox(20);
|
||||
root.setPadding(new Insets(40));
|
||||
root.setAlignment(Pos.CENTER);
|
||||
|
||||
Label titleLabel = new Label("数学学习软件");
|
||||
titleLabel.setFont(Font.font(24));
|
||||
|
||||
Label subtitleLabel = new Label("用户登录");
|
||||
subtitleLabel.setFont(Font.font(18));
|
||||
|
||||
TextField emailField = new TextField();
|
||||
emailField.setPromptText("请输入邮箱");
|
||||
emailField.setMaxWidth(300);
|
||||
emailField.setPrefHeight(40);
|
||||
|
||||
PasswordField passwordField = new PasswordField();
|
||||
passwordField.setPromptText("请输入密码");
|
||||
passwordField.setMaxWidth(300);
|
||||
passwordField.setPrefHeight(40);
|
||||
|
||||
Button loginButton = new Button("登录");
|
||||
loginButton.setStyle("-fx-background-color: #4CAF50; -fx-text-fill: white; -fx-font-size: 14px;");
|
||||
loginButton.setPrefSize(300, 40);
|
||||
|
||||
Button registerButton = new Button("注册账号");
|
||||
registerButton.setStyle("-fx-background-color: #2196F3; -fx-text-fill: white; -fx-font-size: 14px;");
|
||||
registerButton.setPrefSize(300, 40);
|
||||
|
||||
Label statusLabel = new Label();
|
||||
|
||||
loginButton.setOnAction(e -> {
|
||||
String email = emailField.getText().trim();
|
||||
String password = passwordField.getText();
|
||||
|
||||
if (email.isEmpty() || password.isEmpty()) {
|
||||
showError(statusLabel, "邮箱和密码不能为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean success = userService.login(email, password);
|
||||
if (success) {
|
||||
showSuccess(statusLabel, "登录成功!");
|
||||
sceneManager.showMainMenuView();
|
||||
} else {
|
||||
showError(statusLabel, "邮箱或密码错误!");
|
||||
}
|
||||
});
|
||||
|
||||
registerButton.setOnAction(e -> {
|
||||
sceneManager.showRegisterView();
|
||||
});
|
||||
|
||||
root.getChildren().addAll(
|
||||
titleLabel, subtitleLabel, emailField, passwordField,
|
||||
loginButton, registerButton, statusLabel
|
||||
);
|
||||
|
||||
scene = new Scene(root, 400, 500);
|
||||
}
|
||||
|
||||
private void showError(Label label, String message) {
|
||||
label.setText(message);
|
||||
label.setStyle("-fx-text-fill: red;");
|
||||
}
|
||||
|
||||
private void showSuccess(Label label, String message) {
|
||||
label.setText(message);
|
||||
label.setStyle("-fx-text-fill: green;");
|
||||
}
|
||||
|
||||
public Scene getScene() {
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,112 @@
|
||||
package com.wsf.mathapp.view;
|
||||
|
||||
import com.wsf.mathapp.controller.SceneManager;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Font;
|
||||
|
||||
public class MainMenuView {
|
||||
private Scene scene;
|
||||
private SceneManager sceneManager;
|
||||
|
||||
public MainMenuView(SceneManager sceneManager) {
|
||||
this.sceneManager = sceneManager;
|
||||
createScene();
|
||||
}
|
||||
|
||||
private void createScene() {
|
||||
VBox root = new VBox(30);
|
||||
root.setPadding(new Insets(50));
|
||||
root.setAlignment(Pos.CENTER);
|
||||
|
||||
Label titleLabel = new Label("数学学习软件");
|
||||
titleLabel.setFont(Font.font(28));
|
||||
|
||||
Label welcomeLabel = new Label("欢迎使用数学学习软件");
|
||||
welcomeLabel.setFont(Font.font(18));
|
||||
|
||||
Button startButton = new Button("开始练习");
|
||||
startButton.setStyle("-fx-background-color: #4CAF50; -fx-text-fill: white; -fx-font-size: 16px;");
|
||||
startButton.setPrefSize(200, 50);
|
||||
|
||||
Button changePasswordButton = new Button("修改密码");
|
||||
changePasswordButton.setStyle("-fx-background-color: #2196F3; -fx-text-fill: white; -fx-font-size: 16px;");
|
||||
changePasswordButton.setPrefSize(200, 50);
|
||||
|
||||
Button logoutButton = new Button("退出登录");
|
||||
logoutButton.setStyle("-fx-background-color: #f44336; -fx-text-fill: white; -fx-font-size: 16px;");
|
||||
logoutButton.setPrefSize(200, 50);
|
||||
|
||||
startButton.setOnAction(e -> {
|
||||
sceneManager.showLevelSelectionView();
|
||||
});
|
||||
|
||||
changePasswordButton.setOnAction(e -> {
|
||||
showChangePasswordDialog();
|
||||
});
|
||||
|
||||
logoutButton.setOnAction(e -> {
|
||||
sceneManager.showLoginView();
|
||||
});
|
||||
|
||||
root.getChildren().addAll(
|
||||
titleLabel, welcomeLabel, startButton,
|
||||
changePasswordButton, logoutButton
|
||||
);
|
||||
|
||||
scene = new Scene(root, 400, 500);
|
||||
}
|
||||
|
||||
private void showChangePasswordDialog() {
|
||||
// 创建修改密码对话框
|
||||
javafx.scene.control.Dialog<Void> dialog = new javafx.scene.control.Dialog<>();
|
||||
dialog.setTitle("修改密码");
|
||||
dialog.setHeaderText("请输入密码信息");
|
||||
|
||||
// 创建表单
|
||||
javafx.scene.layout.GridPane grid = new javafx.scene.layout.GridPane();
|
||||
grid.setHgap(10);
|
||||
grid.setVgap(10);
|
||||
grid.setPadding(new Insets(20, 150, 10, 10));
|
||||
|
||||
javafx.scene.control.PasswordField oldPassword = new javafx.scene.control.PasswordField();
|
||||
oldPassword.setPromptText("原密码");
|
||||
javafx.scene.control.PasswordField newPassword = new javafx.scene.control.PasswordField();
|
||||
newPassword.setPromptText("新密码");
|
||||
javafx.scene.control.PasswordField confirmPassword = new javafx.scene.control.PasswordField();
|
||||
confirmPassword.setPromptText("确认新密码");
|
||||
|
||||
grid.add(new Label("原密码:"), 0, 0);
|
||||
grid.add(oldPassword, 1, 0);
|
||||
grid.add(new Label("新密码:"), 0, 1);
|
||||
grid.add(newPassword, 1, 1);
|
||||
grid.add(new Label("确认密码:"), 0, 2);
|
||||
grid.add(confirmPassword, 1, 2);
|
||||
|
||||
dialog.getDialogPane().setContent(grid);
|
||||
|
||||
// 添加按钮
|
||||
dialog.getDialogPane().getButtonTypes().addAll(
|
||||
javafx.scene.control.ButtonType.OK,
|
||||
javafx.scene.control.ButtonType.CANCEL
|
||||
);
|
||||
|
||||
dialog.setResultConverter(dialogButton -> {
|
||||
if (dialogButton == javafx.scene.control.ButtonType.OK) {
|
||||
// 这里可以添加修改密码的逻辑
|
||||
System.out.println("修改密码功能待实现");
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
dialog.showAndWait();
|
||||
}
|
||||
|
||||
public Scene getScene() {
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,148 @@
|
||||
package com.wsf.mathapp.view;
|
||||
|
||||
import com.wsf.mathapp.controller.SceneManager;
|
||||
import com.wsf.mathapp.service.QuestionService;
|
||||
import com.ybw.mathapp.service.ChoiceGenerator;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Font;
|
||||
import java.util.List;
|
||||
|
||||
public class QuizView {
|
||||
private Scene scene;
|
||||
private SceneManager sceneManager;
|
||||
private QuestionService questionService;
|
||||
private String currentLevel;
|
||||
private int questionCount;
|
||||
private List<ChoiceGenerator.MultipleChoiceQuestion> questions;
|
||||
private int currentQuestionIndex = 0;
|
||||
private int correctAnswers = 0;
|
||||
|
||||
private Label questionLabel;
|
||||
private ToggleGroup optionsGroup;
|
||||
private VBox optionsContainer;
|
||||
private Button nextButton;
|
||||
private Label progressLabel;
|
||||
private Label questionNumberLabel;
|
||||
|
||||
public QuizView(SceneManager sceneManager) {
|
||||
this.sceneManager = sceneManager;
|
||||
this.questionService = new QuestionService();
|
||||
createScene();
|
||||
}
|
||||
|
||||
private void createScene() {
|
||||
VBox root = new VBox(20);
|
||||
root.setPadding(new Insets(30));
|
||||
root.setAlignment(Pos.TOP_CENTER);
|
||||
|
||||
progressLabel = new Label();
|
||||
progressLabel.setFont(Font.font(14));
|
||||
|
||||
questionNumberLabel = new Label();
|
||||
questionNumberLabel.setFont(Font.font(16));
|
||||
questionNumberLabel.setStyle("-fx-text-fill: #666;");
|
||||
|
||||
questionLabel = new Label();
|
||||
questionLabel.setFont(Font.font(18));
|
||||
questionLabel.setWrapText(true);
|
||||
questionLabel.setStyle("-fx-padding: 10 0 20 0;");
|
||||
|
||||
optionsGroup = new ToggleGroup();
|
||||
optionsContainer = new VBox(15);
|
||||
optionsContainer.setAlignment(Pos.CENTER_LEFT);
|
||||
optionsContainer.setPadding(new Insets(10));
|
||||
|
||||
nextButton = new Button("下一题");
|
||||
nextButton.setStyle("-fx-background-color: #4CAF50; -fx-text-fill: white; -fx-font-size: 14px;");
|
||||
nextButton.setPrefSize(150, 40);
|
||||
nextButton.setDisable(true);
|
||||
|
||||
root.getChildren().addAll(progressLabel, questionNumberLabel, questionLabel, optionsContainer, nextButton);
|
||||
|
||||
scene = new Scene(root, 600, 500);
|
||||
}
|
||||
|
||||
public void setQuizParameters(String level, int count) {
|
||||
this.currentLevel = level;
|
||||
this.questionCount = count;
|
||||
this.currentQuestionIndex = 0;
|
||||
this.correctAnswers = 0;
|
||||
|
||||
// 生成题目
|
||||
generateQuestions();
|
||||
showQuestion(0);
|
||||
}
|
||||
|
||||
private void generateQuestions() {
|
||||
questions = questionService.generateQuestions(currentLevel, questionCount);
|
||||
}
|
||||
|
||||
private void showQuestion(int index) {
|
||||
if (index >= questions.size()) {
|
||||
// 所有题目已回答,显示结果
|
||||
double score = (double) correctAnswers / questions.size();
|
||||
sceneManager.showResultView(score);
|
||||
return;
|
||||
}
|
||||
|
||||
ChoiceGenerator.MultipleChoiceQuestion question = questions.get(index);
|
||||
|
||||
// 更新进度和题号
|
||||
progressLabel.setText("进度: " + (index + 1) + "/" + questions.size());
|
||||
questionNumberLabel.setText("第 " + (index + 1) + " 题");
|
||||
|
||||
// 设置题目内容
|
||||
String questionText = question.getQuestion();
|
||||
// 移除末尾的 "="
|
||||
if (questionText.endsWith(" =")) {
|
||||
questionText = questionText.substring(0, questionText.length() - 2);
|
||||
}
|
||||
questionLabel.setText(questionText + " = ?");
|
||||
|
||||
// 清空选项容器
|
||||
optionsContainer.getChildren().clear();
|
||||
optionsGroup = new ToggleGroup();
|
||||
|
||||
// 添加选项
|
||||
List<Double> options = question.getOptions();
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
RadioButton radioButton = new RadioButton((char)('A' + i) + ". " + options.get(i));
|
||||
radioButton.setToggleGroup(optionsGroup);
|
||||
radioButton.setFont(Font.font(14));
|
||||
radioButton.setWrapText(true);
|
||||
radioButton.setPrefWidth(500);
|
||||
optionsContainer.getChildren().add(radioButton);
|
||||
}
|
||||
|
||||
// 设置下一题按钮
|
||||
nextButton.setDisable(true);
|
||||
nextButton.setText(index == questions.size() - 1 ? "提交答案" : "下一题");
|
||||
nextButton.setOnAction(e -> {
|
||||
checkAnswer(question);
|
||||
showQuestion(index + 1);
|
||||
});
|
||||
|
||||
// 启用下一题按钮当选择了一个选项时
|
||||
optionsGroup.selectedToggleProperty().addListener((obs, oldVal, newVal) -> {
|
||||
nextButton.setDisable(newVal == null);
|
||||
});
|
||||
}
|
||||
|
||||
private void checkAnswer(ChoiceGenerator.MultipleChoiceQuestion question) {
|
||||
RadioButton selectedRadioButton = (RadioButton) optionsGroup.getSelectedToggle();
|
||||
if (selectedRadioButton != null) {
|
||||
int selectedIndex = optionsContainer.getChildren().indexOf(selectedRadioButton);
|
||||
if (selectedIndex == question.getCorrectIndex()) {
|
||||
correctAnswers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Scene getScene() {
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.wsf.mathapp.view;
|
||||
|
||||
import com.wsf.mathapp.controller.SceneManager;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Font;
|
||||
|
||||
public class ResultView {
|
||||
private Scene scene;
|
||||
private SceneManager sceneManager;
|
||||
private double score;
|
||||
|
||||
public ResultView(SceneManager sceneManager) {
|
||||
this.sceneManager = sceneManager;
|
||||
createScene();
|
||||
}
|
||||
|
||||
private void createScene() {
|
||||
VBox root = new VBox(30);
|
||||
root.setPadding(new Insets(50));
|
||||
root.setAlignment(Pos.CENTER);
|
||||
|
||||
Label titleLabel = new Label("答题完成");
|
||||
titleLabel.setFont(Font.font(24));
|
||||
|
||||
Label scoreLabel = new Label();
|
||||
scoreLabel.setFont(Font.font(48));
|
||||
|
||||
Label messageLabel = new Label();
|
||||
messageLabel.setFont(Font.font(18));
|
||||
|
||||
Button restartButton = new Button("再次练习");
|
||||
restartButton.setStyle("-fx-background-color: #4CAF50; -fx-text-fill: white; -fx-font-size: 16px;");
|
||||
restartButton.setPrefSize(200, 50);
|
||||
|
||||
Button mainMenuButton = new Button("返回主菜单");
|
||||
mainMenuButton.setStyle("-fx-background-color: #2196F3; -fx-text-fill: white; -fx-font-size: 16px;");
|
||||
mainMenuButton.setPrefSize(200, 50);
|
||||
|
||||
Button exitButton = new Button("退出系统");
|
||||
exitButton.setStyle("-fx-background-color: #757575; -fx-text-fill: white; -fx-font-size: 16px;");
|
||||
exitButton.setPrefSize(200, 50);
|
||||
|
||||
restartButton.setOnAction(e -> {
|
||||
sceneManager.showLevelSelectionView();
|
||||
});
|
||||
|
||||
mainMenuButton.setOnAction(e -> {
|
||||
sceneManager.showMainMenuView();
|
||||
});
|
||||
|
||||
exitButton.setOnAction(e -> {
|
||||
System.exit(0);
|
||||
});
|
||||
|
||||
root.getChildren().addAll(
|
||||
titleLabel, scoreLabel, messageLabel,
|
||||
restartButton, mainMenuButton, exitButton
|
||||
);
|
||||
|
||||
scene = new Scene(root, 400, 500);
|
||||
}
|
||||
|
||||
public void setScore(double score) {
|
||||
this.score = score;
|
||||
updateScoreDisplay();
|
||||
}
|
||||
|
||||
private void updateScoreDisplay() {
|
||||
if (scene != null) {
|
||||
VBox root = (VBox) scene.getRoot();
|
||||
Label scoreLabel = (Label) root.getChildren().get(1);
|
||||
Label messageLabel = (Label) root.getChildren().get(2);
|
||||
|
||||
int percentage = (int) (score * 100);
|
||||
scoreLabel.setText(percentage + "分");
|
||||
|
||||
// 根据分数设置不同的颜色和评语
|
||||
if (score >= 0.9) {
|
||||
scoreLabel.setStyle("-fx-text-fill: #4CAF50;");
|
||||
messageLabel.setText("优秀!表现非常出色!");
|
||||
} else if (score >= 0.7) {
|
||||
scoreLabel.setStyle("-fx-text-fill: #FF9800;");
|
||||
messageLabel.setText("良好!继续加油!");
|
||||
} else if (score >= 0.6) {
|
||||
scoreLabel.setStyle("-fx-text-fill: #FFC107;");
|
||||
messageLabel.setText("及格!还有进步空间!");
|
||||
} else {
|
||||
scoreLabel.setStyle("-fx-text-fill: #f44336;");
|
||||
messageLabel.setText("需要多加练习!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Scene getScene() {
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue