|
|
|
|
@ -0,0 +1,764 @@
|
|
|
|
|
import sys
|
|
|
|
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
|
|
|
|
|
QHBoxLayout, QLabel, QPushButton, QLineEdit,
|
|
|
|
|
QMessageBox, QFrame, QGridLayout, QSizePolicy, QStackedWidget)
|
|
|
|
|
from PyQt5.QtCore import Qt
|
|
|
|
|
from PyQt5.QtGui import QFont, QPalette, QColor
|
|
|
|
|
|
|
|
|
|
# 导入各个页面(需要先修改这些类继承QWidget)
|
|
|
|
|
from .login_ui import LoginPage
|
|
|
|
|
from .register_ui import RegisterPage
|
|
|
|
|
from .question_ui import QuestionPage
|
|
|
|
|
from .result_ui import ResultPage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MainWindow(QMainWindow):
|
|
|
|
|
def __init__(self,user_system):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.user_system = user_system
|
|
|
|
|
self.menu_bar = None
|
|
|
|
|
self.current_level = None
|
|
|
|
|
self.question_count = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 创建堆叠窗口
|
|
|
|
|
self.stacked_widget = QStackedWidget()
|
|
|
|
|
|
|
|
|
|
self.init_ui()
|
|
|
|
|
|
|
|
|
|
def init_ui(self):
|
|
|
|
|
"""初始化主窗口界面"""
|
|
|
|
|
self.setWindowTitle("🎮 数学冒险岛 🎮")
|
|
|
|
|
# self.setMinimumSize(900, 650)
|
|
|
|
|
# 设置固定大小(例如 900×650)
|
|
|
|
|
# self.setFixedSize(900, 1200)
|
|
|
|
|
# 获取字体高度来设置相对大小
|
|
|
|
|
font_metrics = self.fontMetrics()
|
|
|
|
|
char_height = font_metrics.height()
|
|
|
|
|
|
|
|
|
|
# 基于字符高度设置尺寸
|
|
|
|
|
self.setFixedSize(40 * char_height, 55 * char_height)
|
|
|
|
|
|
|
|
|
|
# 设置可爱的渐变背景色
|
|
|
|
|
palette = self.palette()
|
|
|
|
|
palette.setColor(QPalette.Window, QColor(255, 240, 245))
|
|
|
|
|
self.setPalette(palette)
|
|
|
|
|
|
|
|
|
|
# 设置中央部件为堆叠窗口
|
|
|
|
|
self.setCentralWidget(self.stacked_widget)
|
|
|
|
|
|
|
|
|
|
# 初始化各个页面
|
|
|
|
|
self.init_pages()
|
|
|
|
|
|
|
|
|
|
# 显示主页面
|
|
|
|
|
self.show_main_page()
|
|
|
|
|
|
|
|
|
|
def init_pages(self):
|
|
|
|
|
"""初始化所有页面"""
|
|
|
|
|
# 主页面
|
|
|
|
|
self.main_page = self.create_main_page()
|
|
|
|
|
self.stacked_widget.addWidget(self.main_page)
|
|
|
|
|
|
|
|
|
|
# 登录页面
|
|
|
|
|
self.login_page = LoginPage(self)
|
|
|
|
|
self.stacked_widget.addWidget(self.login_page)
|
|
|
|
|
|
|
|
|
|
# 注册页面
|
|
|
|
|
self.register_page = RegisterPage(self)
|
|
|
|
|
self.stacked_widget.addWidget(self.register_page)
|
|
|
|
|
|
|
|
|
|
# 学段选择页面
|
|
|
|
|
self.level_page = self.create_level_page()
|
|
|
|
|
self.stacked_widget.addWidget(self.level_page)
|
|
|
|
|
|
|
|
|
|
# 题目数量页面
|
|
|
|
|
self.count_page = self.create_count_page()
|
|
|
|
|
self.stacked_widget.addWidget(self.count_page)
|
|
|
|
|
|
|
|
|
|
def show_main_page(self):
|
|
|
|
|
"""显示主页面"""
|
|
|
|
|
self.stacked_widget.setCurrentWidget(self.main_page)
|
|
|
|
|
self.clear_menu_bar()
|
|
|
|
|
|
|
|
|
|
def show_login_page(self):
|
|
|
|
|
"""显示登录页面"""
|
|
|
|
|
self.stacked_widget.setCurrentWidget(self.login_page)
|
|
|
|
|
self.clear_menu_bar()
|
|
|
|
|
|
|
|
|
|
def show_register_page(self):
|
|
|
|
|
"""显示注册页面"""
|
|
|
|
|
self.stacked_widget.setCurrentWidget(self.register_page)
|
|
|
|
|
self.clear_menu_bar()
|
|
|
|
|
|
|
|
|
|
def show_level_page(self):
|
|
|
|
|
"""显示学段选择页面"""
|
|
|
|
|
if not self.user_system or not self.user_system.current_user:
|
|
|
|
|
QMessageBox.warning(self, "提示", "请先登录")
|
|
|
|
|
return
|
|
|
|
|
self.stacked_widget.setCurrentWidget(self.level_page)
|
|
|
|
|
self.create_user_menu()
|
|
|
|
|
|
|
|
|
|
def show_count_page(self):
|
|
|
|
|
"""显示题目数量输入页面"""
|
|
|
|
|
if not self.user_system or not self.user_system.current_user:
|
|
|
|
|
QMessageBox.warning(self, "提示", "请先登录")
|
|
|
|
|
return
|
|
|
|
|
self.update_count_page(self.current_level)
|
|
|
|
|
self.stacked_widget.setCurrentWidget(self.count_page)
|
|
|
|
|
|
|
|
|
|
def show_question_page(self, level: str, count: int):
|
|
|
|
|
try:
|
|
|
|
|
# ✅ 每次创建新页面前,清理旧的 QuestionPage(如果有)
|
|
|
|
|
for i in reversed(range(self.stacked_widget.count())):
|
|
|
|
|
widget = self.stacked_widget.widget(i)
|
|
|
|
|
if isinstance(widget, QuestionPage):
|
|
|
|
|
self.stacked_widget.removeWidget(widget)
|
|
|
|
|
widget.deleteLater() # 释放内存
|
|
|
|
|
|
|
|
|
|
# ✅ 再创建新页面
|
|
|
|
|
question_page = QuestionPage(self, level, count)
|
|
|
|
|
self.stacked_widget.addWidget(question_page)
|
|
|
|
|
self.stacked_widget.setCurrentWidget(question_page)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
QMessageBox.critical(self, "❌ 程序错误", f"生成题目时发生错误:\n{str(e)}")
|
|
|
|
|
print(f"[ERROR] 题目生成失败: {e}")
|
|
|
|
|
try:
|
|
|
|
|
question_page = QuestionPage(self, level, count)
|
|
|
|
|
self.stacked_widget.addWidget(question_page)
|
|
|
|
|
self.stacked_widget.setCurrentWidget(question_page)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
QMessageBox.critical(self, "❌ 程序错误", f"生成题目时发生错误:\n{str(e)}")
|
|
|
|
|
print(f"[ERROR] 题目生成失败: {e}")
|
|
|
|
|
|
|
|
|
|
def show_result_page(self, score: int, level: str, count: int):
|
|
|
|
|
"""显示结果页面"""
|
|
|
|
|
result_page = ResultPage(self, score, level, count)
|
|
|
|
|
self.stacked_widget.addWidget(result_page)
|
|
|
|
|
self.stacked_widget.setCurrentWidget(result_page)
|
|
|
|
|
|
|
|
|
|
def remove_current_page(self):
|
|
|
|
|
"""移除当前页面(用于答题和结果页面)"""
|
|
|
|
|
current_index = self.stacked_widget.currentIndex()
|
|
|
|
|
# 只移除动态添加的页面(索引大于固定页面数量)
|
|
|
|
|
if current_index >= 5: # 主页面、登录、注册、学段、题目数量
|
|
|
|
|
current_widget = self.stacked_widget.currentWidget()
|
|
|
|
|
self.stacked_widget.removeWidget(current_widget)
|
|
|
|
|
|
|
|
|
|
def create_main_page(self):
|
|
|
|
|
"""创建主页面"""
|
|
|
|
|
widget = QWidget()
|
|
|
|
|
|
|
|
|
|
# 主布局 - 使用弹性布局
|
|
|
|
|
main_layout = QVBoxLayout(widget)
|
|
|
|
|
main_layout.setContentsMargins(30, 20, 30, 20)
|
|
|
|
|
main_layout.setSpacing(0)
|
|
|
|
|
|
|
|
|
|
# 主容器框架 - 自适应尺寸
|
|
|
|
|
container = QFrame()
|
|
|
|
|
container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
|
|
|
container.setStyleSheet("""
|
|
|
|
|
QFrame {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FFD1DC, stop:1 #B5EAD7);
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
border: 3px solid #FF9EBC;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
main_layout.addWidget(container)
|
|
|
|
|
|
|
|
|
|
# 容器布局 - 使用弹性布局
|
|
|
|
|
container_layout = QVBoxLayout(container)
|
|
|
|
|
container_layout.setContentsMargins(40, 30, 40, 30)
|
|
|
|
|
container_layout.setSpacing(0)
|
|
|
|
|
|
|
|
|
|
# 顶部弹性空间
|
|
|
|
|
container_layout.addStretch(1)
|
|
|
|
|
|
|
|
|
|
# --- 标题区域 ---
|
|
|
|
|
title_frame = QFrame()
|
|
|
|
|
title_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
title_frame.setStyleSheet("background: transparent; border: none;")
|
|
|
|
|
title_layout = QVBoxLayout(title_frame)
|
|
|
|
|
title_layout.setSpacing(10)
|
|
|
|
|
|
|
|
|
|
# 装饰性emoji
|
|
|
|
|
emoji_label = QLabel("✨🎓🧮🌟")
|
|
|
|
|
emoji_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 20pt 'Arial';
|
|
|
|
|
color: #FF6B9C;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
title_layout.addWidget(emoji_label)
|
|
|
|
|
|
|
|
|
|
# 主标题
|
|
|
|
|
title_label = QLabel("数学冒险岛")
|
|
|
|
|
title_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 28pt '微软雅黑';
|
|
|
|
|
color: #FF6B9C;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
title_layout.addWidget(title_label)
|
|
|
|
|
|
|
|
|
|
# 副标题
|
|
|
|
|
subtitle_label = QLabel("🚀 开启你的数学冒险之旅! 🚀")
|
|
|
|
|
subtitle_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: 14pt '微软雅黑';
|
|
|
|
|
color: #5A5A5A;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
title_layout.addWidget(subtitle_label)
|
|
|
|
|
|
|
|
|
|
container_layout.addWidget(title_frame)
|
|
|
|
|
container_layout.addSpacing(40)
|
|
|
|
|
|
|
|
|
|
# --- 按钮区域 ---
|
|
|
|
|
button_frame = QFrame()
|
|
|
|
|
button_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
button_frame.setStyleSheet("background: transparent; border: none;")
|
|
|
|
|
button_layout = QVBoxLayout(button_frame)
|
|
|
|
|
button_layout.setSpacing(20)
|
|
|
|
|
|
|
|
|
|
# 登录按钮
|
|
|
|
|
login_btn = QPushButton("🎮 开始冒险")
|
|
|
|
|
login_btn.setMinimumSize(250, 60)
|
|
|
|
|
login_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
login_btn.setStyleSheet("""
|
|
|
|
|
QPushButton {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FF9EBC, stop:1 #FF6B9C);
|
|
|
|
|
color: white;
|
|
|
|
|
font: bold 16pt '微软雅黑';
|
|
|
|
|
border-radius: 30px;
|
|
|
|
|
border: 3px solid #FF85A1;
|
|
|
|
|
max-width: 300px;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:hover {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FF85A1, stop:1 #FF5784);
|
|
|
|
|
border: 3px solid #FF6B9C;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:pressed {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FF5784, stop:1 #FF3D6D);
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
login_btn.clicked.connect(self.show_login_page) # 改为页面切换
|
|
|
|
|
button_layout.addWidget(login_btn, alignment=Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
# 注册按钮
|
|
|
|
|
register_btn = QPushButton("📝 注册账号")
|
|
|
|
|
register_btn.setMinimumSize(250, 60)
|
|
|
|
|
register_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
register_btn.setStyleSheet("""
|
|
|
|
|
QPushButton {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #A0E7E5, stop:1 #6CD6D3);
|
|
|
|
|
color: white;
|
|
|
|
|
font: bold 16pt '微软雅黑';
|
|
|
|
|
border-radius: 30px;
|
|
|
|
|
border: 3px solid #8ADBD9;
|
|
|
|
|
max-width: 300px;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:hover {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #8ADBD9, stop:1 #5AC7C4);
|
|
|
|
|
border: 3px solid #6CD6D3;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:pressed {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #5AC7C4, stop:1 #4BB5B2);
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
register_btn.clicked.connect(self.show_register_page) # 改为页面切换
|
|
|
|
|
button_layout.addWidget(register_btn, alignment=Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
container_layout.addWidget(button_frame)
|
|
|
|
|
container_layout.addStretch(2)
|
|
|
|
|
|
|
|
|
|
# --- 装饰性元素 ---
|
|
|
|
|
decoration_frame = QFrame()
|
|
|
|
|
decoration_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
decoration_frame.setStyleSheet("background: transparent; border: none;")
|
|
|
|
|
decoration_layout = QHBoxLayout(decoration_frame)
|
|
|
|
|
|
|
|
|
|
math_symbols = QLabel("🔢 ➕ ➖ ✖️ ➗ 📐 📊 🧮")
|
|
|
|
|
math_symbols.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 16pt 'Arial';
|
|
|
|
|
color: #FF9EBC;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
decoration_layout.addWidget(math_symbols)
|
|
|
|
|
|
|
|
|
|
container_layout.addWidget(decoration_frame)
|
|
|
|
|
container_layout.addSpacing(20)
|
|
|
|
|
|
|
|
|
|
# --- 底部信息 ---
|
|
|
|
|
footer_frame = QFrame()
|
|
|
|
|
footer_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
footer_frame.setStyleSheet("background: transparent; border: none;")
|
|
|
|
|
footer_layout = QHBoxLayout(footer_frame)
|
|
|
|
|
|
|
|
|
|
footer_label = QLabel("🌈 版权所有 © 2025 数学冒险岛 🌈")
|
|
|
|
|
footer_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: 10pt '微软雅黑';
|
|
|
|
|
color: #888888;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
footer_layout.addWidget(footer_label)
|
|
|
|
|
|
|
|
|
|
container_layout.addWidget(footer_frame)
|
|
|
|
|
|
|
|
|
|
return widget
|
|
|
|
|
|
|
|
|
|
def create_level_page(self):
|
|
|
|
|
"""创建学段选择页面"""
|
|
|
|
|
widget = QWidget()
|
|
|
|
|
|
|
|
|
|
# 主布局
|
|
|
|
|
main_layout = QVBoxLayout(widget)
|
|
|
|
|
main_layout.setContentsMargins(30, 20, 30, 20)
|
|
|
|
|
main_layout.setSpacing(0)
|
|
|
|
|
|
|
|
|
|
# 主容器
|
|
|
|
|
frame = QFrame()
|
|
|
|
|
frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
|
|
|
frame.setStyleSheet("""
|
|
|
|
|
QFrame {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FFD1DC, stop:1 #B5EAD7);
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
border: 3px solid #FF9EBC;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
main_layout.addWidget(frame)
|
|
|
|
|
|
|
|
|
|
frame_layout = QVBoxLayout(frame)
|
|
|
|
|
frame_layout.setContentsMargins(40, 30, 40, 30)
|
|
|
|
|
frame_layout.setSpacing(0)
|
|
|
|
|
|
|
|
|
|
# 顶部空间
|
|
|
|
|
frame_layout.addStretch(1)
|
|
|
|
|
|
|
|
|
|
# 欢迎信息
|
|
|
|
|
welcome_text = f"🎉 欢迎回来! 🎉"
|
|
|
|
|
self.welcome_label = QLabel(welcome_text)
|
|
|
|
|
self.welcome_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 18pt '微软雅黑';
|
|
|
|
|
color: #FF6B9C;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
self.welcome_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
frame_layout.addWidget(self.welcome_label)
|
|
|
|
|
|
|
|
|
|
frame_layout.addSpacing(40)
|
|
|
|
|
|
|
|
|
|
# 学段选择标题
|
|
|
|
|
select_label = QLabel("🎯 选择你的冒险地图 🎯")
|
|
|
|
|
select_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 20pt '微软雅黑';
|
|
|
|
|
color: #5A5A5A;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
select_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
frame_layout.addWidget(select_label)
|
|
|
|
|
|
|
|
|
|
frame_layout.addSpacing(40)
|
|
|
|
|
|
|
|
|
|
# 按钮区域
|
|
|
|
|
btn_frame = QFrame()
|
|
|
|
|
btn_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
|
|
|
btn_frame.setStyleSheet("background: transparent; border: none;")
|
|
|
|
|
btn_layout = QGridLayout(btn_frame)
|
|
|
|
|
btn_layout.setSpacing(20)
|
|
|
|
|
btn_layout.setVerticalSpacing(25)
|
|
|
|
|
|
|
|
|
|
levels = [("🏫 小学乐园", "primary"), ("🏰 初中城堡", "middle"), ("🚀 高中太空", "high")]
|
|
|
|
|
colors = [
|
|
|
|
|
("#FF9EBC", "#FF6B9C"), # 粉色
|
|
|
|
|
("#A0E7E5", "#6CD6D3"), # 青色
|
|
|
|
|
("#B5EAD7", "#8CD9B3") # 绿色
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for i, (text, level) in enumerate(levels):
|
|
|
|
|
color_pair = colors[i % len(colors)]
|
|
|
|
|
btn = QPushButton(text)
|
|
|
|
|
btn.setMinimumSize(280, 70)
|
|
|
|
|
btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
btn.setStyleSheet(f"""
|
|
|
|
|
QPushButton {{
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 {color_pair[0]}, stop:1 {color_pair[1]});
|
|
|
|
|
color: white;
|
|
|
|
|
font: bold 18pt '微软雅黑';
|
|
|
|
|
border-radius: 35px;
|
|
|
|
|
border: 3px solid {color_pair[0]};
|
|
|
|
|
max-width: 320px;
|
|
|
|
|
}}
|
|
|
|
|
QPushButton:hover {{
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 {color_pair[1]}, stop:1 {color_pair[0]});
|
|
|
|
|
}}
|
|
|
|
|
QPushButton:pressed {{
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #555555, stop:1 {color_pair[1]});
|
|
|
|
|
}}
|
|
|
|
|
""")
|
|
|
|
|
btn.clicked.connect(lambda checked, l=level: self.on_level_selected(l))
|
|
|
|
|
btn_layout.addWidget(btn, i, 0, alignment=Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
frame_layout.addWidget(btn_frame)
|
|
|
|
|
frame_layout.addStretch(1)
|
|
|
|
|
|
|
|
|
|
# 功能按钮区域
|
|
|
|
|
func_frame = QFrame()
|
|
|
|
|
func_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
func_frame.setStyleSheet("background: transparent; border: none;")
|
|
|
|
|
func_layout = QHBoxLayout(func_frame)
|
|
|
|
|
func_layout.setSpacing(20)
|
|
|
|
|
|
|
|
|
|
# 修改密码按钮
|
|
|
|
|
change_pwd_btn = QPushButton("🔑 修改密码")
|
|
|
|
|
change_pwd_btn.setMinimumSize(180, 50)
|
|
|
|
|
change_pwd_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
change_pwd_btn.setStyleSheet("""
|
|
|
|
|
QPushButton {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FFDAC1, stop:1 #FFB347);
|
|
|
|
|
color: white;
|
|
|
|
|
font: bold 14pt '微软雅黑';
|
|
|
|
|
border-radius: 25px;
|
|
|
|
|
border: 3px solid #FFB347;
|
|
|
|
|
max-width: 200px;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:hover {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FFB347, stop:1 #FF9800);
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
change_pwd_btn.clicked.connect(self.open_change_password)
|
|
|
|
|
func_layout.addWidget(change_pwd_btn)
|
|
|
|
|
|
|
|
|
|
# 返回上级按钮
|
|
|
|
|
back_btn = QPushButton("🔙 返回主页")
|
|
|
|
|
back_btn.setMinimumSize(180, 50)
|
|
|
|
|
back_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
back_btn.setStyleSheet("""
|
|
|
|
|
QPushButton {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #C7CEEA, stop:1 #9FA8DA);
|
|
|
|
|
color: white;
|
|
|
|
|
font: bold 14pt '微软雅黑';
|
|
|
|
|
border-radius: 25px;
|
|
|
|
|
border: 3px solid #9FA8DA;
|
|
|
|
|
max-width: 200px;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:hover {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #9FA8DA, stop:1 #7986CB);
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
back_btn.clicked.connect(self.show_main_page) # 改为页面切换
|
|
|
|
|
func_layout.addWidget(back_btn)
|
|
|
|
|
|
|
|
|
|
frame_layout.addWidget(func_frame, alignment=Qt.AlignCenter)
|
|
|
|
|
frame_layout.addStretch(1)
|
|
|
|
|
|
|
|
|
|
return widget
|
|
|
|
|
|
|
|
|
|
def create_count_page(self):
|
|
|
|
|
"""创建题目数量页面"""
|
|
|
|
|
widget = QWidget()
|
|
|
|
|
|
|
|
|
|
# 主布局
|
|
|
|
|
main_layout = QVBoxLayout(widget)
|
|
|
|
|
main_layout.setContentsMargins(30, 20, 30, 20)
|
|
|
|
|
main_layout.setSpacing(0)
|
|
|
|
|
|
|
|
|
|
# 主容器
|
|
|
|
|
frame = QFrame()
|
|
|
|
|
frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
|
|
|
frame.setStyleSheet("""
|
|
|
|
|
QFrame {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FFD1DC, stop:1 #B5EAD7);
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
border: 3px solid #FF9EBC;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
main_layout.addWidget(frame)
|
|
|
|
|
|
|
|
|
|
frame_layout = QVBoxLayout(frame)
|
|
|
|
|
frame_layout.setContentsMargins(40, 30, 40, 30)
|
|
|
|
|
frame_layout.setSpacing(0)
|
|
|
|
|
|
|
|
|
|
# 顶部空间
|
|
|
|
|
frame_layout.addStretch(1)
|
|
|
|
|
|
|
|
|
|
# 显示当前学段
|
|
|
|
|
self.level_label = QLabel()
|
|
|
|
|
self.level_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
self.level_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 16pt '微软雅黑';
|
|
|
|
|
color: #FF6B9C;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
frame_layout.addWidget(self.level_label)
|
|
|
|
|
|
|
|
|
|
frame_layout.addSpacing(30)
|
|
|
|
|
|
|
|
|
|
# 输入提示
|
|
|
|
|
count_label = QLabel("🎯 请输入题目数量(10-30)")
|
|
|
|
|
count_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 18pt '微软雅黑';
|
|
|
|
|
color: #5A5A5A;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
count_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
frame_layout.addWidget(count_label)
|
|
|
|
|
|
|
|
|
|
# 装饰性emoji
|
|
|
|
|
emoji_label = QLabel("🔢 ✨ 📚 💫")
|
|
|
|
|
emoji_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
font: bold 16pt 'Arial';
|
|
|
|
|
color: #FF6B9C;
|
|
|
|
|
background: transparent;
|
|
|
|
|
qproperty-alignment: AlignCenter;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
emoji_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
frame_layout.addWidget(emoji_label)
|
|
|
|
|
|
|
|
|
|
frame_layout.addSpacing(30)
|
|
|
|
|
|
|
|
|
|
# 输入框
|
|
|
|
|
self.count_input = QLineEdit()
|
|
|
|
|
self.count_input.setFont(QFont("微软雅黑", 14))
|
|
|
|
|
self.count_input.setMinimumSize(200, 50)
|
|
|
|
|
self.count_input.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
|
|
|
|
self.count_input.setAlignment(Qt.AlignCenter)
|
|
|
|
|
self.count_input.setStyleSheet("""
|
|
|
|
|
QLineEdit {
|
|
|
|
|
background: white;
|
|
|
|
|
border: 3px solid #FF9EBC;
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
font: bold 14pt '微软雅黑';
|
|
|
|
|
color: #FF6B9C;
|
|
|
|
|
padding: 5px;
|
|
|
|
|
selection-background-color: #FFE4EC;
|
|
|
|
|
}
|
|
|
|
|
QLineEdit:focus {
|
|
|
|
|
border: 3px solid #FF6B9C;
|
|
|
|
|
background: #FFF9FA;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
frame_layout.addWidget(self.count_input, alignment=Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
frame_layout.addSpacing(40)
|
|
|
|
|
|
|
|
|
|
# 按钮区域
|
|
|
|
|
btn_frame = QFrame()
|
|
|
|
|
btn_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
btn_frame.setStyleSheet("background: transparent; border: none;")
|
|
|
|
|
btn_layout = QHBoxLayout(btn_frame)
|
|
|
|
|
btn_layout.setSpacing(30)
|
|
|
|
|
|
|
|
|
|
# 开始答题按钮
|
|
|
|
|
start_btn = QPushButton("🚀 开始冒险")
|
|
|
|
|
start_btn.setMinimumSize(210, 60)
|
|
|
|
|
start_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
start_btn.setStyleSheet("""
|
|
|
|
|
QPushButton {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FF9EBC, stop:1 #FF6B9C);
|
|
|
|
|
color: white;
|
|
|
|
|
font: bold 14pt '微软雅黑';
|
|
|
|
|
border-radius: 30px;
|
|
|
|
|
border: 3px solid #FF85A1;
|
|
|
|
|
max-width: 220px;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:hover {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FF85A1, stop:1 #FF5784);
|
|
|
|
|
}
|
|
|
|
|
QPushButton:pressed {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FF5784, stop:1 #FF3D6D);
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
start_btn.clicked.connect(self.start_question)
|
|
|
|
|
btn_layout.addWidget(start_btn)
|
|
|
|
|
|
|
|
|
|
# 返回按钮
|
|
|
|
|
back_btn = QPushButton("🔙 返回选择")
|
|
|
|
|
back_btn.setMinimumSize(210, 60)
|
|
|
|
|
back_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
|
|
|
|
back_btn.setStyleSheet("""
|
|
|
|
|
QPushButton {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #C7CEEA, stop:1 #9FA8DA);
|
|
|
|
|
color: white;
|
|
|
|
|
font: bold 14pt '微软雅黑';
|
|
|
|
|
border-radius: 30px;
|
|
|
|
|
border: 3px solid #9FA8DA;
|
|
|
|
|
max-width: 220px;
|
|
|
|
|
}
|
|
|
|
|
QPushButton:hover {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #9FA8DA, stop:1 #7986CB);
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
back_btn.clicked.connect(self.show_level_page) # 改为页面切换
|
|
|
|
|
btn_layout.addWidget(back_btn)
|
|
|
|
|
|
|
|
|
|
frame_layout.addWidget(btn_frame, alignment=Qt.AlignCenter)
|
|
|
|
|
frame_layout.addStretch(2)
|
|
|
|
|
|
|
|
|
|
return widget
|
|
|
|
|
|
|
|
|
|
def update_level_page(self):
|
|
|
|
|
"""更新学段选择页面的欢迎信息"""
|
|
|
|
|
if self.user_system and self.user_system.current_user:
|
|
|
|
|
welcome_text = f"🎉 欢迎回来,{self.user_system.current_user}! 🎉"
|
|
|
|
|
self.welcome_label.setText(welcome_text)
|
|
|
|
|
|
|
|
|
|
def update_count_page(self, level: str):
|
|
|
|
|
"""更新题目数量页面的学段信息"""
|
|
|
|
|
level_text = {"primary": "🏫 小学乐园", "middle": "🏰 初中城堡", "high": "🚀 高中太空"}.get(level, level)
|
|
|
|
|
self.level_label.setText(f"🗺️ 当前地图:{level_text}")
|
|
|
|
|
self.count_input.clear()
|
|
|
|
|
self.count_input.setFocus()
|
|
|
|
|
|
|
|
|
|
# 修改原有方法
|
|
|
|
|
def open_login(self):
|
|
|
|
|
"""打开登录界面 - 改为页面切换"""
|
|
|
|
|
self.show_login_page()
|
|
|
|
|
|
|
|
|
|
def open_register(self):
|
|
|
|
|
"""打开注册界面 - 改为页面切换"""
|
|
|
|
|
self.show_register_page()
|
|
|
|
|
|
|
|
|
|
def on_level_selected(self, level: str):
|
|
|
|
|
"""学段选择后进入题目数量输入"""
|
|
|
|
|
if self.user_system:
|
|
|
|
|
self.user_system.set_level(level)
|
|
|
|
|
self.current_level = level
|
|
|
|
|
self.update_count_page(level)
|
|
|
|
|
self.show_count_page()
|
|
|
|
|
|
|
|
|
|
def start_question(self):
|
|
|
|
|
"""开始答题"""
|
|
|
|
|
try:
|
|
|
|
|
count = int(self.count_input.text())
|
|
|
|
|
if 10 <= count <= 30:
|
|
|
|
|
self.question_count = count
|
|
|
|
|
self.show_question_page(self.current_level, count)
|
|
|
|
|
else:
|
|
|
|
|
QMessageBox.warning(self, "⚠️ 提示", "请输入10-30之间的数字哦!")
|
|
|
|
|
except ValueError:
|
|
|
|
|
QMessageBox.warning(self, "⚠️ 提示", "请输入有效的数字!")
|
|
|
|
|
|
|
|
|
|
# 其他方法保持不变...
|
|
|
|
|
def create_user_menu(self):
|
|
|
|
|
"""创建用户菜单栏"""
|
|
|
|
|
if self.menu_bar:
|
|
|
|
|
self.menu_bar.clear()
|
|
|
|
|
else:
|
|
|
|
|
self.menu_bar = self.menuBar()
|
|
|
|
|
self.menu_bar.setStyleSheet("""
|
|
|
|
|
QMenuBar {
|
|
|
|
|
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
|
|
|
|
|
stop:0 #FFD1DC, stop:1 #B5EAD7);
|
|
|
|
|
color: #FF6B9C;
|
|
|
|
|
font: bold 12pt '微软雅黑';
|
|
|
|
|
border-bottom: 2px solid #FF9EBC;
|
|
|
|
|
}
|
|
|
|
|
QMenuBar::item {
|
|
|
|
|
background: transparent;
|
|
|
|
|
padding: 5px 10px;
|
|
|
|
|
}
|
|
|
|
|
QMenuBar::item:selected {
|
|
|
|
|
background: #FF9EBC;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 用户菜单
|
|
|
|
|
user_menu = self.menu_bar.addMenu(f"🎮 欢迎(点这里哦),{self.user_system.current_user}")
|
|
|
|
|
user_menu.setStyleSheet("""
|
|
|
|
|
QMenu {
|
|
|
|
|
background: white;
|
|
|
|
|
border: 2px solid #FF9EBC;
|
|
|
|
|
border-radius: 15px;
|
|
|
|
|
}
|
|
|
|
|
QMenu::item {
|
|
|
|
|
padding: 8px 20px;
|
|
|
|
|
font: 11pt '微软雅黑';
|
|
|
|
|
}
|
|
|
|
|
QMenu::item:selected {
|
|
|
|
|
background: #FFE4EC;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
user_menu.addAction("🔑 修改密码", self.open_change_password)
|
|
|
|
|
user_menu.addSeparator()
|
|
|
|
|
user_menu.addAction("🚪 退出登录", self.logout)
|
|
|
|
|
|
|
|
|
|
def open_change_password(self):
|
|
|
|
|
"""打开修改密码界面"""
|
|
|
|
|
if self.user_system and self.user_system.current_user:
|
|
|
|
|
from .login_ui import ChangePasswordUI
|
|
|
|
|
change_password_ui = ChangePasswordUI(self)
|
|
|
|
|
change_password_ui.exec_() # 这个还是弹窗,因为涉及敏感操作
|
|
|
|
|
else:
|
|
|
|
|
QMessageBox.warning(self, "提示", "请先登录")
|
|
|
|
|
|
|
|
|
|
def logout(self):
|
|
|
|
|
"""退出登录"""
|
|
|
|
|
if self.user_system:
|
|
|
|
|
self.user_system.current_user = None
|
|
|
|
|
self.user_system.current_level = None
|
|
|
|
|
QMessageBox.information(self, "🎮 再见", "期待下次与你一起冒险!")
|
|
|
|
|
self.show_main_page()
|
|
|
|
|
|
|
|
|
|
def clear_menu_bar(self):
|
|
|
|
|
"""清空菜单栏"""
|
|
|
|
|
if self.menu_bar:
|
|
|
|
|
self.menu_bar.clear()
|
|
|
|
|
self.menu_bar = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
app = QApplication(sys.argv)
|
|
|
|
|
app.setStyle('Fusion')
|
|
|
|
|
window = MainWindow()
|
|
|
|
|
window.show()
|
|
|
|
|
sys.exit(app.exec_())
|