Python Tkinter类封装Listbox初始值未正常显示问题排查
问题:类封装的Tkinter Listbox无法显示初始选项
环境:Python 3.8 + macOS Big Sur
以下类封装代码运行时,Listbox无法显示预期的初始选项:
import tkinter as tk class GUI(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.root = tk.Tk() self.root.title('title') self.root.geometry("300x100+630+80") self.interface() def interface(self): LIST = ["Go", "Python", "Java", "Dart", "JavaScript"] var = tk.StringVar() var.set(LIST) lb = tk.Listbox(self.root, listvariable=var, selectmode=tk.BROWSE) print('var.get()', var.get()) lb.pack(padx=10, pady=10) if __name__ == '__main__': gui = GUI() gui.root.mainloop()
但非类封装的代码可以正常显示所有初始选项:
from tkinter import * root = Tk() list_var = StringVar() list_var.set(["Go", "Python", "Java", "Dart", "JavaScript"]) Listbox(root, listvariable=list_var, selectmode=BROWSE).pack() root.mainloop()
问题原因
核心错误是创建了两个独立的Tk主窗口实例:
GUI类继承自tk.Tk,__init__中调用tk.Tk.__init__(self)已经初始化了一个主窗口;- 同时又新建
self.root = tk.Tk(),生成第二个完全独立的Tk上下文; - 创建的
StringVar默认绑定到第一个Tk实例,却被挂载到第二个窗口的Listbox上,变量与窗口上下文不匹配,导致Listbox无法读取选项数据。
修复方案
方案1:取消继承,用组合方式管理窗口
不再让GUI继承tk.Tk,仅通过self.root维护唯一主窗口:
import tkinter as tk class GUI: def __init__(self): self.root = tk.Tk() self.root.title('title') self.root.geometry("300x100+630+80") self.interface() def interface(self): LIST = ["Go", "Python", "Java", "Dart", "JavaScript"] var = tk.StringVar() var.set(LIST) lb = tk.Listbox(self.root, listvariable=var, selectmode=tk.BROWSE) lb.pack(padx=10, pady=10) if __name__ == '__main__': gui = GUI() gui.root.mainloop()
方案2:利用继承特性,直接用self作为主窗口
保留GUI对tk.Tk的继承,直接用self作为主窗口实例,不再额外创建self.root:
import tkinter as tk class GUI(tk.Tk): def __init__(self): super().__init__() self.title('title') self.geometry("300x100+630+80") self.interface() def interface(self): LIST = ["Go", "Python", "Java", "Dart", "JavaScript"] var = tk.StringVar() var.set(LIST) lb = tk.Listbox(self, listvariable=var, selectmode=tk.BROWSE) lb.pack(padx=10, pady=10) if __name__ == '__main__': gui = GUI() gui.mainloop()
内容的提问来源于stack exchange,提问作者missmango
相关产品推荐
相关产品推荐

