问题
I'm learning tkinter off of the Sentdex tutorials and I into a problem when trying to change pages. My compiler throws something about a KeyError that it doesn't give whenever I change the button on the start page to change to itself rather than PageOne:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Jason\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/Users/Jason/PycharmProjects/gui/main.py", line 43, in <lambda>
button1 = tk.Button(self, text="Visit Page 1",command=lambda: controller.show_frame(PageOne))
File "C:/Users/Jason/PycharmProjects/gui/main.py", line 29, in show_frame
frame = self.frames[cont]
KeyError: <class '__main__.PageOne'>
and my code:
import tkinter as tk
LARGE_FONT=("Verdana", 12)
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
frame = StartPage(container, self)
self.frames[StartPage] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def qf(param):
print(param)
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#command within button cant throw args to funcs. Use lambda to throw those args to the func instead
button1 = tk.Button(self, text="Visit Page 1",command=lambda: controller.show_frame(PageOne))
button1.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#command within button cant throw args to funcs. Use lambda to throw those args to the func instead
button1 = tk.Button(self, text="Visit Page 1",command=lambda: controller.show_frame(StartPage))
button1.pack()
app = SeaofBTCapp()
app.mainloop()
回答1:
Your button is calling show_frame(PageOne)
, but you never created an instance of PageOne
. So, of course, there is no key in self.frames
that matches that page.
Perhaps you intended to create an instance of PageOne
in your initial code?
def __init__(self, *args, **kwargs):
...
frame = PageOne(container, self)
self.frames[PageOne] = frame
...
If you don't want to create the page until you need it, you can add that code in show_frame
. First, you'll need to make container
an instance variable (ie: self.container
), then modify show_frame
to look something like this:
def show_frame(self, cont):
if cont not in self.frames:
self.frames[cont] = cont(self.container, self)
frame = self.frames[cont]
frame.tkraise()
回答2:
Your code contains several problems. The key code you have gotten caused by that you didn't mapped <class '__main__.PageOne'>
to something.
If you change your code like the following, you will have no more key errors.
# .....
frame = StartPage(container, self)
frame_ = PageOne(container, self)
self.frames[StartPage] = frame
self.frames[PageOne] = frame_
# ......
Here is the full code:
import tkinter as tk
LARGE_FONT=("Verdana", 12)
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
frame = StartPage(container, self)
frame_ = PageOne(container, self)
self.frames[StartPage] = frame
self.frames[PageOne] = frame_
frame.grid(row=0, column=0, sticky="nsew")
frame_.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def qf(param):
print(param)
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#command within button cant throw args to funcs. Use lambda to throw those args to the func instead
button1 = tk.Button(self, text="Visit Page 1",command=lambda: controller.show_frame(PageOne))
button1.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page One", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#command within button cant throw args to funcs. Use lambda to throw those args to the func instead
button1 = tk.Button(self, text="Start Page",command=lambda: controller.show_frame(StartPage))
button1.pack()
app = SeaofBTCapp()
app.mainloop()
来源:https://stackoverflow.com/questions/32705659/tkinter-throwing-a-keyerror-when-trying-to-change-frames