You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter问答程序故障排查:如何避免题目直接跳至最后一题?

修复Tkinter随机加减问答程序的题目展示异常问题

问题描述

使用Tkinter开发随机加减问答程序,要求用户依次完成10道题目,但当前程序存在以下问题:

  • 程序运行后直接跳过前9题,仅显示第10题的GUI界面,终端提前输出所有错误提示信息。
  • 经AI修改后的代码无法弹出GUI界面。
    需要修复代码,实现题目从第1题到第10题依次展示的效果。

原始代码

import tkinter as tk
from tkinter import ttk, messagebox, END
from tkinter import *
import random

def qna():
    qna = tk.Tk()
    qna.title("Quiz")
    question = 1
    attempt = 1
    uscore = 0
    answer = 0
    while question <=10:
        num1 = random.randint(0, 9)
        num2 = random.randint(0, 9)
        score = num1 + num2
        while True:
            while True:
                try:
                    tk.Label(qna, text = f"Question {question}, Attempt {attempt}\nWhat's the answer for {num1} + {num2}?: ").grid(row=0, column=0, padx=5, pady=5)
                    answer_entry = tk.Entry(qna)
                    answer_entry.grid(row=1, column=0, padx=5, pady=5)
                    qna.btnSubmitAnswer = tk.Button(qna, text="Submit", command=qna_submit).grid(row=2, column=0)
                    break
                except Exception:
                    messagebox.showwarning("Warning", "Please try again with a number.")
                    continue
            if answer == score:
                print("Bravo", "That's correct. Good job!")
                attempt = 1
                question += 1
                uscore += 1
                answer_entry.delete(0, END)
                break
            elif answer != score and attempt == 3:
                print(f"That's wrong, you ran out of attempt. The answer is {score}")
                attempt = 1
                question += 1
                answer_entry.delete(0, END)
                break
            elif answer != score:
                print("That's wrong, please try again.")
                attempt += 1
                continue
    qna.mainloop()
    
def qna_submit():
    qna.answer = qna.answer_entry.get()
    
qna()

异常输出

仅弹出第10题的GUI界面,终端输出如下:

That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 5
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 10
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 12
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 11
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 8
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 9
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 12
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 9
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 14
That's wrong, please try again.
That's wrong, please try again.
That's wrong, you ran out of attempt. The answer is 10

AI修改后的代码(未添加mainloop版本)

import tkinter as tk
from tkinter import ttk, messagebox, END
from tkinter import *
import random

def qna():
    qna = tk.Tk()
    qna.title("Quiz")
    question = 1
    attempt = 1
    uscore = 0
    answer = 0

    def qna_submit(answer_entry, answer):
        answer = answer_entry.get()
        if answer == str(score):
            messagebox.showinfo("Bravo", "That's correct. Good job!")
            attempt = 1
            question += 1
            uscore += 1
            answer_entry.delete(0, END)
        elif attempt == 3:
            messagebox.showinfo("Out of attempts", f"That's wrong, you ran out of attempts. The answer is {score}")
            attempt = 1
            question += 1
            answer_entry.delete(0, END)
        else:
            messagebox.showinfo("Wrong answer", "That's wrong, please try again.")
            attempt += 1

    while question <= 10:
        num1 = random.randint(0, 9)
        num2 = random.randint(0, 9)
        score = num1 + num2
        while True:
            try:
                tk.Label(qna, text = f"Question {question}, Attempt {attempt}\nWhat's the answer for {num1} + {num2}?: ").grid(row=0, column=0, padx=5, pady=5)
                answer_entry = tk.Entry(qna)
                answer_entry.grid(row=1, column=0, padx=5, pady=5)
                btnSubmitAnswer = tk.Button(qna, text="Submit", command=lambda: qna_submit(answer_entry, answer))
                btnSubmitAnswer.grid(row=2, column=0)
                break
            except Exception:
                messagebox.showwarning("Warning", "Please try again with a number.")
                continue

qna()

