Tkinter throwing a KeyError when trying to change frames

a 夏天 提交于 2019-12-14 03:26:43

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!