从tkinter子窗口获取变量

时间:2019-07-18 15:38:04

标签: python 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生成一个子窗口,询问用户新数据,然后销毁该子窗口并将新输入的数据传回直到调用函数。

理论上,这可以使我不必从头开始重新启动代码,因为此subwindow_test函数可以在代码中的任何位置运行。

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

有没有解决这个问题的方法?

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

据我所知,也无法将子窗口对象传递回调用函数并在此处关闭它,因为subwindow_test直到返回window.sub_win.mainloop()才返回(如果返回值在mainloop()之前,则该窗口将永远不会出现)。

此外,我发现唯一可以返回值的唯一方法是使用StringVar。我宁愿尝试避免使用全局变量,而且如果不得不猜测,我会说return val.get()很可能是问题的根源。但是,由于找不到从该函数向上传递变量的其他方法,因此感到很困惑。

1 个答案:

答案 0 :(得分:1)

您不应该多次致电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