JGoundry
JGoundry

Reputation: 15

Tkinter destroying Toplevel and creating another error

When attempting to create a second Toplevel in Tkinter after closing the first I get the error:

_tkinter.TclError: bad window path name ".!toplevel

The error only occurs when the first Toplevel is closed, when I run the code without close_window() no error occurs and new_window works and creates the second Toplevel. I need to be able to close the first Toplevel and am not sure what is going wrong here so any help is much appreciated.

Here is a minimal reproducible example.

import tkinter as tk

class auto_haven:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.frame.place(relwidth=1, relheight=1)

        self.admin_login_button = tk.Button(self.frame, text="Admin Login", font=40, command=self.new_window)
        self.admin_login_button.place(relwidth=1, relheight=1)

    def new_window(self):
        self.newWindow = tk.Toplevel(self.master)
        self.app = admin_login(self.newWindow)

class admin_login:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.frame.place(relwidth=1, relheight=1)

        self.login_button = tk.Button(self.frame, text="Login", font=40, command=self.login)
        self.login_button.pack()

        self.back_button = tk.Button(self.frame, text="Exit", font=40, command=self.close_window)
        self.back_button.pack()

    def new_window(self):
        self.newWindow = tk.Toplevel(self.master)
        self.app = admin_panel(self.newWindow)

    def close_window(self):
        self.master.destroy()

    def login(self):
        self.close_window()
        self.new_window()

class admin_panel:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_window)
        self.quitButton.pack()
        self.frame.pack()
    def close_window(self):
        self.master.destroy()

def main():
    root = tk.Tk()
    app = auto_haven(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Upvotes: 1

Views: 82

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385900

When you call self.login, the first thing it does is call self.close_window(). When you do that, it calls self.master.destroy(). It then calls self.new_window() which calls self.newWindow = tk.Toplevel(self.master).

Notice that you are now trying to create a new window as a child of self.master, but you've destroyed self.master so tkinter will throw an error. When you create a new window, it needs to be the child of an existing window, such as the root window.

Upvotes: 2

Related Questions