使用实例方法无法更新Tkinter Frame或Label的问题求助
我在Tkinter GUI开发中遇到了内容更新失效的问题,已搜索两天但未找到完全匹配的解决方案。有一篇标题为《Tkinter updating labels in stacked frame windows》的帖子与我的问题接近,但并不完全一致。
我采用类结构搭建应用,主窗口包含ttk.Notebook组件,下分三个标签页:Add New Product、List All Product、Edit Product。其中Edit Product标签页内嵌套了EditProductFrame,这个Frame内部通过堆叠方式管理DetailFrame和EditFrame两个子Frame,使用tkraise()切换显示。
我尝试从ListProduct标签页的按钮触发修改DetailFrame的内容,代码能正常执行,打印值也显示已修改,但界面上的Label文本和Frame背景完全没更新。试过config方法和StringVar都无效。
示例代码
主窗口代码
import tkinter as tk from tkinter import ttk class ProductWindow(tk.Tk): def __init__(self): tk.Tk.__init__(self) self.geometry("600x500") 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.notebook = ttk.Notebook(container) self.notebook.grid(row=0, column=0, sticky='nsew') self.new_product_tab = tk.Frame(self.notebook, bg='#233223' ) self.list_product_tab = tk.Frame(self.notebook, bg='#323232') self.edit_product_tab = tk.Frame(self.notebook, bg='#433434') # 添加标签页 self.notebook.add(self.new_product_tab, text=" Add New Product ") self.notebook.add(self.list_product_tab, text=" List All Product ") self.notebook.add(self.edit_product_tab, text=" Edit Product ") self.productframe = EditProductFrame(self.edit_product_tab) self.detailframe = DetailFrame(self.productframe) # 问题根源:额外创建了一个未显示的实例 button = tk.Button(self.list_product_tab, text="Change background in Edit Form", command=self.change_method) button.pack() def change_method(self): print("Trying to change the frame") self.productframe.raise_edit_frame(DetailFrame) self.detailframe.change_bg('green') # 修改的是未显示的实例 self.notebook.select(self.edit_product_tab) if __name__ == "__main__": testObj = ProductWindow() testObj.mainloop()
DetailFrame所在文件代码
import tkinter as tk class EditProductFrame(tk.Frame): def __init__(self, parent): print("Edit product frame constructor is called...") tk.Frame.__init__(self, parent) self.pack(side='top', fill='both', expand=True) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(0, weight=1) # 存储堆叠的Frame实例 self.frames = {} for F in {DetailFrame, EditFrame}: frame = F(self) self.frames[F] = frame frame.grid(row=0, column=0, sticky='nsew') self.raise_edit_frame(DetailFrame) def raise_edit_frame(self, container): frame = self.frames[container] frame.tkraise() class EditFrame(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent) self.config(bg='green') label = tk.Label(self, text="Edit Page",) label.pack(pady=0,padx=0) tk.Button(self, text="Go to Detail", command=lambda:parent.raise_edit_frame(DetailFrame)).pack() class DetailFrame(tk.Frame): def __init__(self, parent): print("something detail view") tk.Frame.__init__(self, parent) self.config(bg='blue') self.label = tk.Label(self, text='Original Label') self.label.pack(pady=0,padx=0) tk.Button(self, text="Go to Edit Frame", command=lambda:parent.raise_edit_frame(EditFrame)).pack() def change_bg(self, color): self.config(bg=color) self.label.config(text='Changed Label') print(self.label.cget('text')) # 打印正确,但界面不更新
问题根源
主窗口中额外创建了一个DetailFrame实例(self.detailframe = DetailFrame(self.productframe)),但界面上实际显示的是EditProductFrame内部通过循环创建并存储在frames字典里的那个实例。你调用self.detailframe.change_bg()修改的是未显示的实例,所以界面完全没反应。
解决方案
删除主窗口中额外创建的DetailFrame实例,直接从EditProductFrame的frames字典中获取界面正在使用的实例进行修改:
修改主窗口代码:
- 移除
self.detailframe = DetailFrame(self.productframe)这一行 - 修改
change_method方法:
def change_method(self): print("Trying to change the frame") # 从EditProductFrame的frames字典中获取正在使用的DetailFrame实例 target_frame = self.productframe.frames[DetailFrame] self.productframe.raise_edit_frame(DetailFrame) target_frame.change_bg('green') self.notebook.select(self.edit_product_tab)
这样修改后,调用的就是界面上显示的DetailFrame实例,修改操作会同步更新到界面上。
内容的提问来源于stack exchange,提问作者alirehman

