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

Python中如何等待带Tkinter GUI的函数返回用户输入值后执行后续代码

问题分析与解决方案

你的核心问题在于没搞明白Tkinter的事件驱动特性:普通函数调用不会阻塞等待用户交互,mark()函数在创建窗口后就直接执行到末尾返回了,根本没等到用户点击"Submit"按钮——这就是为什么obj1、obj2、obj3全是None。而且你后来尝试的按钮触发方式也没用,因为那些变量在mark()调用完成时就已经被赋值为None,后续用户操作根本改不了它们的值。

解决思路:用回调函数串联异步流程

Tkinter的交互是异步的,我们不能用「顺序调用→等待返回」的思路,而是要用回调函数把流程串起来:收集完第一个数据后,再触发第二个窗口,等第三个数据收集完成,最后再调用pdf_gen()。同时用类来管理状态,避免全局变量的混乱。

修正后的代码示例

import tkinter as tk
from tkinter import StringVar, OptionMenu, Button, Label, Frame
import random
# 假设你已经定义了 cur(数据库游标)和 random_num_gen 函数

class QuestionPaperGenerator:
    def __init__(self):
        # 用来保存三个步骤的结果
        self.collected_data = []
        self.total_steps = 3
        self.current_step = 0

    def show_mark_window(self, diff, on_complete):
        """弹出选择窗口,收集数据后调用回调函数"""
        diff = diff.upper()
        win = tk.Tk()
        win.title("Question Paper Generator")
        win.configure(background='#ECECEC')
        win.geometry('650x500')
        
        t1 = StringVar(win)
        t1.set("THEORITICAL")

        def handle_submit():
            question_type = t1.get()
            # 执行数据库查询
            cur.execute(f"SELECT MAX(ID) FROM {diff}4{question_type}")
            max_id = cur.fetchone()[0]
            rand_id = random_num_gen(max_id)[0]  # 取第一个随机ID(你原代码里j=0)
            cur.execute(f"SELECT QS FROM {diff}4{question_type} WHERE ID = {rand_id}")
            question = list(cur.fetchone())
            
            win.destroy()  # 关闭当前窗口
            on_complete(question)  # 把结果传给回调

        # 界面元素
        Label(win, font="SF\Mono 16 bold", text="Enter Question Type", 
              background='#ECECEC', justify='left').grid(column=0, row=1, padx=20, pady=10)
        
        frame5 = Frame(win)
        frame5.grid(column=0, row=2, padx=0, pady=10)
        OptionMenu(frame5, t1, "THEORITICAL", "PROOF", "MCQ", "NUMERICAL").grid(column=0, row=0)
        
        frame4 = Frame(win)
        frame4.grid(column=0, row=11, padx=0, pady=10)
        Button(frame4, text="Submit", command=handle_submit).grid(column=0, row=0)
        
        win.mainloop()

    def on_step_complete(self, result):
        """每完成一个步骤的回调"""
        self.collected_data.append(result)
        self.current_step += 1
        
        if self.current_step < self.total_steps:
            # 还没完成所有步骤,继续弹出下一个窗口
            self.show_mark_window("Easy", self.on_step_complete)
        else:
            # 三个数据都收集完了,生成PDF
            self.pdf_gen(*self.collected_data)

    def pdf_gen(self, obj1, obj2, obj3):
        """你的PDF生成逻辑"""
        print("开始生成PDF,获取到的题目:")
        print(f"题目1: {obj1}")
        print(f"题目2: {obj2}")
        print(f"题目3: {obj3}")
        # 这里替换成你的实际PDF生成代码

    def start(self):
        """启动整个流程"""
        self.show_mark_window("Easy", self.on_step_complete)

# 运行程序
if __name__ == "__main__":
    app = QuestionPaperGenerator()
    app.start()

关键说明

  1. 用类管理状态:collected_data列表保存每一步的结果,避免了全局变量的混乱,也方便在回调之间共享数据。
  2. 回调串联流程:show_mark_window函数接受一个on_complete回调,用户点击提交后,会把结果传给这个回调,然后关闭当前窗口。
  3. 分步触发:每完成一个步骤,检查是否收集完所有数据,如果没有就继续弹出下一个选择窗口,直到三个数据都收集好,才调用pdf_gen()。

这样就能保证程序严格等待用户完成每一步输入后,再执行后续的PDF生成逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:27:03