Tkinter Attribute Error when configuring tk Buttons
<p>I'm building an SMTP mail sender and when I started building the login window, I stumbled uppon an <strong>Attribute Error</strong> when trying to set a button state to '<em>disabled</em>'.</p>

<p>The first function in this example is the root and the second one is the one causing problems.</p>

<pre><code>class smtp_gui(tk.Tk):
    is_logged_in = False
    user_email = ''
    user_passwd = ''

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.wm_title("SMTP Mail Sender")
        self.resizable(False, False)
        self.iconbitmap('at.ico')
        self.container = tk.Frame(self)
        self.btn_container = tk.Frame(self)
        self.bind('&lt;Control-s&gt;', self.send)
        self.bind('&lt;Control-h&gt;', self.get_help)

        self.container.pack(side="top", padx=1, pady=1)
        self.container.columnconfigure(1, weight=1)
        self.btn_container.pack(side="bottom", padx=1, pady=1, fill='x')

        tk.Label(self.container, text='From:').grid(row=0, column=0, sticky='e')
        tk.Label(self.container, text='To:').grid(row=1, column=0, sticky='e')
        tk.Label(self.container, text='Subject:').grid(row=2, column=0, sticky='e')

        self.refresh()

        self.To = tk.Entry(self.container)
        self.To.grid(row=1, column=1, sticky="we", pady=3, padx=2)

        self.Subject = tk.Entry(self.container)
        self.Subject.grid(row=2, column=1, sticky="we", pady=2, padx=2)

        self.Msg = tk.Text(self.container, width=40, height=5)
        self.Msg.grid(columnspan=2, padx=3, pady=3)

        send_btn = tk.Button(self.btn_container, text="Send", command=self.send)
        send_btn.pack(side='right', padx=2, pady=1)

        quit_btn = tk.Button(self.btn_container, text="Quit", command=self.quit)
        quit_btn.pack(side='right', padx=2, pady=1)

    def send(self, event=None):
        print(self.Msg.get("0.0", "end"))

    def refresh(self):
        if self.logged_in():
            try:
                self.login_btn.destroy()
            except AttributeError:
                pass
            self.mailabel = tk.Label(self.container, bd=1, text=smtp_gui.user_email, relief='sunken')
            self.mailabel.grid(row=0, column=1, pady=3, padx=2, sticky='we')
        else:
            try:
                self.mailabel.destroy()
            except AttributeError:
                pass
            self.login_btn = tk.Button(self.container, text="login before sending", command=self.get_login)
            self.login_btn.grid(row=0, column=1, sticky="we", pady=3, padx=2)

    def logged_in(self):
        return smtp_gui.is_logged_in

    def get_login(self):
        login = LoginWindow()
        self.refresh()

    def get_help(self, event=None):
        get_help = HelpWindow()


class LoginWindow(tk.Toplevel):

    def __init__(self, *args, **kwargs):
        # Window config
        tk.Toplevel.__init__(self, *args, **kwargs)
        self.grab_set()
        self.wm_title("Email login")
        self.resizable(False, False)
        self.iconbitmap('login.ico')
        # Containers
        self.container = tk.Frame(self)
        self.btn_container = tk.Frame(self)

        self.container.pack(padx=2, pady=2)
        self.btn_container.pack(side="bottom", padx=1, pady=1, fill='x')

        # Tracers

        self.tracetest = tk.StringVar()
        self.tracetest.trace('w', self.tracer)

        # Window elements
        tk.Label(self.container, text="Gmail address:").grid(row=0, column=0)
        tk.Label(self.container, text="Password:").grid(row=1, column=0)

        # Entries
        self.Address = tk.Entry(self.container, width=44, textvariable=self.tracetest)
        self.Address.grid(row=0, column=1, sticky="we", pady=3, padx=2)
        self.Address.insert(0, "your address")

        self.Passwd = tk.Entry(self.container, show="*", textvariable=None)
        self.Passwd.grid(row=1, column=1, sticky="we", pady=3, padx=2)

        # Buttons
        self.login_btn = tk.Button(self.btn_container, text="Login", command=self.get_credentials)
        self.login_btn.pack(side='right', padx=2, pady=3)

        storno_btn = tk.Button(self.btn_container, text="Storno", command=self.destroy)
        storno_btn.pack(side='right', padx=2, pady=3)

    def get_credentials(self):
        user_address = self.Address.get()
        try:
            assert(match(r'[a-zA-Z0-9]+@gmail.com', user_address))
        except AssertionError:
        messagebox.showwarning("Invalid login", "This is not a valid gmail     address!")

    def tracer(self, *args):
        address = match(r'[a-zA-Z0-9]+@gmail.com', self.Address.get())
        passwd = ''
        if passwd and address:
            self.login_btn.config(state='enabled') # Attribute error here, the program says these buttons don't exist in the functions even tough I defined them above
        else:
            self.login_btn.config(state='disabled')
</code></pre>

<p>The problematic function is at <strong>the very end</strong> (in the tracer function), you should be able to reproduce the problem with this code ( just import tkinter as tk and regex )</p>

<p>I'm guessing there is some kind of a reference problem. </p>

<h1><strong>EDIT - FULL TRACEBACK</strong></h1>

<pre><code>Traceback (most recent call last):
  File "C:\Users\david\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1550, in __call__
    return self.func(*args)
  File "C:\Users\david\Documents\Git_repositories\smtp_client\main_menu.py", line 129, in tracer
    self.login_btn.config(state='disabled')
AttributeError: 'LoginWindow' object has no attribute 'login_btn'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\david\Documents\Git_repositories\smtp_client\main_menu.py", line 160, in &lt;module&gt;
    root.mainloop()
  File "C:\Users\david\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1131, in mainloop
    self.tk.mainloop(n)
  File "C:\Users\david\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1554, in __call__
    self.widget._report_exception()
AttributeError: 'StringVar' object has no attribute '_report_exception'
</code></pre>

<h1>FOUND A SOLUTION</h1>

<p>The traceback occured because the tracer was called before the creation of the button, when I moved the tracer after the initiation of the button, it worked perfectly, thanks guys!</p>

<p>The trace fires when the value changes. The value changes when you do <code>self.address.insert(0, "your address")</code> because that widget is tied to the variable. All of this happens before you define <code>self.login_btn</code>.</p>

<p>You need to define the button before you enable the trace, or before you change the value of the traced variable.</p>

python class tkinter attributeerror