首页 > 解决方案 > Tkinter - 撤回前一个窗口而不是破坏它导致当前窗口出现问题

问题描述

我有一个使用登录窗口初始化的应用程序 - 一旦验证了用户和密码,它就会打开主菜单窗口(该窗口的代码如下)。以前,如果用户没有选择从主菜单注销以返回登录。但现在我插入了一个注销按钮,它应该杀死当前窗口打开以前的登录窗口。

问题是以前我不必保留登录窗口的状态,因为我从未计划返回那里,但现在我确实希望选择返回那里 - 所以我需要保留状态 - 因此我需要与之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)

标签: pythontkinter

解决方案


Tkinter 从不强迫你传递主参数。你通常这样做:

self.label = tk.Label(self.frame, text=text)

self.frame是标签的主人。同样,您应该在创建PhotoImages 时传入 master 参数,如下所示:

image = PhotoImage(image_path, master=parent)

仅当您有超过 1 个Tk()实例时才需要这样做,但我建议始终通过它。

如果你不把它传入,tkinter 会假设 master 是Tk()你创建的第一个实例。这是一个问题,因为 的不同实例Tk()(大多数情况下)不能相互交谈,因此PhotoImage根据 . 的第二个实例实际上并不存在Tk()


推荐阅读