forked from hnu202306010409/Mathlearn
commit
f3d5eb3388
@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
echo 启动小初高数学学习软件...
|
||||
echo.
|
||||
python src/main.py
|
||||
pause
|
||||
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
echo "启动小初高数学学习软件..."
|
||||
echo ""
|
||||
python3 src/main.py
|
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
小初高数学学习软件
|
||||
主程序入口
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
import sys
|
||||
import os
|
||||
|
||||
# 添加当前目录到Python路径
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from ui.login_window import LoginWindow
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
try:
|
||||
# 创建主窗口
|
||||
root = tk.Tk()
|
||||
root.withdraw() # 隐藏主窗口
|
||||
|
||||
# 创建登录窗口
|
||||
login_window = LoginWindow()
|
||||
|
||||
# 运行应用
|
||||
root.mainloop()
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"程序启动失败: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
测试脚本
|
||||
用于验证各个模块的功能
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# 添加当前目录到Python路径
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from user_manager import UserManager
|
||||
from question_generator import QuestionGenerator
|
||||
|
||||
def test_user_manager():
|
||||
"""测试用户管理功能"""
|
||||
print("测试用户管理功能...")
|
||||
|
||||
user_manager = UserManager()
|
||||
|
||||
# 测试邮箱验证
|
||||
test_email = "test@example.com"
|
||||
print(f"测试邮箱格式验证: {test_email} -> {user_manager.is_valid_email(test_email)}")
|
||||
|
||||
# 测试密码验证
|
||||
test_passwords = ["Abc123", "abc123", "ABC123", "Abcdef", "123456", "Abc123456789"]
|
||||
for pwd in test_passwords:
|
||||
print(f"测试密码格式验证: {pwd} -> {user_manager.is_valid_password(pwd)}")
|
||||
|
||||
print("用户管理功能测试完成\n")
|
||||
|
||||
def test_question_generator():
|
||||
"""测试题目生成功能"""
|
||||
print("测试题目生成功能...")
|
||||
|
||||
generator = QuestionGenerator()
|
||||
|
||||
# 测试各学段题目生成
|
||||
levels = ["小学", "初中", "高中"]
|
||||
for level in levels:
|
||||
print(f"\n生成{level}题目:")
|
||||
questions = generator.generate_questions(level, 3)
|
||||
for i, q in enumerate(questions, 1):
|
||||
print(f" 题目{i}: {q['question']}")
|
||||
print(f" 选项: {q['options']}")
|
||||
print(f" 正确答案: {q['correct_answer']}")
|
||||
|
||||
print("\n题目生成功能测试完成")
|
||||
|
||||
def main():
|
||||
"""主测试函数"""
|
||||
print("=" * 50)
|
||||
print("小初高数学学习软件 - 功能测试")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
test_user_manager()
|
||||
test_question_generator()
|
||||
|
||||
print("=" * 50)
|
||||
print("所有测试完成!")
|
||||
print("=" * 50)
|
||||
|
||||
except Exception as e:
|
||||
print(f"测试过程中出现错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -0,0 +1 @@
|
||||
# UI模块初始化文件
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
答题窗口
|
||||
处理答题界面和评分
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
import sys
|
||||
import os
|
||||
|
||||
# 添加父目录到路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from question_generator import QuestionGenerator
|
||||
from ui.result_window import ResultWindow
|
||||
|
||||
class ExamWindow:
|
||||
"""答题窗口类"""
|
||||
|
||||
def __init__(self, email, level, count):
|
||||
self.email = email
|
||||
self.level = level
|
||||
self.count = count
|
||||
self.current_question = 0
|
||||
self.user_answers = []
|
||||
self.score = 0
|
||||
|
||||
# 生成题目
|
||||
self.generator = QuestionGenerator()
|
||||
self.questions = self.generator.generate_questions(level, count)
|
||||
|
||||
self.setup_ui()
|
||||
self.show_question()
|
||||
|
||||
def setup_ui(self):
|
||||
"""设置UI界面"""
|
||||
self.window = tk.Tk()
|
||||
self.window.title(f"数学学习软件 - {self.level}答题")
|
||||
self.window.geometry("600x500")
|
||||
self.window.resizable(False, False)
|
||||
|
||||
# 居中显示
|
||||
self.center_window()
|
||||
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(self.window, padding="20")
|
||||
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# 进度信息
|
||||
self.progress_label = ttk.Label(main_frame, text="", font=("Arial", 12))
|
||||
self.progress_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
|
||||
|
||||
# 题目显示区域
|
||||
question_frame = ttk.LabelFrame(main_frame, text="题目", padding="15")
|
||||
question_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 20))
|
||||
|
||||
self.question_label = ttk.Label(question_frame, text="",
|
||||
font=("Arial", 14), wraplength=500)
|
||||
self.question_label.grid(row=0, column=0, sticky=tk.W)
|
||||
|
||||
# 选项显示区域
|
||||
options_frame = ttk.LabelFrame(main_frame, text="选项", padding="15")
|
||||
options_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 20))
|
||||
|
||||
self.option_vars = []
|
||||
self.option_buttons = []
|
||||
|
||||
for i in range(4):
|
||||
var = tk.StringVar()
|
||||
self.option_vars.append(var)
|
||||
|
||||
btn = ttk.Radiobutton(options_frame, text="", variable=var,
|
||||
value=str(i), command=self.on_option_selected)
|
||||
btn.grid(row=i, column=0, sticky=tk.W, pady=5)
|
||||
self.option_buttons.append(btn)
|
||||
|
||||
# 按钮框架
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.grid(row=3, column=0, columnspan=2, pady=20)
|
||||
|
||||
# 上一题按钮
|
||||
self.prev_btn = ttk.Button(button_frame, text="上一题",
|
||||
command=self.previous_question, state='disabled')
|
||||
self.prev_btn.grid(row=0, column=0, padx=5)
|
||||
|
||||
# 下一题按钮
|
||||
self.next_btn = ttk.Button(button_frame, text="下一题",
|
||||
command=self.next_question, state='disabled')
|
||||
self.next_btn.grid(row=0, column=1, padx=5)
|
||||
|
||||
# 提交按钮
|
||||
self.submit_btn = ttk.Button(button_frame, text="提交答案",
|
||||
command=self.submit_answer, state='disabled')
|
||||
self.submit_btn.grid(row=0, column=2, padx=5)
|
||||
|
||||
# 完成按钮
|
||||
self.finish_btn = ttk.Button(button_frame, text="完成答题",
|
||||
command=self.finish_exam, state='disabled')
|
||||
self.finish_btn.grid(row=0, column=3, padx=5)
|
||||
|
||||
def center_window(self):
|
||||
"""窗口居中显示"""
|
||||
self.window.update_idletasks()
|
||||
width = self.window.winfo_width()
|
||||
height = self.window.winfo_height()
|
||||
x = (self.window.winfo_screenwidth() // 2) - (width // 2)
|
||||
y = (self.window.winfo_screenheight() // 2) - (height // 2)
|
||||
self.window.geometry(f'{width}x{height}+{x}+{y}')
|
||||
|
||||
def show_question(self):
|
||||
"""显示当前题目"""
|
||||
if self.current_question >= len(self.questions):
|
||||
return
|
||||
|
||||
question = self.questions[self.current_question]
|
||||
|
||||
# 更新进度
|
||||
self.progress_label.config(text=f"第 {self.current_question + 1} 题 / 共 {len(self.questions)} 题")
|
||||
|
||||
# 显示题目
|
||||
self.question_label.config(text=question['question'])
|
||||
|
||||
# 显示选项
|
||||
for i, option in enumerate(question['options']):
|
||||
self.option_buttons[i].config(text=f"{chr(65+i)}. {option}")
|
||||
|
||||
# 清除选择
|
||||
for var in self.option_vars:
|
||||
var.set("")
|
||||
|
||||
# 如果之前已经选择过,恢复选择
|
||||
if self.current_question < len(self.user_answers):
|
||||
if self.user_answers[self.current_question] is not None:
|
||||
self.option_vars[self.user_answers[self.current_question]].set(str(self.user_answers[self.current_question]))
|
||||
|
||||
# 更新按钮状态
|
||||
self.update_button_states()
|
||||
|
||||
def on_option_selected(self):
|
||||
"""选项被选择时的处理"""
|
||||
self.update_button_states()
|
||||
|
||||
def update_button_states(self):
|
||||
"""更新按钮状态"""
|
||||
# 检查是否有选择
|
||||
has_selection = any(var.get() for var in self.option_vars)
|
||||
|
||||
# 更新提交按钮状态
|
||||
self.submit_btn.config(state='normal' if has_selection else 'disabled')
|
||||
|
||||
# 更新上一题按钮状态
|
||||
self.prev_btn.config(state='normal' if self.current_question > 0 else 'disabled')
|
||||
|
||||
# 更新下一题按钮状态
|
||||
self.next_btn.config(state='normal' if self.current_question < len(self.questions) - 1 else 'disabled')
|
||||
|
||||
# 更新完成按钮状态
|
||||
all_answered = all(answer is not None for answer in self.user_answers)
|
||||
self.finish_btn.config(state='normal' if all_answered else 'disabled')
|
||||
|
||||
def submit_answer(self):
|
||||
"""提交当前题目的答案"""
|
||||
# 获取选择的答案
|
||||
selected_option = None
|
||||
for i, var in enumerate(self.option_vars):
|
||||
if var.get():
|
||||
selected_option = i
|
||||
break
|
||||
|
||||
if selected_option is None:
|
||||
messagebox.showerror("错误", "请选择一个答案")
|
||||
return
|
||||
|
||||
# 保存答案
|
||||
while len(self.user_answers) <= self.current_question:
|
||||
self.user_answers.append(None)
|
||||
|
||||
self.user_answers[self.current_question] = selected_option
|
||||
|
||||
# 检查答案是否正确
|
||||
question = self.questions[self.current_question]
|
||||
if selected_option == question['correct_answer']:
|
||||
self.score += 1
|
||||
|
||||
# 自动跳转到下一题
|
||||
if self.current_question < len(self.questions) - 1:
|
||||
self.next_question()
|
||||
else:
|
||||
# 最后一题,显示完成提示
|
||||
messagebox.showinfo("完成", "所有题目已完成!")
|
||||
self.update_button_states()
|
||||
|
||||
def previous_question(self):
|
||||
"""上一题"""
|
||||
if self.current_question > 0:
|
||||
self.current_question -= 1
|
||||
self.show_question()
|
||||
|
||||
def next_question(self):
|
||||
"""下一题"""
|
||||
if self.current_question < len(self.questions) - 1:
|
||||
self.current_question += 1
|
||||
self.show_question()
|
||||
|
||||
def finish_exam(self):
|
||||
"""完成答题"""
|
||||
# 计算最终分数
|
||||
correct_count = 0
|
||||
for i, answer in enumerate(self.user_answers):
|
||||
if answer is not None and answer == self.questions[i]['correct_answer']:
|
||||
correct_count += 1
|
||||
|
||||
percentage = (correct_count / len(self.questions)) * 100
|
||||
|
||||
self.window.destroy()
|
||||
# 打开结果窗口
|
||||
result_window = ResultWindow(self.email, self.level, correct_count,
|
||||
len(self.questions), percentage)
|
||||
@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
登录窗口
|
||||
处理用户注册和登录功能
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
import sys
|
||||
import os
|
||||
|
||||
# 添加父目录到路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from user_manager import UserManager
|
||||
from ui.register_window import RegisterWindow
|
||||
from ui.main_window import MainWindow
|
||||
|
||||
class LoginWindow:
|
||||
"""登录窗口类"""
|
||||
|
||||
def __init__(self):
|
||||
self.user_manager = UserManager()
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self):
|
||||
"""设置UI界面"""
|
||||
self.window = tk.Tk()
|
||||
self.window.title("数学学习软件 - 登录")
|
||||
self.window.geometry("400x300")
|
||||
self.window.resizable(False, False)
|
||||
|
||||
# 居中显示
|
||||
self.center_window()
|
||||
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(self.window, padding="20")
|
||||
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# 标题
|
||||
title_label = ttk.Label(main_frame, text="数学学习软件", font=("Arial", 16, "bold"))
|
||||
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
|
||||
|
||||
# 邮箱输入
|
||||
ttk.Label(main_frame, text="邮箱:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
self.email_var = tk.StringVar()
|
||||
self.email_entry = ttk.Entry(main_frame, textvariable=self.email_var, width=30)
|
||||
self.email_entry.grid(row=1, column=1, pady=5, padx=(10, 0))
|
||||
|
||||
# 密码输入
|
||||
ttk.Label(main_frame, text="密码:").grid(row=2, column=0, sticky=tk.W, pady=5)
|
||||
self.password_var = tk.StringVar()
|
||||
self.password_entry = ttk.Entry(main_frame, textvariable=self.password_var,
|
||||
show="*", width=30)
|
||||
self.password_entry.grid(row=2, column=1, pady=5, padx=(10, 0))
|
||||
|
||||
# 按钮框架
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.grid(row=3, column=0, columnspan=2, pady=20)
|
||||
|
||||
# 登录按钮
|
||||
login_btn = ttk.Button(button_frame, text="登录", command=self.login)
|
||||
login_btn.grid(row=0, column=0, padx=5)
|
||||
|
||||
# 注册按钮
|
||||
register_btn = ttk.Button(button_frame, text="注册", command=self.open_register)
|
||||
register_btn.grid(row=0, column=1, padx=5)
|
||||
|
||||
# 修改密码按钮
|
||||
change_pwd_btn = ttk.Button(button_frame, text="修改密码", command=self.open_change_password)
|
||||
change_pwd_btn.grid(row=0, column=2, padx=5)
|
||||
|
||||
# 绑定回车键
|
||||
self.window.bind('<Return>', lambda e: self.login())
|
||||
|
||||
# 设置焦点
|
||||
self.email_entry.focus()
|
||||
|
||||
def center_window(self):
|
||||
"""窗口居中显示"""
|
||||
self.window.update_idletasks()
|
||||
width = self.window.winfo_width()
|
||||
height = self.window.winfo_height()
|
||||
x = (self.window.winfo_screenwidth() // 2) - (width // 2)
|
||||
y = (self.window.winfo_screenheight() // 2) - (height // 2)
|
||||
self.window.geometry(f'{width}x{height}+{x}+{y}')
|
||||
|
||||
def login(self):
|
||||
"""处理登录"""
|
||||
email = self.email_var.get().strip()
|
||||
password = self.password_var.get().strip()
|
||||
|
||||
if not email or not password:
|
||||
messagebox.showerror("错误", "请输入邮箱和密码")
|
||||
return
|
||||
|
||||
success, message = self.user_manager.login(email, password)
|
||||
|
||||
if success:
|
||||
messagebox.showinfo("成功", message)
|
||||
self.window.destroy()
|
||||
# 打开主窗口
|
||||
main_window = MainWindow(email)
|
||||
else:
|
||||
messagebox.showerror("错误", message)
|
||||
|
||||
def open_register(self):
|
||||
"""打开注册窗口"""
|
||||
self.window.destroy()
|
||||
register_window = RegisterWindow()
|
||||
|
||||
def open_change_password(self):
|
||||
"""打开修改密码窗口"""
|
||||
email = self.email_var.get().strip()
|
||||
if not email:
|
||||
messagebox.showerror("错误", "请先输入邮箱")
|
||||
return
|
||||
|
||||
if email not in self.user_manager.users:
|
||||
messagebox.showerror("错误", "用户不存在")
|
||||
return
|
||||
|
||||
# 创建修改密码对话框
|
||||
self.change_password_dialog(email)
|
||||
|
||||
def change_password_dialog(self, email):
|
||||
"""修改密码对话框"""
|
||||
dialog = tk.Toplevel(self.window)
|
||||
dialog.title("修改密码")
|
||||
dialog.geometry("350x200")
|
||||
dialog.resizable(False, False)
|
||||
dialog.transient(self.window)
|
||||
dialog.grab_set()
|
||||
|
||||
# 居中显示
|
||||
dialog.update_idletasks()
|
||||
x = (dialog.winfo_screenwidth() // 2) - (175)
|
||||
y = (dialog.winfo_screenheight() // 2) - (100)
|
||||
dialog.geometry(f'350x200+{x}+{y}')
|
||||
|
||||
main_frame = ttk.Frame(dialog, padding="20")
|
||||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
# 原密码
|
||||
ttk.Label(main_frame, text="原密码:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||
old_password_var = tk.StringVar()
|
||||
old_password_entry = ttk.Entry(main_frame, textvariable=old_password_var,
|
||||
show="*", width=25)
|
||||
old_password_entry.grid(row=0, column=1, pady=5, padx=(10, 0))
|
||||
|
||||
# 新密码
|
||||
ttk.Label(main_frame, text="新密码:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
new_password_var = tk.StringVar()
|
||||
new_password_entry = ttk.Entry(main_frame, textvariable=new_password_var,
|
||||
show="*", width=25)
|
||||
new_password_entry.grid(row=1, column=1, pady=5, padx=(10, 0))
|
||||
|
||||
# 确认新密码
|
||||
ttk.Label(main_frame, text="确认新密码:").grid(row=2, column=0, sticky=tk.W, pady=5)
|
||||
confirm_password_var = tk.StringVar()
|
||||
confirm_password_entry = ttk.Entry(main_frame, textvariable=confirm_password_var,
|
||||
show="*", width=25)
|
||||
confirm_password_entry.grid(row=2, column=1, pady=5, padx=(10, 0))
|
||||
|
||||
def change_password():
|
||||
old_password = old_password_var.get().strip()
|
||||
new_password = new_password_var.get().strip()
|
||||
confirm_password = confirm_password_var.get().strip()
|
||||
|
||||
if not all([old_password, new_password, confirm_password]):
|
||||
messagebox.showerror("错误", "请填写所有字段")
|
||||
return
|
||||
|
||||
if new_password != confirm_password:
|
||||
messagebox.showerror("错误", "两次输入的新密码不一致")
|
||||
return
|
||||
|
||||
success, message = self.user_manager.change_password(email, old_password, new_password)
|
||||
|
||||
if success:
|
||||
messagebox.showinfo("成功", message)
|
||||
dialog.destroy()
|
||||
else:
|
||||
messagebox.showerror("错误", message)
|
||||
|
||||
# 按钮
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.grid(row=3, column=0, columnspan=2, pady=20)
|
||||
|
||||
ttk.Button(button_frame, text="确定", command=change_password).grid(row=0, column=0, padx=5)
|
||||
ttk.Button(button_frame, text="取消", command=dialog.destroy).grid(row=0, column=1, padx=5)
|
||||
|
||||
# 设置焦点
|
||||
old_password_entry.focus()
|
||||
@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
主窗口
|
||||
显示学段选择界面
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
import sys
|
||||
import os
|
||||
|
||||
# 添加父目录到路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from ui.level_selection_window import LevelSelectionWindow
|
||||
|
||||
class MainWindow:
|
||||
"""主窗口类"""
|
||||
|
||||
def __init__(self, email):
|
||||
self.email = email
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self):
|
||||
"""设置UI界面"""
|
||||
self.window = tk.Tk()
|
||||
self.window.title("数学学习软件 - 主界面")
|
||||
self.window.geometry("500x400")
|
||||
self.window.resizable(False, False)
|
||||
|
||||
# 居中显示
|
||||
self.center_window()
|
||||
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(self.window, padding="30")
|
||||
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# 欢迎信息
|
||||
welcome_label = ttk.Label(main_frame, text=f"欢迎,{self.email}",
|
||||
font=("Arial", 14, "bold"))
|
||||
welcome_label.grid(row=0, column=0, columnspan=3, pady=(0, 30))
|
||||
|
||||
# 标题
|
||||
title_label = ttk.Label(main_frame, text="请选择学习阶段",
|
||||
font=("Arial", 16, "bold"))
|
||||
title_label.grid(row=1, column=0, columnspan=3, pady=(0, 30))
|
||||
|
||||
# 学段选择按钮
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.grid(row=2, column=0, columnspan=3, pady=20)
|
||||
|
||||
# 小学按钮
|
||||
primary_btn = ttk.Button(button_frame, text="小学",
|
||||
command=lambda: self.select_level("小学"),
|
||||
width=15, style="Large.TButton")
|
||||
primary_btn.grid(row=0, column=0, padx=10, pady=10)
|
||||
|
||||
# 初中按钮
|
||||
middle_btn = ttk.Button(button_frame, text="初中",
|
||||
command=lambda: self.select_level("初中"),
|
||||
width=15, style="Large.TButton")
|
||||
middle_btn.grid(row=0, column=1, padx=10, pady=10)
|
||||
|
||||
# 高中按钮
|
||||
high_btn = ttk.Button(button_frame, text="高中",
|
||||
command=lambda: self.select_level("高中"),
|
||||
width=15, style="Large.TButton")
|
||||
high_btn.grid(row=0, column=2, padx=10, pady=10)
|
||||
|
||||
# 底部按钮框架
|
||||
bottom_frame = ttk.Frame(main_frame)
|
||||
bottom_frame.grid(row=3, column=0, columnspan=3, pady=30)
|
||||
|
||||
# 退出按钮
|
||||
exit_btn = ttk.Button(bottom_frame, text="退出", command=self.exit_app)
|
||||
exit_btn.grid(row=0, column=0, padx=10)
|
||||
|
||||
# 配置大按钮样式
|
||||
style = ttk.Style()
|
||||
style.configure("Large.TButton", font=("Arial", 12, "bold"))
|
||||
|
||||
def center_window(self):
|
||||
"""窗口居中显示"""
|
||||
self.window.update_idletasks()
|
||||
width = self.window.winfo_width()
|
||||
height = self.window.winfo_height()
|
||||
x = (self.window.winfo_screenwidth() // 2) - (width // 2)
|
||||
y = (self.window.winfo_screenheight() // 2) - (height // 2)
|
||||
self.window.geometry(f'{width}x{height}+{x}+{y}')
|
||||
|
||||
def select_level(self, level):
|
||||
"""选择学段"""
|
||||
self.window.destroy()
|
||||
# 打开学段选择窗口
|
||||
level_selection_window = LevelSelectionWindow(self.email, level)
|
||||
|
||||
def exit_app(self):
|
||||
"""退出应用"""
|
||||
if messagebox.askyesno("确认", "确定要退出吗?"):
|
||||
self.window.destroy()
|
||||
sys.exit(0)
|
||||
@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
注册窗口
|
||||
处理用户注册功能
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
import sys
|
||||
import os
|
||||
|
||||
# 添加父目录到路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from user_manager import UserManager
|
||||
from ui.password_setup_window import PasswordSetupWindow
|
||||
|
||||
class RegisterWindow:
|
||||
"""注册窗口类"""
|
||||
|
||||
def __init__(self):
|
||||
self.user_manager = UserManager()
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self):
|
||||
"""设置UI界面"""
|
||||
self.window = tk.Tk()
|
||||
self.window.title("数学学习软件 - 注册")
|
||||
self.window.geometry("400x250")
|
||||
self.window.resizable(False, False)
|
||||
|
||||
# 居中显示
|
||||
self.center_window()
|
||||
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(self.window, padding="20")
|
||||
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# 标题
|
||||
title_label = ttk.Label(main_frame, text="用户注册", font=("Arial", 16, "bold"))
|
||||
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 20))
|
||||
|
||||
# 邮箱输入
|
||||
ttk.Label(main_frame, text="邮箱:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||
self.email_var = tk.StringVar()
|
||||
self.email_entry = ttk.Entry(main_frame, textvariable=self.email_var, width=30)
|
||||
self.email_entry.grid(row=1, column=1, pady=5, padx=(10, 0))
|
||||
|
||||
# 验证码输入
|
||||
ttk.Label(main_frame, text="验证码:").grid(row=2, column=0, sticky=tk.W, pady=5)
|
||||
self.code_var = tk.StringVar()
|
||||
self.code_entry = ttk.Entry(main_frame, textvariable=self.code_var, width=20)
|
||||
self.code_entry.grid(row=2, column=1, pady=5, padx=(10, 0), sticky=tk.W)
|
||||
|
||||
# 获取验证码按钮
|
||||
self.get_code_btn = ttk.Button(main_frame, text="获取验证码", command=self.get_verification_code)
|
||||
self.get_code_btn.grid(row=2, column=1, pady=5, padx=(10, 0), sticky=tk.E)
|
||||
|
||||
# 按钮框架
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.grid(row=3, column=0, columnspan=2, pady=20)
|
||||
|
||||
# 注册按钮
|
||||
register_btn = ttk.Button(button_frame, text="注册", command=self.register)
|
||||
register_btn.grid(row=0, column=0, padx=5)
|
||||
|
||||
# 返回登录按钮
|
||||
back_btn = ttk.Button(button_frame, text="返回登录", command=self.back_to_login)
|
||||
back_btn.grid(row=0, column=1, padx=5)
|
||||
|
||||
# 绑定回车键
|
||||
self.window.bind('<Return>', lambda e: self.register())
|
||||
|
||||
# 设置焦点
|
||||
self.email_entry.focus()
|
||||
|
||||
def center_window(self):
|
||||
"""窗口居中显示"""
|
||||
self.window.update_idletasks()
|
||||
width = self.window.winfo_width()
|
||||
height = self.window.winfo_height()
|
||||
x = (self.window.winfo_screenwidth() // 2) - (width // 2)
|
||||
y = (self.window.winfo_screenheight() // 2) - (height // 2)
|
||||
self.window.geometry(f'{width}x{height}+{x}+{y}')
|
||||
|
||||
def get_verification_code(self):
|
||||
"""获取验证码"""
|
||||
email = self.email_var.get().strip()
|
||||
|
||||
if not email:
|
||||
messagebox.showerror("错误", "请输入邮箱")
|
||||
return
|
||||
|
||||
success, message = self.user_manager.send_verification_code(email)
|
||||
|
||||
if success:
|
||||
messagebox.showinfo("成功", message)
|
||||
# 禁用获取验证码按钮5分钟
|
||||
self.get_code_btn.config(state='disabled')
|
||||
self.window.after(300000, lambda: self.get_code_btn.config(state='normal')) # 5分钟后重新启用
|
||||
else:
|
||||
messagebox.showerror("错误", message)
|
||||
|
||||
def register(self):
|
||||
"""处理注册"""
|
||||
email = self.email_var.get().strip()
|
||||
code = self.code_var.get().strip()
|
||||
|
||||
if not email or not code:
|
||||
messagebox.showerror("错误", "请输入邮箱和验证码")
|
||||
return
|
||||
|
||||
# 验证验证码
|
||||
success, message = self.user_manager.verify_code(email, code)
|
||||
|
||||
if success:
|
||||
messagebox.showinfo("成功", message)
|
||||
self.window.destroy()
|
||||
# 打开密码设置窗口
|
||||
password_setup_window = PasswordSetupWindow(email)
|
||||
else:
|
||||
messagebox.showerror("错误", message)
|
||||
|
||||
def back_to_login(self):
|
||||
"""返回登录窗口"""
|
||||
self.window.destroy()
|
||||
from ui.login_window import LoginWindow
|
||||
login_window = LoginWindow()
|
||||
@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
结果窗口
|
||||
显示答题结果和分数
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
import sys
|
||||
import os
|
||||
|
||||
# 添加父目录到路径
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from ui.main_window import MainWindow
|
||||
|
||||
class ResultWindow:
|
||||
"""结果窗口类"""
|
||||
|
||||
def __init__(self, email, level, correct_count, total_count, percentage):
|
||||
self.email = email
|
||||
self.level = level
|
||||
self.correct_count = correct_count
|
||||
self.total_count = total_count
|
||||
self.percentage = percentage
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self):
|
||||
"""设置UI界面"""
|
||||
self.window = tk.Tk()
|
||||
self.window.title("数学学习软件 - 答题结果")
|
||||
self.window.geometry("500x400")
|
||||
self.window.resizable(False, False)
|
||||
|
||||
# 居中显示
|
||||
self.center_window()
|
||||
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(self.window, padding="30")
|
||||
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
|
||||
|
||||
# 标题
|
||||
title_label = ttk.Label(main_frame, text="答题结果",
|
||||
font=("Arial", 18, "bold"))
|
||||
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 30))
|
||||
|
||||
# 学段信息
|
||||
level_label = ttk.Label(main_frame, text=f"学段:{self.level}",
|
||||
font=("Arial", 12))
|
||||
level_label.grid(row=1, column=0, columnspan=2, pady=5)
|
||||
|
||||
# 分数显示
|
||||
score_frame = ttk.LabelFrame(main_frame, text="成绩", padding="20")
|
||||
score_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=20)
|
||||
|
||||
# 正确题数
|
||||
correct_label = ttk.Label(score_frame, text=f"正确题数:{self.correct_count}",
|
||||
font=("Arial", 14))
|
||||
correct_label.grid(row=0, column=0, columnspan=2, pady=5)
|
||||
|
||||
# 总题数
|
||||
total_label = ttk.Label(score_frame, text=f"总题数:{self.total_count}",
|
||||
font=("Arial", 14))
|
||||
total_label.grid(row=1, column=0, columnspan=2, pady=5)
|
||||
|
||||
# 百分比
|
||||
percentage_label = ttk.Label(score_frame, text=f"正确率:{self.percentage:.1f}%",
|
||||
font=("Arial", 16, "bold"))
|
||||
percentage_label.grid(row=2, column=0, columnspan=2, pady=10)
|
||||
|
||||
# 评价
|
||||
evaluation = self.get_evaluation(self.percentage)
|
||||
evaluation_label = ttk.Label(score_frame, text=evaluation,
|
||||
font=("Arial", 12), foreground="blue")
|
||||
evaluation_label.grid(row=3, column=0, columnspan=2, pady=5)
|
||||
|
||||
# 按钮框架
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.grid(row=3, column=0, columnspan=2, pady=30)
|
||||
|
||||
# 继续做题按钮
|
||||
continue_btn = ttk.Button(button_frame, text="继续做题",
|
||||
command=self.continue_exam, style="Large.TButton")
|
||||
continue_btn.grid(row=0, column=0, padx=10)
|
||||
|
||||
# 返回主菜单按钮
|
||||
back_btn = ttk.Button(button_frame, text="返回主菜单",
|
||||
command=self.back_to_main)
|
||||
back_btn.grid(row=0, column=1, padx=10)
|
||||
|
||||
# 退出按钮
|
||||
exit_btn = ttk.Button(button_frame, text="退出",
|
||||
command=self.exit_app)
|
||||
exit_btn.grid(row=0, column=2, padx=10)
|
||||
|
||||
# 配置大按钮样式
|
||||
style = ttk.Style()
|
||||
style.configure("Large.TButton", font=("Arial", 12, "bold"))
|
||||
|
||||
def center_window(self):
|
||||
"""窗口居中显示"""
|
||||
self.window.update_idletasks()
|
||||
width = self.window.winfo_width()
|
||||
height = self.window.winfo_height()
|
||||
x = (self.window.winfo_screenwidth() // 2) - (width // 2)
|
||||
y = (self.window.winfo_screenheight() // 2) - (height // 2)
|
||||
self.window.geometry(f'{width}x{height}+{x}+{y}')
|
||||
|
||||
def get_evaluation(self, percentage):
|
||||
"""根据百分比获取评价"""
|
||||
if percentage >= 90:
|
||||
return "优秀!继续保持!"
|
||||
elif percentage >= 80:
|
||||
return "良好!继续努力!"
|
||||
elif percentage >= 70:
|
||||
return "及格,需要加强练习!"
|
||||
elif percentage >= 60:
|
||||
return "需要更多练习!"
|
||||
else:
|
||||
return "加油!多练习会更好!"
|
||||
|
||||
def continue_exam(self):
|
||||
"""继续做题"""
|
||||
self.window.destroy()
|
||||
from ui.level_selection_window import LevelSelectionWindow
|
||||
level_selection_window = LevelSelectionWindow(self.email, self.level)
|
||||
|
||||
def back_to_main(self):
|
||||
"""返回主菜单"""
|
||||
self.window.destroy()
|
||||
main_window = MainWindow(self.email)
|
||||
|
||||
def exit_app(self):
|
||||
"""退出应用"""
|
||||
if messagebox.askyesno("确认", "确定要退出吗?"):
|
||||
self.window.destroy()
|
||||
sys.exit(0)
|
||||
Loading…
Reference in new issue