Reputation: 15
I have a button in my Tkinter window that, when clicked, needs to call two functions: a .get()
to store the entry box value and a .destroy()
so the window closes when button is pressed.
I must be doing something wrong because whether I put the .destroy()
in my grouped function with .get()
or put .destroy()
as the sole command in the button, I get this error:
AttributeError: 'GuardianLocator' object has no attribute 'frame'
I believe my code is near identical to other answers on this site so I'm not sure why .destroy()
isn't working...
from tkinter import *
class GuardianLocator:
def __init__(self, master):
self._name = ""
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
self.locator_label = Label(frame, text="Which Sailor Guardian are you looking for?", width=40, height=2)
self.locator_label.grid()
self.entry = Entry(frame)
self.entry.grid()
self.button1 = Button(frame, text="Search", command=self.guardian_name, pady=2)
self.button1.grid()
def guardian_name(self):
self._name = self.entry.get()
self.frame.destroy()
return self.entry.get()
EDIT
When I make the recommended changes to the self.frame from the answers, the program runs, but then when I click the button I get this error-
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1482, in __call__
return self.func(*args)
File "C:\Users\david\PycharmProjects\Sailor Moon Hunt\guardian_locator.py", line 25, in guardian_name
return self.entry.get()
File "C:\Python34\lib\tkinter\__init__.py", line 2484, in get
return self.tk.call(self._w, 'get')
_tkinter.TclError: invalid command name ".45213328.45795632"
It appears to be referring to the .get() call, but that was working fine before I made the self.frame changes. Does anyone know what that error means?
Upvotes: 0
Views: 2381
Reputation:
The problem isn't with the destroy
method. Instead, Python is complaining that it cannot find the frame
attribute of self
. This is because you forgot to actually make frame
an instance attribute inside GuardianLocator.__init__
:
self.frame = Frame(master)
self.frame.grid()
Notice the self.
placed before each use of the name frame
.
Without doing this, the name frame
is local to the __init__
method and therefore inaccessible inside guardian_name
via self
.
Edit:
When you do:
self.frame.destroy()
the Frame
object referenced by self.frame
is destroyed and becomes no longer usable. Moreover, the Entry
object referenced by self.entry
is likewise destroyed since it is a child of the frame. This means that you cannot do:
return self.entry.get()
because self.entry
no longer exists at that point.
To avoid this problem, you should be returning self._name
, which equals self.entry.get()
:
return self._name
Upvotes: 2
Reputation: 2063
change this code:
def __init__(self, master):
self._name = ""
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
with the following:
def __init__(self, master):
self._name = ""
self.frame = Frame(master)
self.frame.grid()
master.title("GUARDIAN LOCATOR")
Upvotes: 0