Tkinter多页面框架中读取控制器类共享变量为空是什么原因?
问题根因
- 所有页面实例是在
AppMain初始化阶段就批量创建完成的,PageOne的__init__方法会在程序启动时立刻执行,此时你还没有上传解析XML,shared_data['tc']就是初始化的空列表,你看到的空打印是程序启动时的输出,不是跳转页面时的输出。 - 你后续上传文件修改
shared_data后调用show_frame切换页面,只是把已经创建好的PageOne实例放到顶层显示,不会重新执行__init__方法,自然不会读取到最新的共享变量值。 - 额外注意:你当前代码中解析XML时只传了文件名,若选择的XML文件不在当前工作目录下会触发
FileNotFoundError,建议直接使用选择的完整路径。
修复方案
- 把
PageOne中读取共享变量的逻辑从__init__中拆分出来,做成独立的刷新方法 - 修改
AppMain的show_frame方法,切换到对应页面时主动调用刷新方法,读取最新的共享变量 - 修复XML路径读取的错误
修改后可运行代码
import os, easygui import xml.etree.ElementTree as ET import tkinter as tk LARGE_FONT = ("Verdana", 12) class PageOne(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller # 新增刷新方法,每次切换到该页面时调用 def update_view(self): print("Second TC:", self.controller.shared_data['tc']) for i in self.controller.shared_data['tc']: print("****: ", i) print("Name:", i['Name'], "Id:", i['Id']) class StartPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller label = tk.Label(self, text='File Upload: Press the button to open the XML file.', font=LARGE_FONT) label.place(relx=.01, rely=.01) # Function to separate the tc "Child_4" inside the xml file def separate_tc(xml_name): file_xml = ET.parse(xml_name) # Get the name and id attributes that the Child_4 tag contains self.controller.shared_data['tc'] = [ {"Name": signal.attrib["Name"], "Id": signal.attrib["Id"], } for signal in file_xml.findall(".//Child_4") ] print('First TC:', self.controller.shared_data['tc']) controller.show_frame("PageOne") # Function to open xml file def open_file(): try: xml_name = easygui.fileopenbox(title='Select XML file', default='*.xml') if not xml_name: # 处理用户点击取消的情况 return separate_tc(xml_name) # 直接传完整路径,不需要转basename except FileNotFoundError: print('XML file was not loaded.') button_open = tk.Button(self, text="Open File XML", command=open_file) button_open.place(relx=.01, rely=.05) class AppMain(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) tk.Tk.wm_title(self, 'Analysis of a XML') self.shared_data = {'tc': []} 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 (StartPage, PageOne): page_name = F.__name__ frame = F(parent=container, controller=self) self.frames[page_name] = frame frame.grid(row=0, column=0, sticky="nsew") self.show_frame("StartPage") def show_frame(self, page_name): '''Show a frame for the given page name''' frame = self.frames[page_name] # 新增逻辑:如果页面有update_view方法就调用,刷新最新数据 if hasattr(frame, 'update_view'): frame.update_view() frame.tkraise() if __name__ == "__main__": app = AppMain(None) app.title('Analysis of XML') app.geometry("1024x920") app.mainloop()
内容的提问来源于stack exchange,提问作者MayEncoding
相关产品推荐
相关产品推荐

