我正在尝试编写一个基本的测验应用程序。由于某种原因,当我前后移动时,小测验不会像我想象的那样重置。例如,如果我正在测验中途,如果我决定向前点击箭头然后再次返回,我的进度应该被重置。我有两个脚本,我向您展示一个是我的 main.py,另一个是 quizzes.py。还有我用于测验的 csv 文件的摘录。
问题、答案 爆炸,爆炸 姓氏,埃尔阿佩利多 会议, 会议 强度,la intensidad 包裹,el paquete 该提案,la propuesta 瓶子,拉博特拉 尸体,el cadaver 组合, 组合 那位女士,拉达玛 涟漪,拉昂达 塔,拉托雷 渴望,el afán 委员会 等等等等 不便, el inconveniente 水龙头,拉拉夫 占有, 姿势 候选人, el Candidato 煤气,煤气
import ttkbootstrap as tb
from quizzes import Quizzes
# main.py
class App(tb.Window):
def __init__(self, *args, **kwargs):
super().__init__(*args, themename='superhero', **kwargs)
self.title('App')
self.geometry('400x300')
container = tb.Frame(self)
container.pack(side="top", fill="both", expand=True)
self.frames = {}
for F in (Quizzes):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.pack(anchor='center')
if __name__ == "__main__":
app = App()
app.mainloop()
import itertools
import pandas as pd
import ttkbootstrap as tb
from PIL import Image
Image.CUBIC = Image.BICUBIC
# quizzes.py
class Quizzes(tb.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
self.parent = parent
self.question_length = 5
# add meter
self.quiz_meter = tb.Meter(self, amounttotal=self.question_length, textright='of',
subtext=f'{self.question_length} correct answers')
self.quiz_meter.pack(anchor='center', pady=10)
# add question label
self.quiz_question = tb.Label(self, text='Question', font=('Helvetica', 22))
self.quiz_question.pack(anchor='center', pady=10)
# entry
self.quiz_entry = tb.Entry(self, font=('Helvetica', 25), justify='center')
self.quiz_entry.pack(anchor='center', pady=10)
self.quiz_entry.bind('<Return>', self.enter_answer)
# Quiz number label
self.quiz_number = tb.Label(self, text=1, font=('Helvetica', 18))
self.quiz_number.pack(anchor='center', pady=10)
# establish button style
self.btn_style = tb.Style()
self.btn_style.configure('outline.TButton', font=('Helvetica', 18))
# back button
self.back_btn = tb.Button(self, text='<', command=self.back, style='outline.TButton')
self.back_btn.pack(side='left', pady=10)
# forward button
self.forward_btn = tb.Button(self, text='>', command=self.forward, style='outline.TButton')
self.forward_btn.pack(side='right', pady=10)
# Main menu button
self.main_menu_btn = tb.Button(self, text='Main Menu', command=self.main_menu, style='outline.TButton')
self.main_menu_btn.pack(anchor='center', pady=10)
# df
self.df = pd.read_csv('csv files\\1000 Spanish Nouns.csv')
# separate df into multiple parts
self.quizzes = []
for i in range(0, len(self.df), self.question_length):
if i + self.question_length < len(self.df) + 1:
dataframe = self.df.iloc[i:i + self.question_length]
lst = [tuple(row) for row in dataframe.itertuples(index=False, name=None)]
self.quizzes.append(lst)
else:
dataframe = self.df.iloc[i:]
lst = [tuple(row) for row in dataframe.itertuples(index=False, name=None)]
self.quizzes.append(lst)
# establish first quiz to test on
self.quiz_index = 0
self.current_quiz = self.quizzes[self.quiz_index]
# quiz cycle
self.quiz_cycle = itertools.cycle(self.current_quiz)
# Setup first question
self.row = next(self.quiz_cycle)
self.question = self.row[0]
self.answer = self.row[1]
self.quiz_question.config(text=self.question)
def back(self):
# Reset meter
self.quiz_meter.configure(amountused=0)
# enable entry
self.quiz_entry.config(state='normal')
# Set next quiz
if self.quiz_index != 0:
self.quiz_index -= 1
self.current_quiz = self.quizzes[self.quiz_index]
self.quiz_cycle = itertools.cycle(self.current_quiz)
else:
self.current_quiz = self.quizzes[self.quiz_index]
self.quiz_cycle = itertools.cycle(self.current_quiz)
# Load first question
self.row = next(self.quiz_cycle)
self.question = self.row[0]
self.answer = self.row[1]
self.quiz_question.config(text=self.question)
# Set new quiz number
self.quiz_number.config(text=self.quiz_index + 1)
def forward(self):
# Reset meter
self.quiz_meter.configure(amountused=0)
# enable entry
self.quiz_entry.config(state='normal')
# Set next quiz
if self.quiz_index != len(self.quizzes) - 1:
self.quiz_index += 1
self.current_quiz = self.quizzes[self.quiz_index]
self.quiz_cycle = itertools.cycle(self.current_quiz)
else:
self.current_quiz = self.quizzes[self.quiz_index]
self.quiz_cycle = itertools.cycle(self.current_quiz)
# Load first question
self.row = next(self.quiz_cycle)
self.question = self.row[0]
self.answer = self.row[1]
self.quiz_question.config(text=self.question)
# Set new quiz number
self.quiz_number.config(text=self.quiz_index + 1)
print(self.current_quiz)
def main_menu(self):
pass
def enter_answer(self, event):
# Check answer
if self.quiz_entry.get() == self.answer:
self.quiz_meter.configure(bootstyle='success')
self.parent.after(400, self.reset_meter)
self.quiz_meter.configure(amountused=self.quiz_meter.amountusedvar.get() + 1)
# if last question is correct disable quiz
if self.quiz_meter.amountusedvar.get() == self.question_length:
self.quiz_question.config(text='Completed!')
self.quiz_entry.delete(0, tb.END)
self.quiz_entry.config(state='disabled')
return
self.current_quiz.remove(self.row)
self.quiz_cycle = itertools.cycle(self.current_quiz)
self.parent.after(400, self.next_question)
else:
self.quiz_meter.configure(bootstyle='danger')
self.parent.after(2000, self.reset_meter)
self.quiz_question.config(text=self.answer)
self.parent.after(2000, self.next_question)
def next_question(self):
# Clear entry
self.quiz_entry.delete(0, tb.END)
# next question
self.row = next(self.quiz_cycle)
self.question = self.row[0]
self.answer = self.row[1]
self.quiz_question.config(text=self.question)
def reset_meter(self):
self.quiz_meter.configure(bootstyle="info")
代码中导致测验重置问题的原因是
forward
和
back
函数的逻辑。问题在于,当使用
itertools.cycle
创建
self.quiz_cycle
时,正在创建一个迭代器,该迭代器在迭代完当前测验后循环回到测验的开头。这意味着,当前进或后退到新测验,然后又返回时,
self.quiz_cycle
迭代器将从上一次停止的位置继续,而不是从测验的开头重新开始。
要解决此问题,需要在每次切换测验时重新创建
self.quiz_cycle
迭代器。可以通过将
self.quiz_cycle = itertools.cycle(self.current_quiz)
行移到
forward
和
back
函数的调用
next(self.quiz_cycle)
之前来实现。
以下是更新后的
forward
和
back
函数:
def back(self):
# Reset meter
self.quiz_meter.configure(amountused=0)
# enable entry
self.quiz_entry.config(state='normal')
# Set next quiz
if self.quiz_index != 0:
self.quiz_index -= 1
self.current_quiz = self.quizzes[self.quiz_index]
else:
self.current_quiz = self.quizzes[self.quiz_index]
# Reset quiz cycle
self.quiz_cycle = itertools.cycle(self.current_quiz)
# Load first question
self.row = next(self.quiz_cycle)
self.question = self.row[0]
self.answer = self.row[1]
self.quiz_question.config(text=self.question)
# Set new quiz number
self.quiz_number.config(text=self.quiz_index + 1)
def forward(self):
# Reset meter
self.quiz_meter.configure(amountused=0)
# enable entry
self.quiz_entry.config(state='normal')
# Set next quiz
if self.quiz_index != len(self.quizzes) - 1:
self.quiz_index += 1
self.current_quiz = self.quizzes[self.quiz_index]
else:
self.current_quiz = self.quizzes[self.quiz_index]
# Reset quiz cycle
self.quiz_cycle = itertools.cycle(self.current_quiz)
# Load first question
self.row = next(self.quiz_cycle)
self.question = self.row[0]
self.answer = self.row[1]
self.quiz_question.config(text=self.question)
# Set new quiz number
self.quiz_number.config(text=self.quiz_index + 1)
print(self.current_quiz)
通过进行此更改,每次切换测验时,都会创建一个新的
self.quiz_cycle
迭代器,该迭代器从测验的开头开始,从而确保测验按预期重置。