我目前正在用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()
很可能是问题的根源。但是,由于找不到从该函数向上传递变量的其他方法,因此感到很困惑。
答案 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