当我在减法测验中按下多项选择按钮时,Tkinter 窗口崩溃

问题描述 投票:0回答:1

我创建了一个图形测验。当我在减法测验中按下多项选择按钮时,Tkinter 窗口崩溃。它不会在任何其他类型的测验中崩溃。有时,当我单击多项选择按钮时,它会起作用,但只会进一步崩溃到测验中:

import tkinter as tk
import random

def main_menu():
    clear_window()
    root.configure(bg='DodgerBlue4')

    title = tk.Label(root, text="Math Quiz", font=("Arial", 32), bg='DodgerBlue4', fg='white')
    title.pack(pady=40)

    button_frame = tk.Frame(root, bg='DodgerBlue4')
    button_frame.pack(pady=20)

    operations = [
        ("Multiplication", lambda: select_quiz_type('Multiplication'), 'red'),
        ("Addition", lambda: select_quiz_type('Addition'), 'forest green'),
        ("Subtraction", lambda: select_quiz_type('Subtraction'), 'blue'),
        ("Division", lambda: select_quiz_type('Division'), 'gold'),
    ]

    for operation, command1, color in operations:
        if command1:
            tk.Button(button_frame, text=operation, font=("Arial", 18), command=command1, bg=color, fg='white', width=12).pack(side='left', padx=20)


def clear_window():
    for widget in root.winfo_children():
        widget.destroy()

def select_quiz_type(operation):
    clear_window()
    root.configure(bg='DodgerBlue4')

    label = tk.Label(root, text=f"{operation} Quiz Type", font=("Arial", 24), bg='DodgerBlue4', fg='white')
    label.pack(pady=20)

    button_frame = tk.Frame(root, bg='DodgerBlue4')
    button_frame.pack(pady=20)

    tk.Button(button_frame, text="Multiple Choice", font=("Arial", 18), command=lambda: start_quiz(operation, "multiple_choice"), bg='gold', fg='black').pack(side='left', padx=20)
    tk.Button(button_frame, text="Submit Box", font=("Arial", 18), command=lambda: start_quiz(operation, "submit_box"), bg='gold', fg='black').pack(side='left', padx=20)

