为何用Tk()创建Tkinter第二个窗口无法更新Label的textvariable?
问题原因与解决方案
核心问题
Tkinter的StringVar(包括IntVar、DoubleVar等变量类)默认会绑定到第一个创建的Tk()实例对应的Tcl解释器。当你在load()中新建第二个Tk()窗口时,text = StringVar()没有指定归属窗口,这个变量会默认关联最初的主窗口,和新窗口的Label不属于同一个Tcl环境,导致变量更新时Label无法同步变化。而Toplevel()是依附主窗口的子窗口,变量默认关联主窗口,因此能正常工作。
快速修复方案
创建StringVar时,明确指定它的master为新创建的loading_window,让变量与新窗口绑定:
text = StringVar(master=loading_window)
修改后的完整代码
from tkinter import * from tkinter import ttk def fill(s,c): c += 1 the_bar['value'] = c if c == 25: text.set('text 2') elif c == 50: text.set('text 3') elif c == 75: text.set('text 4') if c <= s: loading_window.after(50,fill,s,c) else: the_bar.destroy() loading_window.destroy() def load(): global loading_window loading_window = Tk() loading_window.title('loading') global text # 明确指定变量归属的窗口 text = StringVar(master=loading_window) text.set('text 1') txt = Label(loading_window,textvariable=text) txt.pack() global the_bar the_bar = ttk.Progressbar(loading_window,length=300,orient=HORIZONTAL,maximum=100) the_bar.pack() delay, steps, count = 50,100,0 loading_window.after(delay,fill,steps,count) loading_window.mainloop() # 主窗口调用示例(销毁主窗口后启动加载窗口) # def start_load(): # root.destroy() # load() # root = Tk() # Button(root, text="启动加载", command=start_load).pack() # root.mainloop()
更规范的做法
Tkinter官方不推荐同时存在多个Tk()实例,因为每个实例对应独立的Tcl解释器,容易引发同步问题。如果你的需求是销毁主窗口后运行新窗口,建议先销毁主窗口,再创建新的Tk()实例,这样新窗口的变量会默认绑定自身的Tcl环境,无需额外指定master也能正常工作(如上述代码注释中的示例)。
内容的提问来源于stack exchange,提问作者Smart boy
相关产品推荐
相关产品推荐

