Python KeyError:

Python KeyError:,python,class,oop,tkinter,tk,Python,Class,Oop,Tkinter,Tk,下面的代码显示了一个包含一系列页面的化学测验应用程序,用户可以在这些页面之间切换 class STARTPAGE(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) Instructions1 = tk.Label(self, text=("You will obtain a Desired Product that is chosen ran

下面的代码显示了一个包含一系列页面的化学测验应用程序,用户可以在这些页面之间切换

class STARTPAGE(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        Instructions1 = tk.Label(self, text=("You will obtain a Desired Product that is chosen randomly from a Starting Reactant."))                                                      
        Instructions2 = tk.Label(self, text=("You get 3 Attempts to complete the question in which Points will be added to your score "))
        Instructions3 = tk.Label(self, text=("After 3 attempts you will be moved onto next stage or question"))
        Instructions4 = tk.Label(self, text=("You need to select one Reagent and 1 or 2 Conditions to complete stage"))
        Instructions5 = tk.Label(self, text=("Your score will be ranked among others in your same class in a leaderboard"))

        Instructions1.grid(row=0, column=0)
        Instructions2.grid(row=1, column=0)
        Instructions3.grid(row=2, column=0)
        Instructions4.grid(row=3, column=0)
        Instructions5.grid(row=4, column=0)

        StartQuiz = tk.Button(self, text="Start Quiz", command=lambda: controller.show_frame(STAGE1))
        StartQuiz.grid(row=8, column=1)

class STAGE1(tk.Frame):
     def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        Stage1 = tk.Label(self, text="STAGE 1")
        Stage1.grid(column=1, row=0)          
        #Explain the Main class and tk frame constructor in each class from stack overflow         
        self.ButtonData = BUTTONDATA(self, tk.Frame)  

        self.ButtonData.ReagentOption1.config(command=lambda: self.AllocatePointsStage(1))
        self.ButtonData.ReagentOption2.config(command=lambda: self.AllocatePointsStage(1))
        self.ButtonData.ReagentOption3.config(command=lambda: self.AllocatePointsStage(1))
        self.ButtonData.ReagentOption4.config(command=lambda: self.AllocatePointsStage(1))

        self.ButtonData.ConditionOption1.config(command=lambda: self.AllocatePointsStage(1))
        self.ButtonData.ConditionOption2.config(command=lambda: self.AllocatePointsStage(1))
        self.ButtonData.ConditionOption3.config(command=lambda: self.AllocatePointsStage(1))
        self.ButtonData.ConditionOption4.config(command=lambda: self.AllocatePointsStage(1))

        self.ButtonData.ReagentOption1.grid(column=2, row=5)
        self.ButtonData.ReagentOption2.grid(column=2, row=6)
        self.ButtonData.ReagentOption3.grid(column=2, row=7)
        self.ButtonData.ReagentOption4.grid(column=2, row=8) 

        self.ButtonData.ConditionOption1.grid(column=10, row=5)
        self.ButtonData.ConditionOption2.grid(column=10, row=6)
        self.ButtonData.ConditionOption3.grid(column=10, row=7)   
        self.ButtonData.ConditionOption4.grid(column=10, row=8)

        self.Continue = tk.Button(self, text="Continue", command=lambda: controller.show_frame(Stage2))
        self.Continue.grid(column=6)

        self.QuestionStarter = QUESTIONSTARTER(self, tk.Frame)
        self.QuestionStarter.PointsLabel.grid(row=0, column=6)
        self.QuestionStarter.AttemptsDisplayed.grid(row=1, column=7)
        self.QuestionStarter.WordedQuestion.grid(row=0, column=1)
        self.QuestionStarter.AttemptsDisplayedText.grid(row=1, column=8)
        DesiredProductLabel = tk.Label(self, command=lambda: ShowDesiredProduct(DesiredProduct))
        DesiredProductLabel.grid(row=5, column=0)

     def ShowDesiredProduct(self, DesiredProduct):
        DesiredProduct = GetDesiredProduct()
        return DesiredProduct

class Main(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "Chemistry Quiz")
        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 = {}

        for F in (STUDENTLOGINPAGE, STAFFLOGINPAGE, STARTPAGE, ASSIGNMENTPAGE, STAGE1, STAGE2, STAGE3, STAGE4, STAGE5, LEADERBOARDPAGE):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

            self.show_frame(STUDENTLOGINPAGE)
            if self.frames == []:
                print ("Error in loading program")
            #This class inherits from Tk class within module of Tk Inter
            #This basically displays each page in turn from the List

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise() 

    def get_page(self, page_class):
        return self.frames[page_class]
由于某些原因,我得到以下错误,它发生在我的第1阶段的show框架中:

Error -Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1549, in __call__
    return self.func(*args)
  File "/Users/ammarhusain/Desktop/Computing Project/Ammar Chemistry Program FINAL.py", line 316, in <lambda>
    StartQuiz = tk.Button(self, text = "Start Quiz", command=lambda: controller.show_frame(STAGE1))
  File "/Users/ammarhusain/Desktop/Computing Project/Ammar Chemistry Program FINAL.py", line 3152, in show_frame
    frame = self.frames[cont]
KeyError: <class '__main__.STAGE1'>

这里的问题是您将类定义用作键:

# add the frame
self.frames[F] = frame
# show the frame
self.show_frame(STUDENTLOGINPAGE)
我建议您使用字符串作为字典中的键,并将这些行移出循环:

self.show_frame(STUDENTLOGINPAGE)
现在回到stacktrace,这里有一行:

controller.show_frame(STAGE1)
因此,控制器在按钮被点击时不包含STAGE1屏幕。如果在创建所有屏幕后显示StudentLogin页面,则问题应消失:

# create all the screens
for F in (STUDENTLOGINPAGE, STAFFLOGINPAGE, STARTPAGE, ASSIGNMENTPAGE, STAGE1, STAGE2, STAGE3, STAGE4, STAGE5, LEADERBOARDPAGE):
    frame = F(container, self)
    self.frames[F] = frame
    frame.grid(row=0, column=0, sticky="nsew")

# check the sreens availability
if self.frames == []:
    print ("Error in loading program")

# now show the login form
self.show_frame(STUDENTLOGINPAGE)

什么是STUDENTLOGINPAGE?这是另一个类,是用于学生登录的页面。由于空格@VMATM,我无法将其放置。调试KeyError的第一步是在抛出错误的代码之前立即从字典中打印出密钥,以验证您认为字典中的密钥是否确实在字典中。您还应该验证cont是否包含您认为它包含的内容。哦,好的,我如何测试代码中cont中是否有内容@BRYANOAKLEY您可以使用打印语句:printcontHi感谢您的帮助,但我仍然不明白您所说的“将密钥放入字符串并在所有屏幕后显示STUDENTLOGINPAGE@VMAtm”是什么意思。我还可以就我的程序中的其他问题与您联系吗,这将是令人惊讶的!!关于字符串-这只是一个建议,因为将字典键作为类来使用不是一个好的可读性实践。关于STUDENTLOGINPAGE-在创建所有屏幕之前,在循环中显示它:self.show\u frameSTUDENTLOGINPAGE。将其从中移出。我已经更新了答案。啊,好吧,我明白了,但是当我现在运行我的程序时,它会首先显示作业页面而不是学生登录页面?当我使用控制器从assignmentpage移动到stage 1时,它会带来相同的错误。我可以就此与您联系吗?在阶段1之前创建@VMAtmASSIGNMENTPAGE将非常有用。看看这个错误。上面说字典找不到舞台。发生这种情况是因为您仍然没有创建它,也没有将它添加到字典中。创建所有表单,只在显示任何表单之后。但是我已经创建了类Stage 1,并且我也将这个类放入了for循环中?