如何在使用函数时不借助全局变量实现tkinter widgets的移除
无全局变量的Tkinter多界面切换实现方案
你遇到的警告是因为全局变量仅在函数内部赋值,模块顶层没有预先定义,下面两种方案可完全规避全局变量,同时方便后续扩展界面切换逻辑:
方案1:面向对象封装(最推荐,可维护性最高)
把所有界面逻辑封装为自定义类,组件和状态都作为实例属性存储,是Tkinter开发的标准实践,后续加第二组组件、返回逻辑的扩展成本极低:
from tkinter import * class App: def __init__(self, root): self.win = root self.win.geometry("1270x725+0+0") # 可分别存储多组界面的组件 self.first_page_widgets = {} self.second_page_widgets = {} # 初始化页面 self.init_first_page() self.init_switch_button() def something_happens(self, e1, e2, e3): print('something is supposed to happen when an option is pressed but that\'s not important') def init_first_page(self): category_names = ['all', 'electrical', 'mechanical', 'optics'] self.first_page_widgets['category_variable'] = StringVar(self.win) self.first_page_widgets['category_variable'].set(category_names[0]) self.first_page_widgets['category_menu'] = OptionMenu( self.win, self.first_page_widgets['category_variable'], *category_names ) self.first_page_widgets['category_menu'].config( width=10, font=('Arial', 20), highlightthickness=0 ) self.first_page_widgets['category_menu'].place(relx=.45, rely=.3) self.first_page_widgets['category_variable'].trace('w', self.something_happens) def switch_to_second_page(self): # 隐藏第一页所有组件 for widget in self.first_page_widgets.values(): if isinstance(widget, Widget): widget.place(relx=2) # 这里可以加第二页组件的初始化/显示逻辑 # if not self.second_page_widgets: # self.init_second_page() # for widget in self.second_page_widgets.values(): # if isinstance(widget, Widget): # widget.place(xxx) def init_switch_button(self): button = Button( self.win, text='this is suppose to get rid of the option menu widget', font=('Arial', 20), command=self.switch_to_second_page ) button.place(relx=.2, rely=.5) if __name__ == "__main__": win = Tk() app = App(win) win.mainloop()
方案2:轻量改造(小项目低改动选择)
如果不想重构为类结构,可以通过函数返回值存储组件,用lambda给回调传参,改动量极小:
from tkinter import * win = Tk() win.geometry("1270x725+0+0") def something_happens(e1, e2, e3): print('something is supposed to happen when an option is pressed but that\'s not important') def category_option_menu(): category_names = ['all', 'electrical', 'mechanical', 'optics'] category_variable = StringVar(win) category_variable.set(category_names[0]) category_drop_down_menu = OptionMenu(win, category_variable, *category_names) category_drop_down_menu.config(width=10, font=('Arial', 20), highlightthickness=0) category_drop_down_menu.place(relx=.45, rely=.3) category_variable.trace('w', something_happens) # 返回创建的组件给外部存储 return category_drop_down_menu, category_variable def hide_widget(widget): widget.place(relx=2) # 组件存在局部变量中,无需全局变量 category_menu, category_var = category_option_menu() button = Button( win, text='this is suppose to get rid of the option menu widget', font=('Arial', 20), command=lambda: hide_widget(category_menu) ) button.place(relx=.2, rely=.5) win.mainloop()
补充说明
你当前用place(relx=2)隐藏组件的方案很适合频繁切换的场景,要恢复第一页组件时,只需要重新调用对应组件的place()方法设置回原坐标即可,不需要销毁重建,性能更好。
内容的提问来源于stack exchange,提问作者neo_codex
相关产品推荐
相关产品推荐

