Python 从tkinter子窗口获取变量

Python 从tkinter子窗口获取变量,python,tkinter,Python,Tkinter,我目前正在用python编写一个脚本,它在脚本开始时接收用户数据,以后可能需要更新这些数据 初始用户数据通过tkinter窗口输入,然后传递给下层函数。在脚本的后面,如果检测到信息不正确,我想提醒用户信息不正确,并提示他们重新输入数据,而不必从头开始启动程序 我试图通过添加一个子窗口函数来实现这一点,该子窗口函数将在需要重新输入数据时调用,获取新的用户输入,然后将其传递回调用它的函数。下面的代码大致显示了我正在尝试执行的操作: import tkinter as tk from tkinter

我目前正在用python编写一个脚本,它在脚本开始时接收用户数据,以后可能需要更新这些数据

初始用户数据通过tkinter窗口输入,然后传递给下层函数。在脚本的后面,如果检测到信息不正确,我想提醒用户信息不正确,并提示他们重新输入数据,而不必从头开始启动程序

我试图通过添加一个子窗口函数来实现这一点,该子窗口函数将在需要重新输入数据时调用,获取新的用户输入,然后将其传递回调用它的函数。下面的代码大致显示了我正在尝试执行的操作:

import tkinter as tk
from tkinter import *

def gui():

    window = tk.Tk()

    window.geometry('300x200')

    L1 = tk.Label(window, text = 'This is a test')
    L1.grid(column = 1, row = 0)
    L2 = tk.Label(window, text = 'Token')
    L2.grid(column = 0, row = 1)
    E1 = tk.Entry(window, width = 25)
    E1.grid(column = 1, row = 1)
    B1 = tk.ttk.Button(window, text = 'Run', command = lambda: shell(window, E1.get()))
    B1.grid(column = 1, row = 2)

    window.mainloop()


def shell(window, val):
    print('Old Val:', val)
    val = subwindow_test(window)
    print('New Val:', val)

def subwindow_test(window):
    def subwinfunc(window, val):
        if val == None or val == '':
            print('Enter something')
        else:
            window.sub_win.destroy()       
            return

    window.sub_win = tk.Toplevel(window)

    window.sub_win.geometry('300x200')

    L1 = tk.Label(window.sub_win, text = 'this is a subwindow')
    L1.grid(column = 1, row = 0)
    L2 = tk.Label(window.sub_win, text = 'New Token')
    L2.grid(column = 0, row = 1, sticky = 'E')
    var = StringVar()    
    E1 = tk.Entry(window.sub_win, width = 25, textvariable = var)
    E1.grid(column = 1, row = 1)
    B1 = tk.ttk.Button(window.sub_win, text = 'Return', command = lambda: subwinfunc(window, var.get()))
    B1.grid(column = 1, row = 2)

    window.sub_win.mainloop()


    return var.get()



gui()
其思想是将窗口向下传递给subwindow_test函数,使用tk.Toplevel生成一个子窗口,向用户请求新数据,然后销毁子窗口并将新输入的数据传递回调用函数

理论上,这将避免我从一开始就重新启动代码,因为这个子窗口测试函数可以从代码中的任何地方运行

问题是,在销毁window.sub_win后,subwinfunc返回后,代码将挂起,直到关闭在gui函数中创建的原始窗口对象。此外,从subwinfunc中删除返回行不会改变这一点

有没有办法绕过这个问题

我尝试过使用一个单独的窗口,一个完全不同的窗口,而不是gui中创建的子窗口,但是同样的问题出现了

据我所知,也不可能将子窗口对象传递回调用函数并在那里关闭它,因为子窗口测试无法返回,直到它从window.sub\u win.mainloop中断。如果返回在mainloop之前,窗口将永远不会出现

此外,我能找到的唯一获得返回值的方法是使用StringVar。我宁愿尝试避免使用全局变量,如果我不得不猜测,我会说返回val.get很可能是问题的根源。然而,因为我找不到从这个函数向上传递变量的其他方法,我被难住了。

您不应该多次调用mainloop。Tkinter提供了在继续使用wait_window方法之前等待窗口关闭的功能

下面是一个非常简单的示例,演示如何创建一个弹出对话框,直到用户单击“确定”或“取消”按钮后才会返回

def get_input():
    value = None
    def do_ok(event=None):
        nonlocal value
        value = entry.get()
        top.destroy()

    def do_cancel():
        nonlocal value
        value = None
        top.destroy()

    top = tk.Toplevel()
    entry = tk.Entry(top)
    ok = tk.Button(top, text="ok", command=do_ok)
    cancel = tk.Button(top, text="cancel", command=do_cancel)
    entry.bind("<Return>", do_ok)

    entry.pack(side="top", fill="x")
    ok.pack(side="right")
    cancel.pack(side="left")

    top.wait_window(top)

    return value