【发布时间】:2023-01-29 23:57:29
【问题描述】:
我最初的方法基于以下示例:
Best way to structure a tkinter application?
我正在尝试创建一个更复杂的应用程序,涉及多个子应用程序,每个子应用程序都显示在一个单独的顶级窗口中。所有子应用程序都需要能够相互交换信息。因此,我打算在主应用程序中使用类变量来完成此要求。
此刻我被困在一点:
我不知道如何在创建子应用程序类实例后正确地销毁它。
“app_one”窗口可以打开一次,然后可以正常关闭。当然,如果窗口第二次打开,则会发生错误,因为只有“Toplevel”窗口实例被销毁,而子应用程序类实例本身没有被销毁。
如何在关闭“Toplevel”窗口时正确实现子应用程序类实例的销毁?
除此之外,我也非常感谢关于如何根据以下“Python”和“tkinter”最佳实践范例改进我的模板结构的任何其他建议:
import tkinter
import tkinter.filedialog
class main_app(tkinter.Tk):
root = None
var_one = None
sub_app_one_instance = None
sub_app_two_instance = None
sub_app_thr_instance = None
def __init__(self):
super().__init__()
main_app.root = self # <<< in order to be able to refer to root window in other classes
main_app.var_one = 99 # <<< class variables in order to exchange data between main app and sub apps
main_app.sub_app_one_instance = None
main_app.sub_app_two_instance = None
main_app.sub_app_thr_instance = None
self.create_tkinter_interface_main_app()
def create_tkinter_button(self, button_destination, button_text, button_width):
tkinter_button = tkinter.Button(button_destination, text=button_text, width=button_width)
return tkinter_button
def create_tkinter_label(self, label_destination, label_text):
tkinter_label = tkinter.Label(label_destination, text=label_text)
return tkinter_label
def create_tkinter_interface_main_app(self):
frame_main = tkinter.Frame(self)
frame_sub_one = tkinter.Frame(frame_main, bg="red")
frame_sub_two = tkinter.Frame(frame_main, bg="green")
frame_sub_thr = tkinter.Frame(frame_main, bg="blue")
label_app = self.create_tkinter_label(frame_main, "application")
label_one = self.create_tkinter_label(frame_sub_one, "menu one")
label_two = self.create_tkinter_label(frame_sub_two, "menu two")
label_thr = self.create_tkinter_label(frame_sub_thr, "menu thr")
button_one = self.create_tkinter_button(frame_sub_one, "app_one", 20)
button_one.configure(command=self.sub_app_one_open)
button_two = self.create_tkinter_button(frame_sub_one, "app_two", 20)
label_app.pack(side=tkinter.TOP, fill=tkinter.X, expand=tkinter.NO)
frame_sub_one.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=tkinter.YES)
frame_sub_two.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=tkinter.YES)
frame_sub_thr.pack(side=tkinter.LEFT, fill=tkinter.BOTH, expand=tkinter.YES)
label_one.pack(side=tkinter.TOP, fill=tkinter.NONE, expand=tkinter.NO, padx=10, pady=10)
button_one.pack(side=tkinter.TOP, fill=tkinter.NONE, expand=tkinter.NO, padx=10, pady=10)
button_two.pack(side=tkinter.TOP, fill=tkinter.NONE, expand=tkinter.NO, padx=10, pady=10)
label_two.pack(side=tkinter.TOP, fill=tkinter.NONE, expand=tkinter.NO, padx=10, pady=10)
label_thr.pack(side=tkinter.TOP, fill=tkinter.NONE, expand=tkinter.NO, padx=10, pady=10)
frame_main.pack(fill=tkinter.BOTH, expand=tkinter.TRUE)
def sub_app_one_open(self):
if not main_app.sub_app_one_instance == None:
main_app.sub_app_one_instance.sub_app_one_move_to_front()
return None
else:
main_app.sub_app_one_instance = sub_app_one()
class sub_app_one(main_app): # <<< inherit from main application in order to be able to access class variables
def __init__(self):
self.sub_app_one_toplevel_instance = tkinter.Toplevel(main_app.root)
self.sub_app_one_toplevel_instance.protocol("WM_DELETE_WINDOW", self.sub_app_one_close_toplevel)
print(main_app.var_one) # <<< access information from main app
def sub_app_one_move_to_front(self):
self.sub_app_one_toplevel_instance.attributes("-topmost", 0x01) # <<< set window state
self.sub_app_one_toplevel_instance.attributes("-topmost", 0x00) # <<< reset window state
def sub_app_one_close_toplevel(self):
self.sub_app_one_toplevel_instance.destroy()
self.sub_app_one_toplevel_instance = None
if __name__ == "__main__":
main_app_instance = main_app()
main_app_instance.mainloop()
【问题讨论】:
-
要隐藏
TopLevel,您可以使用toplevel.wm_withdraw()。要再次显示它,请使用toplevel.wm_deiconify()。当然,要使其正常工作,您还需要删除self.sub_app_one_toplevel_instance = None行。另一个提示:使一个类继承自另一个类并不能使其能够访问实例的变量;如果你想这样做,你应该给sub_app_main_one一个master参数,然后使用master.<var_name>作为你需要访问的任何main_app变量。另外,类名应该在CamelCase中,所以例如main_app变成了MainApp。 -
您好,感谢您的评论,但是如何在关闭 Toplevel 窗口时销毁类实例“sub_app_one”?
-
好吧,如果您将
sub_app_one实例设为sub_app_one_open()中的局部变量,一旦该函数被调用完毕,该变量就会被遗忘。您是否尝试删除sub_app_one_open()中的所有代码,并添加sub_app_one()行?这应该有效,以便忘记sub_app_one实例,并销毁窗口。另一种选择是编写您自己的自定义TopLevel类来代替sub_app_one。但我也很好奇为什么你想销毁sub_app_one实例吗?
标签: python python-3.x oop tkinter