I get an error: bad window path name ".!frame" when i press a button in the following code? I get an error: bad window path name ".!frame" when i press a button in the following code? tkinter tkinter

I get an error: bad window path name ".!frame" when i press a button in the following code?


The first thing you do in main_screen is to destroy other_frame. When you call second_screen, it tries to use that frame as the parent for new widgets but it has been destroyed. That is why you get the error bad window path name ".!frame" - it is bad because it has been destroyed and can no longer be used.

A simple solution is to simply not call other_frame.destroy(). Instead, you can remove it from view with other_frame.pack_forget().

It's important to know that pack works by placing objects in available space, and in the order that pack was called. If you remove and add widgets once the app has started, that may affect the order in which the widgets appear.

In this specific case, since main_screen and other_screen are the only widgets directly in root it doesn't matter, and doesn't affect the reason why you got the error you got.


The problem is you delete the frame other_frame before when you write other_frame.destroy(). This makes it inaccessible by the rest of the program since you destroyed it.

So there would be two solutions: One would be to, as BryanOakley mentioned, to use .pack(). The other would be to use .place().

Code for .pack():

from tkinter import *root = Tk()my_height = 600my_width = 350root.geometry(f"{my_height}x{my_width}")# root.maxsize(my_height, my_width)def main_screen():    other_frame.pack_forget()    main_frame.pack()def second_screen():    main_frame.pack_forget()    other_frame.pack()# FRAMESmain_frame = Frame(root, bg="Red", borderwidth=30)other_frame = Frame(root, bg="Yellow", borderwidth=30)Label(other_frame, text="Second Window").pack()Button(other_frame, text="BACK", command=main_screen).pack()Label(main_frame, text="First Window").pack()Button(main_frame, text="GO", command=second_screen).pack()# first windowmain_screen()root.mainloop()

Code for .place():

from tkinter import *root = Tk()my_height = 600my_width = 350root.geometry(f"{my_height}x{my_width}")# root.maxsize(my_height, my_width)# first windowdef main_screen():    main_frame.place(relx = 0.5, rely = 0.1, anchor = "center")    other_frame.place(relx = 1.5, rely = 0.1, anchor = "center")    main_frame.update()    other_frame.update()def second_screen():    main_frame.place(relx = -0.5, rely = 0.1, anchor = "center")    main_frame.update()    other_frame.place(relx = 0.5, rely = 0.1, anchor = "center")    other_frame.update()# FRAMESmain_frame = Frame(root, bg="Red", borderwidth=30)other_frame = Frame(root, bg="Yellow", borderwidth=30)main_frame.place(relx = 0.5, rely = 0.1, anchor = "center")other_frame.place(relx = 1.5, rely = 0.1, anchor = "center")Label(main_frame, text="First Window").pack()Button(main_frame, text="GO", command=second_screen).pack()Label(other_frame, text="Second Window").pack()Button(other_frame, text="BACK", command=main_screen).pack()main_screen()root.mainloop()

The advantage of using .place() is you can animate the frame back and forth using a for loop.

Here is the code for that:

from tkinter import *root = Tk()my_height = 600my_width = 350root.geometry(f"{my_height}x{my_width}")# root.maxsize(my_height, my_width)# first windowdef main_screen():    global x1, y1, x2, y2    for i in range(1000):        x1 += 0.001        x2 += 0.001        main_frame.place(relx = x1, rely = y1, anchor = "center")        other_frame.place(relx = x2, rely = y2, anchor = "center")        main_frame.update()        other_frame.update()            def second_screen():    global x1, y1, x2, y2    for i in range(1000):        x1 -= 0.001        x2 -= 0.001        main_frame.place(relx = x1, rely = y1, anchor = "center")        other_frame.place(relx = x2, rely = y2, anchor = "center")        main_frame.update()        other_frame.update()    # FRAMESx1, y1 = 0.5, 0.1x2, y2 = 1.5, y1main_frame = Frame(root, bg="Red", borderwidth=30)other_frame = Frame(root, bg="Yellow", borderwidth=30)main_frame.place(relx = 0.5, rely = 0.1, anchor = "center")other_frame.place(relx = 1.5, rely = 0.1, anchor = "center")Label(main_frame, text="First Window").pack()Button(main_frame, text="GO", command=second_screen).pack()Label(other_frame, text="Second Window").pack()Button(other_frame, text="BACK", command=main_screen).pack()root.mainloop()

Hope this helps!


Set a fixed position on the frames and stack them on top of each other every time they are needed.