【问题标题】:python AttributeError: NoneType has no attributepython AttributeError:NoneType没有属性
【发布时间】:2018-06-09 19:10:42
【问题描述】:

在我的程序 sn-p 中,我创建了一个带有 2 个字段和 3 个按钮的 Python 窗口。左边的两个按钮应该执行一些操作,但会抛出错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib64/python3.4/tkinter/__init__.py", line 1538, in __call__
    return self.func(*args)
  File ".../GuiFile.py", line 11, in <lambda>
    self.F[2] = ButtonClass().make_button(stacked="left",buttontext= "Action button", buttoncommand = lambda: cf.mainButtons.doButtonAction1(self))
  File ".../ClassFile.py", line 11, in doButtonAction1
    print(gf.StartGui.F[0].textField.get("1.0","end-1c"))
AttributeError: 'NoneType' object has no attribute 'textField'

为什么 dict item F[0](在 GuiFile.py 的第 9 行创建)不能被识别为具有 textField 属性的 Text() 类(在 GuiFile.py 的第 43 行定义)?

MainProgramFile.py

#!/usr/bin/env python3

import sys
import ClassFile
import GuiFile as gf

if __name__== '__main__': 
    gf.StartGui().mainloop()

GuiFile.py

import sys
from tkinter import *
import ClassFile as cf

class StartGui(Frame):
    F = {}
    def __init__(self,parent=None):
        Frame.__init__(self, parent)
        self.F[0] = FieldTextClass().make_field(labeltext="Label of field 1", fieldtext="veld 1", fieldheight=90) 
        self.F[1] = FieldTextClass().make_field(labeltext="Label of field 2", fieldtext="veld 2")
        self.F[2] = ButtonClass().make_button(stacked="left",buttontext= "Action button", buttoncommand = lambda: cf.mainButtons.doButtonAction1(self))
        self.F[3] = ButtonClass().make_button(stacked="left", buttontext= "Exchange button", buttoncommand = lambda: cf.mainButtons.doButtonSwitchValues(self))
        self.F[4] = ButtonClass().make_button(stacked="right",buttontext= "Quit button",buttoncommand = lambda: cf.mainButtons.doButtonQuit(self))
        self.pack(expand=True, fill=BOTH, anchor="nw", side=LEFT)
        #for i in range(self.F.__len__()): print(self.F[i].__class__,self.F[i].objectType)


class ButtonClass (Frame, Button):
    objectType = "button"

    def make_button(self, parent=None, stacked="horizontal", buttontext="Button", buttonwidth=120, buttonheight=32, buttoncommand=""):
        self.buttonwidth=buttonwidth
        self.buttonheight=buttonheight
        self.buttontext=buttontext
        self.buttoncommand=buttoncommand

        if stacked=="vertical": 
            BUTTONSTACK = TOP 
        elif stacked=="right": 
            BUTTONSTACK = RIGHT 
        elif stacked=="horizontal" or stacked=="left": 
            BUTTONSTACK = LEFT
        else:
            BUTTONSTACK = LEFT 

        self.top = Frame(parent, height=self.buttonheight, width=self.buttonwidth)
        self.top.pack_propagate(False)
        self.top.pack(side=BUTTONSTACK)       
        button = Button(self.top, text=self.buttontext, command=self.buttoncommand,height=self.buttonheight, width=self.buttonwidth)
        button.pack(fill=BOTH)

class FieldTextClass(Frame,Text,Label):
    textField = None
    objectType = "inputField" 

    def make_field(self, parent=None,  labeltext="Empty", fieldtext="Empty", fieldwidth=600, fieldheight=20, labelwidth=120, labelheight=20):
        self.fieldheight=fieldheight
        self.fieldwidth=fieldwidth
        self.fieldtext=fieldtext
        self.labeltext=labeltext
        self.labelheight=labelheight
        self.labelwidth=labelwidth
        self.top = Frame(parent)

        #create the label, whith the text shifted left/top in a separate Frame
        labelFrame = Frame(self.top, height = self.labelheight,width=self.labelwidth)
        label = Label(labelFrame, text=self.labeltext, fg="black", anchor="nw") 
        label.pack(expand=True, fill=BOTH, anchor="nw", side=LEFT)
        labelFrame.pack_propagate(False) 
        labelFrame.pack(side=LEFT,  anchor="nw")

        #create the text field, packed in a separate Frame
        fieldFrame = Frame(self.top, height = self.fieldheight,width=self.fieldwidth)
        self.textField = Text(fieldFrame, fg="black",bg="white")
        self.textField.insert(INSERT,self.fieldtext)
        self.textField.pack(expand=True, fill=BOTH, side=LEFT)
        fieldFrame.pack_propagate(False)
        fieldFrame.pack(side=LEFT)

        self.top.pack(side=TOP)

类文件.py

import sys 
from tkinter import *
import GuiFile as gf

class mainButtons():
    def doButtonQuit(self):
        print("Quitting test via ClassFile")
        self.quit()

    def doButtonAction1(self):
        print(gf.StartGui.F[0].textField.get("1.0","end-1c"))
        print(gf.StartGui.F[1].textField.get("1.0","end-1c"))
        gf.StartGui.F[0].textField.delete("1.0","end") 
        gf.StartGui.F[0].textField.insert(INSERT, "New text")

    def doButtonSwitchValues(self):
        tmp0=gf.StartGui.F[0].textField.get("1.0","end-1c")
        tmp1=gf.StartGui.F[1].textField.get("1.0","end-1c")
        gf.StartGui.F[0].textField.delete("1.0","end") 
        gf.StartGui.F[0].textField.insert(INSERT, tmp1)
        gf.StartGui.F[1].textField.delete("1.0","end") 
        gf.StartGui.F[1].textField.insert(INSERT, tmp0)

【问题讨论】:

  • 这里有一大堆问题。你需要了解类和实例,类属性和实例属性的区别。

标签: python tkinter attributeerror nonetype


【解决方案1】:

当您执行ButtonClass().make_button()(或FieldTextClass.make_field())时,python 将返回函数的值,而不是类的实例。函数返回None,所以字典元素为None

您使用自定义类的方式很奇怪。不要创建特殊函数,而是将该代码放在 __init__ 中,然后像使用任何其他类一样使用该类。

例如:

class ButtonClass (Frame):
    def __init__(self, parent=None, stacked="horizontal",
                 buttontext="Button", buttonwidth=120, buttonheight=32,
                 buttoncommand=""):
        Frame.__init__(self, parent)
        self.buttonwidth=buttonwidth
        ...

...
self.F[2] = ButtonClass(stacked="left",buttontext= "Action button", buttoncommand = lambda: cf.mainButtons.doButtonAction1(self))

注意:这样做时,您不必在__init__ 内创建单独的框架(即:self.top),因为self 本身已经是一个框架。

【讨论】:

  • 好的,很清楚。有用。但是,使用 Frame.__init__(parent) 会在此行引发错误:AttributeError: 'NoneType' object has no attribute 'widgetName'。我错过了什么?
  • @Mike:对不起,我给Frame.__init__ 遗漏了一个参数。我已经更新了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 1970-01-01
  • 2010-10-05
  • 2014-05-14
  • 1970-01-01
  • 2018-06-08
相关资源
最近更新 更多