¿Por qué aparece "AttributeError: el objeto NoneType no tiene atributo" usando Tkinter? ¿De dónde vino el valor Ninguno?
He creado esta sencilla 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()
Cuando hago clic en el Grab
botón, ocurre un error:
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'
¿Por qué está entryBox
configurado en None
?
Consulte también ¿Por qué aparece AttributeError: el objeto 'NoneType' no tiene el atributo 'algo'? para el caso general.
Las funciones y grid
del objeto y de todos los demás widgets devuelven . En Python, cuando lo hace , el resultado de la expresión es lo que regresa, por lo tanto, regresará .pack
place
Entry
None
a().b()
b()
Entry(...).grid(...)
None
Deberías dividirlo en dos líneas como esta:
entryBox = Entry(root, width=60)
entryBox.grid(row=2, column=1, sticky=W)
De esa manera, tu Entry
referencia se almacena entryBox
y se presenta como esperas. Esto tiene el efecto secundario adicional de hacer que su diseño sea más fácil de entender y mantener si recopila todas sus declaraciones grid
y/o pack
en bloques.
Cambie esta línea:
entryBox=Entry(root,width=60).grid(row=2, column=1,sticky=W)
en estas dos líneas:
entryBox=Entry(root,width=60)
entryBox.grid(row=2, column=1,sticky=W)
Tal como ya lo haces correctamente con grabBtn
!
Solución alternativa para Python3.8+
versiones que permite poner todo esto en una línea usando walrus operator
:
(entryBox := Entry(root, width=60)).grid(row=2, column=1, sticky=W)
Ahora entryBox
nos referiremos al Entry
widget y también lo empaquetaremos.
Para la gestión de caracteres por línea puedo sugerir algo como esto:
(var := Button(
text='fine', command=some_func, width=20, height=15, activebackground='grey'
)).grid(row=0, column=0, columnspan=0, rowspan=0, sticky='news')
Pero en ese momento también podría hacer esto "normalmente" (como lo sugieren otras respuestas)
Fuentes:
- PEP 572 -- Expresiones de asignación
- En mi opinión, gran video explicativo sobre
walrus operator