Tkinter: AttributeError: NoneType object has no attribute <attribute name>
The grid
, pack
and place
functions of the Entry
object and of all other widgets returns None
. In python when you do a().b()
, the result of the expression is whatever b()
returns, therefore Entry(...).grid(...)
will return None
.
You should split that on to two lines like this:
entryBox = Entry(root, width=60)
entryBox.grid(row=2, column=1, sticky=W)
That way you get your Entry
reference stored in entryBox
and it's laid out like you expect. This has a bonus side effect of making your layout easier to understand and maintain if you collect all of your grid
and/or pack
statements in blocks.
Change this line:
entryBox=Entry(root,width=60).grid(row=2, column=1,sticky=W)
into these two lines:
entryBox=Entry(root,width=60)
entryBox.grid(row=2, column=1,sticky=W)
Just as you already correctly do for grabBtn
!
For entryBox.get()
to access get()
method you need Entry object but Entry(root, width=60).grid(row=2, column=1, sticky=W)
returns None.
entryBox = Entry(root, width=60)
creates a new Entry Object.
Moreover, you won't need
entryBox = entryBox.grid(row=2, column=1, sticky=W)
as it will rewrite entryBox
with None
Just replace entryBox = entryBox.grid(row=2, column=1, sticky=W)
with
entryBox = Entry(root, width=60)
entryBox.grid(row=2, column=1, sticky=W)
Alternative solution for Python3.8+
versions that allows to put all of this in one line using the walrus operator
:
(entryBox := Entry(root, width=60)).grid(row=2, column=1, sticky=W)
Now entryBox
will refer to the Entry
widget and also get packed.
For chars per line management I can suggest sth like this:
(var := Button(
text='fine', command=some_func, width=20, height=15, activebackground='grey'
)).grid(row=0, column=0, columnspan=0, rowspan=0, sticky='news')
But at that point might as well just do this "normally" (as suggested by other answers)
Sources:
- PEP 572 -- Assignment Expressions
- IMO great video explanation about
walrus operator