I'm making a game in tkinter using classes to switch frames, however whenever I run it I get 2 extra windows one of which when destroyed gives this error:
Exception in Tkinter callback Traceback (most recent call last): File "D:\Thonny\lib\tkinter_init_.py", line 1921, in call return self.func(*args) File "D:\Thonny\lib\tkinter_init_.py", line 2342, in destroy Misc.destroy(self) File "D:\Thonny\lib\tkinter_init_.py", line 665, in destroy self.tk.deletecommand(name) _tkinter.TclError: can't delete Tcl command
I think it may be due to calling Tk() and also something to do with super() and init but i dont really know what they do My code:
import tkinter as tk
from tkinter import *
from tkinter import ttk,font
from tkinter.messagebox import showinfo
from tkinter import messagebox
import shelve
from PIL import ImageTk,Image #I know there are some that are probably unnescesary but
#it works so i dont waant to touch it T.T
Game=Tk()
class Game(tk.Tk):
def __init__(self):
global background
tk.Tk.__init__(self)
super().__init__()
self.geometry('992x558')
background=ImageTk.PhotoImage(Image.open('background.png'),master=self)
backgroundlabel= Label(self,image=background).place(x=0,y=0)
self.iconbitmap('icon.ico')
self._frame = None
self.switchframe(npcheck)
def switchframe(self, frameclass):
newframe = frameclass(self)
print(frameclass(self))
if self._frame is not None:
self._frame.destroy() # destroy old frame
self._frame = newframe #set new frmae
self._frame.grid() ##draw new frame
class npcheck(tk.Frame): #new player check
def __init__(self, master):
tk.Frame.__init__(self, master)
#tk.Frame.__init__(self, master,image=background)
backgroundlabel= Label(self,image=background).place(x=0,y=0)
q=Label(self, text= 'New or existing player?')
q.grid(row=0,column=1,sticky=W+E,padx=50,pady=50)
gobutton= Button(self,text='New Player.', command=lambda: master.switchframe(accountcreation))
gobutton.grid(row=1,column=0,sticky=W,padx=50,pady=50)
gobutton= Button(self,text='Existing Account.', command=lambda: master.switchframe(login))
gobutton.grid(row=1,column=2,sticky=E,padx=50,pady=50)
if __name__ == "__main__":
game = Game()
game.mainloop()
I tried removing the Game=Tk() and fiddling with it a bit however this only broke it more T.T
You're getting extra windows because you're inadvertently instantiating Tk
multiple times (in a few places throughout the code). Note that I've commented out or otherwise disabled the background image stuff, since I don't have those files on hand.
I've added some notes (as comments) regarding convention / style, but this should work as written.
import tkinter as tk
from tkinter import ttk, font
from tkinter.messagebox import showinfo
# you're already importing something from messagebox above; if you need other
# methods from that module, just add them there
# from tkinter import messagebox
import shelve
from PIL import ImageTk, Image
# from tkinter import * # it's best to avoid star imports. Instead, just access
# tk widgets like this: tk.Label, tk.Button, etc.
# Game=Tk() # this is creating a window, but your Game class already
# inherits from tk.Tk, so you don't need to instantiate it here
class Game(tk.Tk):
def __init__(self) -> None:
# tk.Tk.__init__(self) # you don't need this *and* super(), just use one - also, using both is creating yet another window!
super().__init__()
self.geometry('992x558')
# background=ImageTk.PhotoImage(Image.open('background.png'),master=self)
backgroundlabel=tk.Label(self,image=None).place(x=0,y=0)
# self.iconbitmap('icon.ico')
self._frame = None
self.switchframe(npcheck)
def switchframe(self, frameclass):
newframe = frameclass(self)
print(frameclass(self))
if self._frame is not None:
self._frame.destroy() # destroy old frame
self._frame = newframe #set new frmae
self._frame.grid() ##draw new frame
class npcheck(tk.Frame): # this should be capitalized, e.g. NpcCheck #new player check
def __init__(self, master):
tk.Frame.__init__(self, master) # you can use super() here too!
# super().__init__(master) # like this
#tk.Frame.__init__(self, master,image=background)
backgroundlabel= tk.Label(self,image=None).place(x=0,y=0)
q=tk.Label(self, text= 'New or existing player?')
q.grid(row=0,column=1,sticky='ew',padx=50,pady=50)
gobutton= tk.Button(self,text='New Player.', command=lambda: master.switchframe(accountcreation))
gobutton.grid(row=1,column=0,sticky='w',padx=50,pady=50)
gobutton= tk.Button(self,text='Existing Account.', command=lambda: master.switchframe(login))
gobutton.grid(row=1,column=2,sticky='e',padx=50,pady=50)
if __name__ == "__main__":
game = Game()
game.mainloop()
I'd recommend taking a sec to look over the PEP8 style guide, and reading up on what super() does!