2016-08-25 22 views
0

TKボタンを設定するとき、私はSMTPメール送信者を構築していると私は、ログインウィンドウを構築開始時に「無効」にボタンの状態を設定しようとしたとき、私は属性エラー upponつまずきました。Tkinterの属性エラー

この例の最初の機能はルートであり、2番目の機能は問題を引き起こす機能です。

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('<Control-s>', self.send) 
     self.bind('<Control-h>', 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][email protected]', 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][email protected]', 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') 

問題の機能は非常に、あなたがこのコードで問題を再現することができるはずです(トレーサー機能で)を終了

私は」(ちょうどTKと正規表現としてTkinterのインポート)であります何らかの参考問題があると推測しています。

EDIT - FULL TRACEBACK

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 <module> 
    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' 

は、私は、ボタンの開始後トレーサーを移動したときトレーサーは、ボタンの作成前に呼ばれたので、トレースバックが発生した

解決策を見つけました、それは完璧に働いた、おかげでみんな!

+0

エラーの完全なトレースバックを投稿してください。また、 '有効'は有効な状態ではありません。おそらく '正常'であるべきです – FamousJameous

+0

トレースバックを追加しました。 –

+0

私はこれまで可変トレーサを使ったことがありません。変数の初期作成時にトレースコールバックが呼び出されますか? – FamousJameous

答えて

2

値が変更されると、トレースが発生します。ウィジェットが変数に関連付けられているため、self.address.insert(0, "your address")を実行すると値が変更されます。これはすべて、self.login_btnを定義する前に発生します。

トレースを有効にする前に、またはトレースされた変数の値を変更する前に、ボタンを定義する必要があります。

+0

Exaclty man、あなたは私と同じ結論になりました編集済みの投稿: –