【问题标题】:Tkinter: AttributeError: NoneType object has no attribute <attribute name>Tkinter:AttributeError:NoneType 对象没有属性<属性名称>
【发布时间】:2022-01-17 21:16:57
【问题描述】:

我创建了这个简单的 GUI:

from tkinter import *

root = Tk()

def grabText(event):
    print(entryBox.get())    

entryBox = Entry(root, width=60).grid(row=2, column=1, sticky=W)

grabBtn = Button(root, text="Grab")
grabBtn.grid(row=8, column=1)
grabBtn.bind('<Button-1>', grabText)

root.mainloop()

我启动并运行了 UI。当我单击Grab 按钮时,控制台上出现以下错误:

C:\Python> python.exe myFiles\testBed.py
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python\lib\lib-tk\Tkinter.py", line 1403, in __call__
    return self.func(*args)
  File "myFiles\testBed.py", line 10, in grabText
    if entryBox.get().strip()=="":
AttributeError: 'NoneType' object has no attribute 'get'

为什么entryBox 设置为None?

【问题讨论】:

    标签: python user-interface tkinter


    【解决方案1】:

    Entry 对象和所有其他小部件的 grid、pack 和 place 函数返回 None。在 python 中,当您执行a().b() 时,表达式的结果是b() 返回的任何内容,因此Entry(...).grid(...) 将返回None。

    你应该像这样把它分成两行:

    entryBox = Entry(root, width=60)
    entryBox.grid(row=2, column=1, sticky=W)
    

    这样您就可以将您的Entry 引用存储在entryBox 中,并且它的布局与您期望的一样。如果您以块的形式收集所有 grid 和/或 pack 语句,这有一个额外的副作用,即使您的布局更易于理解和维护。

    【讨论】:

      【解决方案2】:

      改变这一行:

      entryBox=Entry(root,width=60).grid(row=2, column=1,sticky=W)
      

      分为这两行:

      entryBox=Entry(root,width=60)
      entryBox.grid(row=2, column=1,sticky=W)
      

      正如您已经正确地为grabBtn 所做的那样!

      【讨论】:

        【解决方案3】:

        要让entryBox.get() 访问get() 方法,您需要Entry 对象,但Entry(root, width=60).grid(row=2, column=1, sticky=W) 返回无。

        entryBox = Entry(root, width=60) 创建一个新的条目对象。

        此外,您不需要 entryBox = entryBox.grid(row=2, column=1, sticky=W) 因为它将用 None 重写 entryBox


        只需替换entryBox = entryBox.grid(row=2, column=1, sticky=W) 与

        entryBox = Entry(root, width=60)
        entryBox.grid(row=2, column=1, sticky=W)
        

        【讨论】:

        • 这不只是重复接受的答案,而是 11 年后?
        【解决方案4】:

        Python3.8+ 版本的替代解决方案允许使用 walrus operator 将所有这些放在一行中:

        (entryBox := Entry(root, width=60)).grid(row=2, column=1, sticky=W)
        

        现在entryBox 将引用Entry 小部件并被打包。

        对于每行管理的字符,我可以这样建议:​​

        (var := Button(
            text='fine', command=some_func, width=20, height=15, activebackground='grey'
        )).grid(row=0, column=0, columnspan=0, rowspan=0, sticky='news')
        

        但到那时还不如“正常”地这样做(正如其他答案所建议的那样)

        来源:

        【讨论】:

          猜你喜欢
          相关资源
          最近更新 更多