尝试更改帧时,Tkinter抛出KeyError

时间:2015-09-21 22:42:51

标签: python tkinter keyerror

我正在学习使用Sentdex教程的tkinter,并且在尝试更改页面时遇到问题。我的编译器会抛出一些关于KeyError的内容,每当我将起始页面上的按钮更改为自身而不是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'>

和我的代码:

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()

2 个答案:

答案 0 :(得分:1)

您的按钮正在调用show_frame(PageOne),但您从未创建过PageOne的实例。所以,当然,self.frames中没有与该页面匹配的键。

也许您打算在初始代码中创建PageOne的实例?

def __init__(self, *args, **kwargs):
    ...
    frame = PageOne(container, self)
    self.frames[PageOne] = frame
    ...

如果您不想在需要之前创建页面,可以在show_frame中添加该代码。首先,您需要将container设为实例变量(即:self.container),然后将show_frame修改为如下所示:

def show_frame(self, cont):
    if cont not in self.frames:
        self.frames[cont] = cont(self.container, self)
    frame = self.frames[cont]
    frame.tkraise()

答案 1 :(得分:0)

您的代码包含几个问题。您没有将<class '__main__.PageOne'>映射到某些内容而导致的密钥代码。

如果您更改以下代码,则不会再出现任何关键错误。

    # .....

    frame = StartPage(container, self)
    frame_ = PageOne(container, self)

    self.frames[StartPage] = frame
    self.frames[PageOne] = frame_

    # ......

以下是完整代码:

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()