def start_quiz(operation, quiz_type):
    if operation == "Multiplication":
        create_quiz("Multiplication", lambda: (random.randint(1, 12), random.randint(1, 12)), lambda x, y: x * y, quiz_type)
    elif operation == "Addition":
        create_quiz("Addition", lambda: (random.randint(0, 100), random.randint(0, 100)), lambda x, y: x + y, quiz_type)
    elif operation == "Subtraction":
        create_quiz("Subtraction", lambda: (random.randint(0, 100), random.randint(0, 100)), lambda x, y: x - y, quiz_type)
    elif operation == "Division":
        create_quiz("Division", lambda: (random.randint(1, 100), random.randint(1, 10)), lambda x, y: x // y if y != 0 else 1, quiz_type)

def create_quiz(title, question_generator, answer_function, quiz_type):
    global current_operation, quiz_questions, quiz_answers, current_question, score, question_label, answer_buttons, answer_entry, current_quiz_type
    clear_window()

    current_operation = title.split()[0]
    current_quiz_type = quiz_type

    tk.Label(root, text=f"{title} Quiz", font=("Arial", 24), bg='DodgerBlue4', fg='white').pack(pady=20)

    quiz_questions = []
    quiz_answers = []

    for _ in range(10):
        x, y = question_generator()
        quiz_questions.append((x, y))
        quiz_answers.append(answer_function(x, y))

    current_question = 0
    score = 0

    question_label = tk.Label(root, font=("Arial", 18), bg='DodgerBlue4', fg='white')
    question_label.pack(pady=20)

    if quiz_type == "multiple_choice":
        answer_buttons = []
        for i in range(4):
            btn = tk.Button(root, font=("Arial", 18), bg='gold', fg='black', command=lambda control=i: check_mp_ans(control))
            btn.pack(pady=5)
            answer_buttons.append(btn)
    else:
        answer_entry = tk.Entry(root, font=("Arial", 18))
        answer_entry.pack(pady=10)
        tk.Button(root, text="Submit", font=("Arial", 18), command=check_sb_ans, bg='gold', fg='black').pack(pady=20)

    update_question()

def update_question():
    global current_question, quiz_questions, question_label, quiz_answers, current_quiz_type, answer_buttons
    if current_question < len(quiz_questions):
        x, y = quiz_questions[current_question]
        symbol = 'x' if current_operation == 'Multiplication' else '+' if current_operation == 'Addition' else '-' if current_operation == 'Subtraction' else '/'
        question_label.config(text=f"Question {current_question + 1}: {x} {symbol} {y} = ?")

        if current_quiz_type == "multiple_choice":
            correct_answer = quiz_answers[current_question]
            choices = [correct_answer]
            while len(choices) < 4:
                choice = random.randint(correct_answer - 10, correct_answer + 10)
                if choice not in choices and choice >= 0:
                    choices.append(choice)
            random.shuffle(choices)
            for i, choice in enumerate(choices):
                answer_buttons[i].config(text=str(choice))
    else:
        show_results()

def check_mp_ans(control):
    global current_question, score, quiz_answers
    selected_answer = int(answer_buttons[control].cget('text'))
    correct_answer = quiz_answers[current_question]
    if selected_answer == correct_answer:
        score += 1
        result_text = "Correct!"
    else:
        result_text = f"Wrong! The correct answer was {correct_answer}."

    current_question += 1
    show_answer_result(result_text)

def check_sb_ans():
    global current_question, score, quiz_answers, answer_entry
    try:
        user_answer = int(answer_entry.get())
    except ValueError:
        user_answer = None
    correct_answer = quiz_answers[current_question]
    if user_answer == correct_answer:
        score += 1
        result_text = "Correct!"
    else:
        result_text = f"Wrong! The correct answer was {correct_answer}."

    current_question += 1
    answer_entry.delete(0, tk.END)
    show_answer_result(result_text)

def show_answer_result(result_text):
    clear_window()
    root.configure(bg='DodgerBlue4')

    tk.Label(root, text=result_text, font=("Arial", 24), bg='DodgerBlue4', fg='white').pack(pady=20)
    tk.Button(root, text="Next", font=("Arial", 18), command=recreate_question_interface, bg='gold', fg='black').pack(pady=20)

def recreate_question_interface():
    clear_window()
    global question_label, answer_buttons, answer_entry
    question_label = tk.Label(root, font=("Arial", 18), bg='DodgerBlue4', fg='white')
    question_label.pack(pady=20)
    if current_quiz_type == "multiple_choice":
        answer_buttons = []
        for i in range(4):
            btn = tk.Button(root, font=("Arial", 18), bg='gold', fg='black', command=lambda control=i: check_mp_ans(control))
            btn.pack(pady=5)
            answer_buttons.append(btn)
    else:
        answer_entry = tk.Entry(root, font=("Arial", 18))
        answer_entry.pack(pady=10)
        tk.Button(root, text="Submit", font=("Arial", 18), command=check_sb_ans, bg='gold', fg='black').pack(pady=20)
    update_question()

def show_results():
    global score, quiz_questions
    clear_window()
    root.configure(bg='DodgerBlue4')

    tk.Label(root, text="Quiz Complete!", font=("Arial", 24), bg='DodgerBlue4', fg='white').pack(pady=20)
    tk.Label(root, text=f"Your score: {score}/{len(quiz_questions)}", font=("Arial", 18), bg='DodgerBlue4', fg='white').pack(pady=10)
    tk.Button(root, text="Main Menu", font=("Arial", 18), command=main_menu, bg='gold', fg='black').pack(pady=20)

root = tk.Tk()
root.geometry("900x600")
main_menu()
root.mainloop()

我在两台设备上尝试过,但也不起作用。该按钮变灰,Tkinter 窗口停止响应。

python tkinter crash
1个回答
0
投票

问题是

update_question()
中的无限循环。当减法问题的答案小于 -10 时,就会发生这种情况。发生这种情况时,该函数无法在
correct_answer-10
correct_answer+10
之间生成满足
choice >= 0
的答案选择。这会导致无限循环,因为
len(choices) < 4
始终为 true。

# If the answer is less than -10:
while len(choices) < 4: # Always true
    choice = random.randint(correct_answer - 10, correct_answer + 10) # Always < 0
    if choice not in choices and choice >= 0: # Always false
        choices.append(choice)

您有几种解决此问题的选项。一是完全删除

choice >= 0
并允许否定答案。如果您仍然想将答案限制为非负数,您可以在问题生成器中添加一些代码,以在需要时交换
x
y

def create_quiz(...):
    ...

    for _ in range(10):
        x, y = question_generator()
        answer = answer_function(x, y)
        if answer < 0:
            x, y = y, x
        answer = answer_function(x, y)
        quiz_questions.append((x, y))
        quiz_answers.append(answer)

    ...
© www.soinside.com 2019 - 2024. All rights reserved.