【发布时间】:2021-04-16 12:40:16
【问题描述】:
我有一个使用登录窗口初始化的应用程序 - 一旦验证了用户和密码,它就会打开主菜单窗口(该窗口的代码如下)。以前,如果用户没有选择从主菜单注销以返回登录。但现在我插入了一个注销按钮,它应该杀死当前窗口打开以前的登录窗口。
问题是以前我不必保留登录窗口的状态,因为我从未计划返回那里,但现在我确实希望选择返回那里 - 所以我需要保留状态 - 因此我需要使用root.withdraw() 而不是root.destroy(),这似乎是我问题的根源(没有双关语)
如果我直接在我的 IDE 上执行 main_menu_window() 函数 - 它可以 100% 工作,但是如果我在下面的代码中从 LoginWindow(“父级”)调用它,我会收到如下详细信息的错误:
def main_menu_window(_parent, _user):
def open_user_man(event=None):
user_man_window(main_win)
main_menu_window(_user)
def open_prof_man(event=None):
prof_man_window(main_win, _user)
main_menu_window(_user)
def open_mon_leagues(event=None):
mon_leagues_window(main_win)
main_menu_window(_user)
def back_to_login():
main_win.destroy()
# if _parent is not None:
# _parent.deiconify()
# Hide Login Window
if _parent is not None:
_parent.withdraw()
# Window Setup
main_win = tk.Tk()
main_win.title("11Sixteen Database Management Controller - Main menu")
main_win.geometry("%dx%d+0+0" % (main_win.winfo_screenwidth(), main_win.winfo_screenheight()))
# Object setup
user_man = ImagedButtonWithText(main_win,
'C:\\Users\\rferreira\\GitHub\\11Sixteen\\DatabaseManagentController\\GlobalResources\\Images_Icons\\user_man_icon.png',
"LargeGroove", "User Management")
prof_man = ImagedButtonWithText(main_win,
'C:\\Users\\rferreira\\GitHub\\11Sixteen\\DatabaseManagentController\\GlobalResources\\Images_Icons\\profile_man_icon.png',
"LargeGroove", "Profile Management")
mon_leas = ImagedButtonWithText(main_win,
'C:\\Users\\rferreira\\GitHub\\11Sixteen\\DatabaseManagentController\\GlobalResources\\Images_Icons\\monitor_leagues_icon.png',
"LargeGroove", "Monitored Leagues")
back_to_mm_btn = ColourSchemedButton(main_win, "PaleGreen", "Logout", width=18)
# Object binding
user_man.btn.config(command=open_user_man)
prof_man.btn.config(command=open_prof_man)
mon_leas.btn.config(command=open_mon_leagues)
back_to_mm_btn.config(command=back_to_login)
# Object placement
back_to_mm_btn.grid(row=0, column=0, columnspan=2, padx=30, pady=20, sticky="nw")
user_man.frame.grid(row=1, column=0, padx=30, pady=20)
prof_man.frame.grid(row=1, column=1, padx=30, pady=20)
mon_leas.frame.grid(row=1, column=2, padx=30, pady=20)
main_win.mainloop()
if __name__ == "__main__":
user = User()
main_menu_window(None, user)
我得到的错误如下:
C:\Users\rferreira\AppData\Local\Programs\Python\Python39\python.exe C:/Users/rferreira/GitHub/11Sixteen/DatabaseManagentController/Login/LoginWindow.py
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\rferreira\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\Login\LoginWindow.py", line 19, in login_process
validate_login(login_win, email_entry, password_entry, message_label)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\Login\LoginValidation.py", line 54, in validate_login
login_attempt()
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\Login\LoginValidation.py", line 42, in login_attempt
MwW.main_menu_window(parent, user)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\MainMenu\MainMenuWindow.py", line 41, in main_menu_window
user_man = ImagedButtonWithText(main_win,
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\GlobalResources\GuiObjectsFactories.py", line 45, in __init__
self.btn = LargeGroove(self.frame, image=image)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\GlobalResources\GUIObjectsComponents.py", line 20, in __init__
super().__init__(master=parent, width=130, height=130, relief="groove", **kw)
File "C:\Users\rferreira\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2650, in __init__
Widget.__init__(self, master, 'button', cnf, kw)
File "C:\Users\rferreira\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2572, in __init__
self.tk.call(
_tkinter.TclError: image "pyimage4" doesn't exist
我希望能提供有关如何消除此错误的任何帮助或想法。如果您需要更多详细信息或进一步的代码提取,请告诉我。
为了更好的上下文,下面是对触发错误的对象的进一步代码提取
class ImagedButtonWithText(tk.Frame):
def __init__(self, parent, image_path, btn_type, text, **kw):
self.frame = tk.Frame(parent)
# Set up button
image = PhotoImageComp(image_path)
if btn_type == "MicroGroove":
self.btn = MicroGroove(self.frame, image=image)
if btn_type == "LargeGroove":
self.btn = LargeGroove(self.frame, image=image)
self.btn.image = image
self.btn.grid(row=0, column=0)
# Set up text
self.label = tk.Label(self.frame, text=text)
self.label.grid(row=1, column=0)
# --------------------- Buttons ---------------------------
class MicroGroove(tk.Button):
def __init__(self, parent, **kw):
super().__init__(master=parent, width=30, height=20, relief="groove", **kw)
class LargeGroove(tk.Button):
def __init__(self, parent, **kw):
super().__init__(master=parent, width=130, height=130, relief="groove", **kw)
【问题讨论】:
-
试试notebook 把东西放在后台,改变包含框架的可见性?
self.nb = ttk.Notebook(master) self.nb.add(page, state='hidden')其中page是您添加到笔记本的框架。 -
另外,不是直接调用框架中的对象,这是有问题的,正如您所指出的,当您删除它们时,您可以查找特定类型和名称的所有对象,然后关联它们具有特定的期望效果。
for i in page.winfo_children(): if i.winfo_class() == "Button": return i.get('value')再次,其中page是一个框架。 -
只是建议,但我上面的任何一个 cmets 都可以解决您遇到的问题。改变可见性而不是删除的问题在于它仍然存在于内存中,如果您正在创建一个复杂的 gui,这可能会很快陷入困境。第二种解决方案不是简单的物流问题。
-
将
image = PhotoImageComp(image_path)更改为image = PhotoImageComp(image_path, master=parent) -
@RubenFerreira 很好,我会在 1 小时内写出正确的答案。基本上是为了缩短它:tkinter 总是假设主窗口是第一个窗口