311 lines
9.8 KiB
Python
311 lines
9.8 KiB
Python
# 答题页
|
||
|
||
import tkinter as tk
|
||
import random
|
||
from functools import partial
|
||
from components import *
|
||
|
||
# 选项
|
||
class WrappingButton(tk.Frame):
|
||
def __init__(self, parent, text="", command=None,title_font=None,button_font=None,text_font=None, **kwargs):
|
||
tk.Frame.__init__(self, parent, **kwargs)
|
||
self.configure(bg=BG_COLOR, relief="raised", bd=1)
|
||
|
||
self.title_front = title_font
|
||
self.button_font = button_font
|
||
self.text_font = text_font
|
||
|
||
self.label = tk.Label(
|
||
self,
|
||
text=text,
|
||
justify="left",
|
||
anchor="w",
|
||
wraplength=800,
|
||
padx=15,
|
||
pady=12,
|
||
bg=BG_COLOR,
|
||
fg=FG_COLOR,
|
||
font=self.button_font
|
||
)
|
||
self.label.pack(fill="both", expand=True)
|
||
|
||
# 绑定点击事件
|
||
self.bind("<Button-1>", lambda e: command() if command else None)
|
||
self.label.bind("<Button-1>", lambda e: command() if command else None)
|
||
|
||
# 绑定鼠标悬停事件
|
||
self.bind("<Enter>", self._on_enter)
|
||
self.bind("<Leave>", self._on_leave)
|
||
self.label.bind("<Enter>", self._on_enter)
|
||
self.label.bind("<Leave>", self._on_leave)
|
||
|
||
# 当前状态
|
||
self.current_style = "Default"
|
||
self._state = "normal"
|
||
|
||
def _on_enter(self, event):
|
||
if self._state == "disabled":
|
||
return
|
||
if self.current_style == "Default":
|
||
self.label.configure(bg=SELECTED_COLOR)
|
||
self.configure(bg=SELECTED_COLOR)
|
||
|
||
def _on_leave(self, event):
|
||
if self._state == "disabled":
|
||
return
|
||
if self.current_style == "Default":
|
||
self.label.configure(bg=BG_COLOR)
|
||
self.configure(bg=BG_COLOR)
|
||
|
||
def config(self, **kwargs):
|
||
if "text" in kwargs:
|
||
self.label.config(text=kwargs["text"])
|
||
kwargs.pop("text")
|
||
|
||
if "style" in kwargs:
|
||
style = kwargs["style"].split(".")[0]
|
||
self.current_style = style
|
||
|
||
if style == "Default":
|
||
self.label.configure(bg=BG_COLOR, fg=FG_COLOR)
|
||
self.configure(bg=BG_COLOR)
|
||
elif style == "Selected":
|
||
self.label.configure(bg=SELECTED_COLOR, fg=FG_COLOR)
|
||
self.configure(bg=SELECTED_COLOR)
|
||
elif style == "Correct":
|
||
self.label.configure(bg=CORRECT_COLOR, fg="#155724")
|
||
self.configure(bg=CORRECT_COLOR)
|
||
elif style == "Miss":
|
||
self.label.configure(bg=MISS_COLOR, fg="#155724")
|
||
self.configure(bg=MISS_COLOR)
|
||
elif style == "Wrong":
|
||
self.label.configure(bg=WRONG_COLOR, fg="#721c24")
|
||
self.configure(bg=WRONG_COLOR)
|
||
|
||
kwargs.pop("style")
|
||
|
||
if "state" in kwargs:
|
||
self._state = kwargs["state"]
|
||
if kwargs["state"] == "disabled":
|
||
self.label.configure(fg="#999999")
|
||
else:
|
||
self.label.configure(fg=FG_COLOR)
|
||
kwargs.pop("state")
|
||
|
||
tk.Frame.config(self, **kwargs)
|
||
|
||
class Page0(tk.Frame):
|
||
# 定义
|
||
indexMap = {6: "A. ", 7: "B. ", 8: "C. ", 9: "D. "} # 映射
|
||
|
||
def __init__(self, parent,fonts,c_backend, **kwargs):
|
||
tk.Frame.__init__(self, parent, **kwargs)
|
||
# 全局变量
|
||
self.buttons = []
|
||
self.text1 = None
|
||
self.text2 = None
|
||
self.row = []
|
||
self.correct_answer = []
|
||
self.my_answer = [0, 0, 0, 0]
|
||
self.shuffle_index = [6, 7, 8, 9]
|
||
self.flag = False
|
||
self.button_disable = True
|
||
|
||
# 入参
|
||
self.c_backend = c_backend
|
||
|
||
# 题目
|
||
frame_top = tk.Frame(parent, bg=BG_COLOR)
|
||
frame_top.pack(pady=15, padx=20, fill='x')
|
||
|
||
self.text1 = tk.Text(
|
||
frame_top,
|
||
font=fonts.title,
|
||
wrap='word',
|
||
height=5,
|
||
bg="white",
|
||
fg=FG_COLOR,
|
||
relief="flat",
|
||
padx=15,
|
||
pady=15,
|
||
selectbackground=ACCENT_COLOR,
|
||
highlightbackground=BG_COLOR
|
||
)
|
||
self.text1.config(state="disabled")
|
||
self.text1.pack(fill='x', expand=True)
|
||
|
||
# 按钮
|
||
frame_buttons = tk.Frame(parent, bg=BG_COLOR)
|
||
frame_buttons.pack(pady=10, padx=20, fill='x')
|
||
|
||
for i in range(4):
|
||
btn = WrappingButton(
|
||
frame_buttons,
|
||
text=f"选项 {i + 1}",
|
||
command=partial(self.on_button_click, i),
|
||
title_font=fonts.title,
|
||
button_font=fonts.button,
|
||
text_font=fonts.text,
|
||
)
|
||
self.buttons.append(btn)
|
||
btn.pack(pady=6, fill='x')
|
||
|
||
# 确定按钮
|
||
button5 = tk.Button(
|
||
parent,
|
||
text="确定",
|
||
font=fonts.button,
|
||
bg=ACCENT_COLOR,
|
||
fg="white",
|
||
command=self.on_ok_click,
|
||
relief="flat",
|
||
padx=20,
|
||
pady=10,
|
||
borderwidth=0,
|
||
cursor="hand2"
|
||
)
|
||
button5.pack(pady=12)
|
||
|
||
def on_enter(e): button5.config(bg="#2980b9")
|
||
|
||
def on_leave(e): button5.config(bg=ACCENT_COLOR)
|
||
|
||
button5.bind("<Enter>", on_enter)
|
||
button5.bind("<Leave>", on_leave)
|
||
|
||
# 解析区
|
||
frame_bottom = tk.Frame(parent, bg=BG_COLOR)
|
||
frame_bottom.pack(pady=10, padx=20, fill='both', expand=True)
|
||
|
||
self.text2 = tk.Text(
|
||
frame_bottom,
|
||
font=fonts.text,
|
||
wrap='word',
|
||
bg="white",
|
||
fg="#555",
|
||
relief="flat",
|
||
padx=15,
|
||
pady=15,
|
||
spacing3=10,
|
||
selectbackground=ACCENT_COLOR
|
||
)
|
||
self.text2.config(state="disabled")
|
||
|
||
scroll = tk.Scrollbar(frame_bottom, orient="vertical", command=self.text2.yview)
|
||
self.text2.configure(yscrollcommand=scroll.set)
|
||
self.text2.pack(side="left", fill='both', expand=True)
|
||
scroll.pack(side="right", fill='y')
|
||
|
||
def _show_result(self, ):
|
||
if self.row == None or len(self.row) < 15:
|
||
return
|
||
elif self.button_disable:
|
||
return
|
||
else:
|
||
self.button_disable = True
|
||
|
||
self.flag = True
|
||
|
||
self.text2.config(state="normal")
|
||
self.text2.delete("1.0", "end")
|
||
self.text2.insert("end", self.row[14])
|
||
self.text2.config(state="disabled")
|
||
|
||
|
||
for i in range(4):
|
||
state = self.correct_answer[i] + 2 * self.my_answer[i] # 0:未选对, 1:漏选, 2:错选, 3:选对
|
||
full_text = self.indexMap.get(self.shuffle_index[i]) + self.row[self.shuffle_index[i]]
|
||
|
||
if state == 1: # 漏选(正确但未选)→ 绿色
|
||
self.buttons[i].config(text=full_text, style="Miss.TButton")
|
||
elif state == 2: # 选错 → 红色
|
||
self.buttons[i].config(text=full_text, style="Wrong.TButton")
|
||
elif state == 3: # 选对 → 淡绿色
|
||
self.buttons[i].config(text=full_text, style="Correct.TButton")
|
||
else: # 未选且错误 → 不变(保持原始或默认)
|
||
self.buttons[i].config(text=full_text, style="Default.TButton")
|
||
|
||
if self.my_answer == self.correct_answer:
|
||
correct = 0 # 或者 True,表示完全正确
|
||
else:
|
||
correct = 1 # 表示不完全正确
|
||
|
||
self.c_backend.update(self.row[0], correct)
|
||
self.winfo_toplevel().focus_set()
|
||
|
||
def init(self):
|
||
self.my_answer = [0, 0, 0, 0]
|
||
self.correct_answer = []
|
||
self.flag = False
|
||
self.button_disable = False
|
||
|
||
self.row = self.c_backend.get_question()
|
||
|
||
if self.row == None:
|
||
print("没有了")
|
||
return
|
||
# 判断题处理
|
||
elif self.row[6] == "" and self.row[7] == "":
|
||
self.row[6] = "正确"
|
||
self.row[7] = "错误"
|
||
self.buttons[2].config(state="disabled")
|
||
self.buttons[3].config(state="disabled")
|
||
else:
|
||
self.buttons[2].config(state="normal")
|
||
self.buttons[3].config(state="normal")
|
||
|
||
# 更新题目
|
||
self.text1.config(state="normal")
|
||
self.text1.delete("1.0", "end")
|
||
self.text1.insert("end", self.row[4] + "\n" + self.row[5])
|
||
self.text1.config(state="disabled")
|
||
|
||
# 清空解析
|
||
self.text2.config(state="normal")
|
||
self.text2.delete("1.0", "end")
|
||
self.text2.config(state="disabled")
|
||
|
||
# 混洗选项
|
||
self.shuffle_index = [6, 7, 8, 9]
|
||
random.shuffle(self.shuffle_index)
|
||
|
||
for i in range(4):
|
||
btn_text = self.row[self.shuffle_index[i]].strip()
|
||
self.buttons[i].config(
|
||
text=f" {btn_text}",
|
||
state="normal",
|
||
style="Default.TButton"
|
||
)
|
||
self.correct_answer.append(1 if self.row[self.shuffle_index[i] + 4] == 1 else 0)
|
||
self.winfo_toplevel().focus_set()
|
||
|
||
def on_button_click(self,button_number):
|
||
if self.button_disable:
|
||
return
|
||
if sum(self.correct_answer) > 1:
|
||
if self.my_answer[button_number] == 0:
|
||
self.my_answer[button_number] = 1
|
||
self.buttons[button_number].config(style="Selected.TButton")
|
||
else:
|
||
self.my_answer[button_number] = 0
|
||
self.buttons[button_number].config(style="Default.TButton")
|
||
else:
|
||
self.my_answer[button_number] = 1
|
||
self._show_result()
|
||
self.winfo_toplevel().focus_set()
|
||
|
||
def on_ok_click(self):
|
||
if self.flag:
|
||
self.init()
|
||
else:
|
||
self. _show_result()
|
||
self.winfo_toplevel().focus_set()
|
||
|
||
if __name__ == "__main__":
|
||
from backend import Backend
|
||
root = tk.Tk()
|
||
font = Fonts()
|
||
c_backend = Backend()
|
||
app = Page0(root,font,c_backend)
|
||
root.mainloop()
|