Python tkinter "KeyError: <class __main__." error

108 阅读2分钟

我在使用 Python tkinter 创建了一个程序,它可以正常运行。

  • 但是,当我添加一个新的类 HelpPage 时,程序开始抛出 KeyError 异常,错误信息为 "KeyError: <class __main__."
  • 我尝试删除 HelpPage 类,但仍然会出现同样的错误,错误信息变为 "KeyError: "main.PageTwo"
  • 我尝试了很多方法,但无法让程序正常运行。

解决方案

  • 仔细检查代码后,发现问题出在 StartPage 类中的 button1 按钮的 command 属性。
  • command 属性的值是一个 lambda 表达式,它会在按钮被按下时调用 controller.show_frame(HelpPage) 函数。
  • 但是,在 StartPage 类中,button1 按钮的 command 属性的值是 controller.show_frame(HelpPage),这会导致函数在按钮被按下之前就被调用,从而抛出 KeyError 异常。
  • command 属性的值改为 lambda: controller.show_frame(HelpPage) 可以解决这个问题,因为这样函数只会在按钮被按下时才被调用。

修改后的代码如下:

class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Image Overlap Program V 1.0")
        label.pack(pady=10, padx=10)

        # 修改此处
        button1 = tk.Button(self, text="Help", command=lambda: controller.show_frame(HelpPage))
        button1.pack()

        button2 = tk.Button(self, text="Select Folder", command=lambda: controller.selectfolder())
        button2.pack()

代码例子

import Tkinter as tk
import tkFileDialog
import os

class Application(tk.Tk):

    PixSize=0
    cnt=1
    height=0
    width=0
    NumPixX=0
    NumPixY=0
    NumImages=0
    file='none'

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={}

    for F in (StartPage,PageOne,PageTwo,PageThree,FinalPage,HelpPage):
        frame = F(container,self)
        self.frames[F]= frame
        frame.grid(row=0,column=0,sticky="nsew")

    self.show_frame(StartPage)

def selectfolder(self):
    folder=tkFileDialog.asksaveasfile()
    self.file=folder
    self.show_frame(PageOne)

def show_frame(self,controller):

    frame=self.frames[controller]
    frame.tkraise()

def rescalc(self,argCamDist,argSenWidth,argFocLen,argNumPix,cont):
    HFOV = float(argCamDist.get())*(float(argSenWidth.get())/float(argFocLen.get()))
    self.PixSize = float(argNumPix.get())/HFOV
    cont.show_frame(PageThree)

def GetNumbers(self,argNumImages,argNumPixX,argNumPixY,cont):
    self.NumPixX=int(argNumPixX.get())
    self.NumPixY=int(argNumPixY.get())
    self.NumImages=int(argNumImages.get())
    cont.file.write(str(self.NumImages))
    cont.show_frame(PageTwo)

def ClipCalculator(self,argLabel,argtop,argleft,argbottom,argright,argNumPixX,argNumPixY,argNumImages,argLabel3,argLabel4,cont):

    upper=int(self.PixSize*float(argtop.get()))+1
    left=int(self.PixSize*float(argleft.get()))+1
    if cont.cnt==1:
        bottom=int(argNumPixY)-(int(self.PixSize*float(argbottom.get()))+1)
        right=int(argNumPixX)-(int(self.PixSize*float(argright.get()))+1)
        cont.width=right-left
        cont.height=upper-bottom
    else:
        bottom=upper+cont.height
        right=left+cont.width    
    cont.file.write('upper left: rows:{0}:columns:{1} \n'.format(upper,left))
    cont.file.write('upper right: rows:{0}:columns:{1} \n'.format(upper,right))
    cont.file.write('lower left: rows:{0}:columns:{1} \n'.format(bottom,left))
    cont.file.write('lower right: rows:{0}:columns:{1} \n'.format(bottom,right))
    cont.cnt+=1
    argLabel['text']="Image Number {0}".format(cont.cnt)
    argtop.delete(0,tk.END)
    argtop.insert(0,"0.0")
    argleft.delete(0,tk.END)
    argleft.insert(0,"0.0")
    argbottom.delete(0,tk.END)
    argbottom.insert(0,"0.0")
    argright.delete(0,tk.END)
    argright.insert(0,"0.0")
    cont.refresh(argbottom,argright,argLabel3,argLabel4,cont)

def refresh(self,Label3,Label4,entry3,entry4,cont):
    if cont.cnt==1:
        cont.show_frame(PageTwo)
    if (cont.cnt > 1 and cont.cnt <= cont.NumImages):
        Label3.forget()
        Label4.forget()
        entry3.forget()
        entry4.forget()
        cont.show_frame(PageTwo)
    else:
        cont.file.close()
        cont.show_frame(FinalPage)
class StartPage(tk.Frame):
def __init__(self,parent,controller):
    tk.Frame.__init__(self,parent)
    label=tk.Label(self,text="Image Overlap Program V 1.0")
    label.pack(pady=10,padx=10)

    # 修改处
    button1 = tk.Button(self, text="Help", command=lambda: controller.show_frame(HelpPage))
    button1.pack()

    button2 = tk.Button(self, text="Select Folder", command=lambda: controller.selectfolder())
    button2.pack()

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


    label3=tk.Label(self,text="Camera Parameters")
    label3.pack(pady=10,padx=10)

    label1=tk.Label(self,text="Camera Distance").pack()
    entry1=tk.Entry(self)
    entry1.insert(0,"0.0")
    entry1.pack()

    label2=tk.Label(self,text="Sensor Width").pack()
    entry2=tk.Entry(self)
    entry2.insert(0,"0.0")
    entry2.pack()

    label3=tk.Label(self,text="Focal Length").pack()
    entry3=tk.Entry(self)
    entry3.insert(0,"0.0")
    entry3.pack()

    label4=tk.Label(self,text="Number Of Pixels").pack()
    entry4=tk.Entry(self)
    entry4.insert(0,"0.0")
    entry4.pack()

    button1=tk.Button(self,text='run',command = lambda: controller.rescalc(entry1,entry2,entry3,entry4,controller))
    button1.pack()

    button3 = tk.Button(self, text="Home", command=lambda: controller.show_frame(StartPage))
    button3.pack()

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

    argNumPixX= cont.NumPixX
    argNumPixY= cont.