问题根源分析

  1. 阻塞事件循环:原始代码和AI修改后的代码都使用while循环直接遍历题目,而Tkinter的GUI更新依赖mainloop()处理事件,循环会阻塞mainloop()启动,导致GUI无法实时更新,直到循环结束才显示最后一题。
  2. 变量作用域错误:qna_submit函数无法正确访问或修改外部变量(如question、attempt),且原始代码中answer始终为0,导致循环直接判定答案错误,提前跑完所有题目。
  3. AI修改代码遗漏核心:AI修改后的代码未调用qna.mainloop(),导致GUI完全无法启动。

修复后的代码

import tkinter as tk
from tkinter import messagebox, END
import random

def qna():
    root = tk.Tk()
    root.title("随机加减问答")
    
    # 初始化全局状态变量
    question_num = 1
    attempt_num = 1
    score = 0
    current_num1 = 0
    current_num2 = 0
    correct_answer = 0
    
    # 创建界面组件
    question_label = tk.Label(root, text="", font=("Arial", 12))
    question_label.grid(row=0, column=0, padx=20, pady=20)
    
    answer_entry = tk.Entry(root, font=("Arial", 12))
    answer_entry.grid(row=1, column=0, padx=20, pady=10)
    
    submit_btn = tk.Button(root, text="提交答案", font=("Arial", 12), command=check_answer)
    submit_btn.grid(row=2, column=0, padx=20, pady=10)
    
    # 生成新题目
    def generate_question():
        nonlocal question_num, attempt_num, current_num1, current_num2, correct_answer
        current_num1 = random.randint(0, 9)
        current_num2 = random.randint(0, 9)
        correct_answer = current_num1 + current_num2
        question_label.config(text=f"第{question_num}题,第{attempt_num}次尝试\n{current_num1} + {current_num2} = ?")
        answer_entry.delete(0, END)
    
    # 检查答案
    def check_answer():
        nonlocal question_num, attempt_num, score, correct_answer
        user_input = answer_entry.get().strip()
        
        # 验证输入是否为数字
        if not user_input.isdigit():
            messagebox.showwarning("输入错误", "请输入有效的数字!")
            return
        
        user_answer = int(user_input)
        
        if user_answer == correct_answer:
            messagebox.showinfo("正确", "太棒了!回答正确!")
            score += 1
            question_num += 1
            attempt_num = 1
            # 判断是否完成所有题目
            if question_num > 10:
                messagebox.showinfo("答题结束", f"所有题目完成!你的得分是:{score}/10")
                root.destroy()
                return
            generate_question()
        else:
            if attempt_num == 3:
                messagebox.showinfo("次数用完", f"错误!已用完3次尝试机会,正确答案是:{correct_answer}")
                question_num += 1
                attempt_num = 1
                if question_num > 10:
                    messagebox.showinfo("答题结束", f"所有题目完成!你的得分是:{score}/10")
                    root.destroy()
                    return
                generate_question()
            else:
                attempt_num += 1
                messagebox.showwarning("错误", f"回答错误!还有{3 - attempt_num + 1}次尝试机会")
                question_label.config(text=f"第{question_num}题,第{attempt_num}次尝试\n{current_num1} + {current_num2} = ?")
    
    # 生成第一题
    generate_question()
    
    root.mainloop()

qna()

关键修改说明

  1. 事件驱动替代循环:移除while循环,改用generate_question函数生成题目,每次提交答案后触发界面更新,符合Tkinter的事件驱动模型。
  2. 变量作用域处理:使用nonlocal关键字让内部函数可以修改外部变量,确保状态正确更新。
  3. 输入验证:添加数字输入检查,避免非数字输入导致错误。
  4. 界面组件复用:创建固定的标签、输入框和按钮,通过修改组件内容更新题目,而非重复创建组件。
  5. 完整的流程控制:处理答题完成后的结束逻辑,显示最终得分并关闭窗口。

内容的提问来源于stack exchange,提问作者Oofie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:14:50