Tkinter框架切换异常:多框架同时显示无法切换的修复
修复Tkinter框架切换失效问题
问题现象
所有框架同时显示且无法隐藏,框架切换功能完全失效。
关键缺陷
main_menuHauptmenu类中的Combobox未绑定选择事件,仅定义lambda表达式但未触发执行,导致选择选项后无法切换框架;lange类创建gl_frame时未指定父容器,使得该框架直接显示在主窗口而非当前lange实例内部,造成多框架叠加显示;main类中重复初始化self.frames变量,属于冗余代码。
修复措施
- 为
unit_modusCombobox绑定<<ComboboxSelected>>事件,触发框架切换逻辑; - 修改
lange类中gl_frame的创建代码,指定父容器为当前lange实例; - 删除
main类中重复的self.frames = {}语句。
修复后的完整代码
import tkinter as tk from tkinter import ttk class main(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.resizable(height=1000, width=700) self.title("a") root = tk.Frame(self) root.pack(fill="both", expand=True) self.frames = {} container = tk.Frame(self) container.pack(side="top", fill="both", expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) # 移除重复的self.frames初始化 for F in (main_menuHauptmenu, lange): frame = F(container, self) self.frames[F] = frame frame.grid(row=0, column=0, sticky="nsew") self.show_frame(main_menuHauptmenu) def show_frame(self, page_name): frame = self.frames[page_name] frame.tkraise() class main_menuHauptmenu(ttk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) hm_label = ttk.Label(self, text="Select Conversion Mode", font=("Times New Roman", 20)) hm_label.grid(row=0, column=0) unit_modus = ttk.Combobox(self) unit_modus['values'] = ('Länge',) # 修正为元组,避免单个元素被解析为字符串 unit_modus['state'] = 'readonly' unit_modus.grid(row=0, column=1) # 绑定Combobox选择事件 unit_modus.bind("<<ComboboxSelected>>", lambda e: controller.show_frame(lange)) class lange(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) # 指定父容器为当前lange实例 gl_frame = tk.Frame(self) gl_frame.pack() of = tk.Frame(gl_frame) of.pack(side='left') pf = tk.Frame(gl_frame) pf.pack(side='left') rf = tk.Frame(gl_frame) rf.pack(side='right') qf = tk.Frame(gl_frame) qf.pack(side='right') ## Label Masseneinheit1 = tk.Label(of, text="Masseneinheit 1:").pack(side='top', anchor='nw') Masseneinheit2 = tk.Label(of, text="Masseneinheit 2:").pack(side='top', anchor='nw') ## Entry def validate_entry(text): if ( all(char in "0123456789.-" for char in text) and "-" not in text[1:] and text.count(".") <= 1): return True else: return False nz = tk.StringVar() ez = tk.Entry(pf, textvariable=nz, validate='key') ez['validatecommand'] = (ez.register(validate_entry), '%P') ez.pack(side='top') resl = tk.StringVar() res = tk.Label(pf, textvariable=resl) res.pack(side='top') ## Combobox enm = tk.StringVar() em = ttk.Combobox(qf, textvariable=enm) em['values'] = ('km', 'hm', 'dam', 'm', 'dm', 'cm', 'mm', 'in', 'ft', 'yd', 'mi') em['state'] = 'readonly' em.pack(side='top', anchor='ne') em.current() znm = tk.StringVar() zm = ttk.Combobox(qf, textvariable=znm) zm['values'] = ('mm', 'cm', 'dm', 'm', 'dam', 'hm', 'km', 'mi', 'yd', 'ft', 'in') zm['state'] = 'readonly' zm.pack(side='top', anchor='ne') zm.current() # 单位转换系数 km = 1000 hm = 100 dam = 10 m = 1 dm = 0.1 cm = 0.01 mm = 0.001 inch = 0.0254 ft = 0.3048 yd = 0.9144 mi = 1609.34 def conv(): # 获取转换系数 er = km if em.get() == "km" else hm if em.get() == "hm" else m if em.get()\ == "m" else dam if em.get() == "dam" else \ dm if em.get() == "dm" else cm if em.get() == "cm" else \ mm if em.get() == "mm" else inch if em.get() == "in" else \ ft if em.get() == "ft" else yd if em.get() == "yd" else \ mi zw = km if zm.get() == "km" else hm if zm.get() == "hm" else \ m if zm.get() == "m" else dam if zm.get() == "dam" else \ dm if zm.get() == "dm" else cm if zm.get() == "cm" else \ mm if zm.get() == "mm" else inch if zm.get() == "in" else \ ft if zm.get() == "ft" else yd if zm.get() == "yd" else \ mi # 检查输入是否为空,避免转换报错 if nz.get(): a = float(nz.get()) * er / zw resl.set(format(a, '.16f').rstrip('0').rstrip('.')) button = tk.Button(rf, text="Umrechnen!", command=conv) button.pack(side='top', anchor='ne') app = main() app.mainloop()
额外优化说明:
- 修正
unit_modus['values']为元组格式,避免单个元素被解析为字符串导致Combobox显示异常; - 在转换函数中增加输入为空判断,防止空值转换报错;
- 移除冗余的变量定义,简化代码结构。
内容的提问来源于stack exchange,提问作者Tomaten Rauschler
相关产品推荐
相关产品推荐

