2016-06-19 9 views
0

Ich machte eine relativ einfache Temperatur-Anwendung in Python mit Tkinter.Temperaturkonverter GUI UnboundLocalError/AttributeError Probleme

Ich habe es geschafft, die meisten Teile funktionieren zu lassen, aber der Teil, der sich damit beschäftigt, die Antwort zu bekommen, gibt mir Ärger. Ich denke, es hat damit zu tun, wie ich mich entscheide, wie ich von "x temperature unit" in "y temperature unit" umwandeln kann, indem ich if/elif benutze, um mein Programm auf die entsprechenden Konvertierungsfunktionen zu lenken. Mit meinen derzeitigen Versuchen tendiere ich dazu, UnboundLocalError zu bekommen, was, wie ich es verstehe, bedeutet, dass ich irgendwie versuche, eine Variable zu verwenden, in diesem Fall converted_temp, bevor ich ihr etwas zugebe. Ich bin mir jedoch nicht sicher, wie ich das lösen soll, da ich versucht habe, es einem Platzhalter zuzuordnen, und das am Ende nichts ausgibt. Gibt es eine Möglichkeit, diesen Fehler mit der Art und Weise zu umgehen, wie ich mein Programm geschrieben habe?

Hier ist, was ich schrieb:

import tkinter 
import tkinter.messagebox 

class TempConverterGUI: 
    def __init__(self): 
# create main window, and set a custom window title 
     self.main_window = tkinter.Tk() 
     self.main_window.wm_title("Convert Temperatures") 

# creates a top frame with label to give a title for the application 
     self.top_frame = tkinter.Frame(self.main_window) 
     self.title_label = tkinter.Label(self.top_frame, text= 'Temperature Converter') 
     self.title_label.pack(side='top') 
     self.top_frame.pack() 
# create middle frame to hold main program components 
     self.mid_frame = tkinter.Frame(self.main_window) 
############################################################################################# 
# create frame to hold the unit lists 
     self.lists_frame = tkinter.Frame(self.mid_frame) 
     ########################## 
# create frame to hold original unit to convert from list components   
     self.from_list_frame = tkinter.Frame(self.lists_frame) 
     self.from_label = tkinter.Label(self.from_list_frame, text='Convert from:') 
     self.from_label.pack(side='top') 

# creates radio button lists to allow user to decide which units to convert from 
     self.from_radio = tkinter.StringVar() 
     self.fb1 = tkinter.Radiobutton(self.from_list_frame, text= 'Fahrenheit', variable= self.from_radio, value= 'FAHRENHEIT') 
     self.fb2 = tkinter.Radiobutton(self.from_list_frame, text= 'Celsius', variable= self.from_radio, value= 'CELSIUS') 
     self.fb3 = tkinter.Radiobutton(self.from_list_frame, text= 'Kelvin', variable= self.from_radio, value= 'KELVIN') 
     self.fb1.pack() 
     self.fb2.pack() 
     self.fb3.pack() 
     ######################## 
# create frame to hold list components to decide which unit to convert to  
     self.to_list_frame = tkinter.Frame(self.lists_frame) 
     self.to_label = tkinter.Label(self.to_list_frame, text='Convert to:') 
     self.to_label.pack(side='top') 
# creates radio button lists to allow user to decide which units to convert to 
     self.to_radio = tkinter.StringVar() 
     self.tb1 = tkinter.Radiobutton(self.to_list_frame, text= 'Fahrenheit', variable= self.to_radio, value= 'FAHRENHEIT') 
     self.tb2 = tkinter.Radiobutton(self.to_list_frame, text= 'Celsius', variable= self.to_radio, value= 'CELSIUS') 
     self.tb3 = tkinter.Radiobutton(self.to_list_frame, text= 'Kelvin', variable= self.to_radio, value= 'KELVIN') 
     self.tb1.pack() 
     self.tb2.pack() 
     self.tb3.pack() 
#############################################################################################  
#Create frame to hold textbox input 
     self.entry_frame = tkinter.Frame(self.mid_frame) 


     self.temp_prompt_label = tkinter.Label(self.entry_frame, text='Enter a temperature:') 
     self.temp_entry = tkinter.Entry(self.entry_frame, width=10) 
     self.temp_prompt_label.pack(side='top') 
     self.temp_entry.pack(side='top') 
############################################################################################################################################################################ 
############################################################################################################################################################################      
# create frame to hold convert button components and answer label components   
     self.convert_frame = tkinter.Frame(self.mid_frame) 

# label to display answer 
     self.answer = tkinter.StringVar() 
     self.answer_label = tkinter.Label(self.convert_frame, textvariable=self.answer) 
     self.answer_label.pack(side='bottom') 
# convert button for actual conversion 
     self.convert_button = tkinter.Button(self.convert_frame, text='Convert', command=self.do_convert)################################## 
     self.convert_button.pack(side='top') 
##################################################### 
     ##Consider creating either error box or popup 

# create a bottom frame for miscellaneous buttons 
     self.bottom_frame = tkinter.Frame(self.main_window) 
     # instructions button that makes popup box telling how to use app 
     self.instructions_button = tkinter.Button(self.bottom_frame, text='Instructions', command=self.instructions) 
     self.instructions_button.pack(side='left') 
# quit button that quits app 
     self.quit_button = tkinter.Button(self.bottom_frame, text='Quit', command=self.main_window.destroy) 
     self.quit_button.pack(side='right') 
##############################################  
# packup the frames 
     self.from_list_frame.pack(side='left') 
     self.to_list_frame.pack(side='left') 

     self.lists_frame.pack(side='left') 
     self.convert_frame.pack(side='left') 
     self.entry_frame.pack(side='right') 



     self.mid_frame.pack(side ='top') 
     self.bottom_frame.pack(side='bottom') 
     # enter main loop 

     tkinter.mainloop() 
     #print(self.from_radio.get(), self.to_radio.get(), self.temp_entry)#### 
    def instructions(self): 
     tkinter.messagebox.showinfo('Instructions', 'This application allows the user to convert a temperature between Fahrenheit, Celsius, and Kelvin. '\ 
     'A user may select a unit to convert from, a unit to convert to, and what temperature they would like to convert. '\ 
      'Using this information they may convert the entered temperature into the desired unit.') 
######################################### 
# called by the convert button, uses from_radio selection to decide who to convert into(which conversion function to call) 
    def do_convert(self): 
     #self.converted_temp = None 
     if self.from_radio == 'FAHRENHEIT': 
      converted_temp = f_convert() 
     elif self.from_radio == 'CELSIUS': 
      converted_temp = c_convert() 
     elif self.from_radio == 'KELVIN': 
      converted_temp = k_convert() 
# sets self.answer(and so answer label) to value returned into converted_temp 
     self.answer.set(converted_temp) 
########################################################### 
# series of functions for each individual unit to hold conversion formulas for each possible case 
# using self.to_radio selection to decide which conversion to perform, then returns the resulting temperature 
# for use in do_convert 
    def f_convert(self): 
     if self.to_radio == 'FAHRENHEIT': 
      new_temp = self.temp_entry 
     elif self.to_radio == 'CELSIUS': 
      new_temp = (self.temp_entry - 32)*(5/9.0) 
     elif self.to_radio == 'KELVIN': 
      new_temp = (self.temp_entry + 459.67)*(5/9.0) 

     return new_temp 

    def c_convert(self): 
     if self.to_radio == 'FAHRENHEIT': 
      new_temp = (9/5.0)*self.temp_entry + 32.0 
     elif self.to_radio == 'CELSIUS': 
      new_temp = self.temp_entry 
     elif self.to_radio == 'KELVIN': 
      new_temp = self.temp_entry + 273.15 

     return new_temp 

    def k_convert(self): 
     if self.to_radio == 'FAHRENHEIT': 
      new_temp = (9/5.0)*(self.temp_entry-273.15) + 32 
     elif self.to_radio == 'CELSIUS': 
      new_temp = self.temp_entry - 273.15 
     elif self.to_radio == 'KELVIN': 
      new_temp = self.temp_entry 

     return new_temp 

conv_gui = TempConverterGUI() 
+0

Dein 'if' und' elif' fallen durch, weil 'self.to_radio' niemals die Werte" FAHRENHEIT "," CELSIUS "oder" KELVIN "hat. Der aktuelle Wert von "self.to_radio" ist "PY_VAR0". Vielleicht brauchst du 'self.to_radio.get()'? Außerdem fehlen einige "self" Präfixe, die Fehler wie 'NameError: globaler Name 'f_convert' ist nicht definiert werden. – jDo

Antwort

0

Der Code erneut berücksichtigt werden könnte - es gibt eine Menge Wiederholung - aber ich werde nur die zwei Dinge erwähnen, die wirklich sind verursacht Fehler:

  1. Die .get() Methode der self.from_radio nie aufgerufen.
  2. Fehlende self s vor Anrufen Klassenmethoden wie f_convert(), c_convert() usw.

Beispiel:

def do_convert(self): 
    if self.from_radio == 'FAHRENHEIT': <---- missing ".get()" after "self.from_radio" 
     converted_temp = f_convert() <---- missing "self" before f_convert() 
    elif self.from_radio == 'CELSIUS': 
     converted_temp = c_convert()  
    elif self.from_radio == 'KELVIN':  
     converted_temp = k_convert()  
    self.answer.set(converted_temp) 

Sie könnten neu schreiben, es zu so etwas wie diese:

def do_convert(self): 
    radio_value = self.from_radio.get() 
    if radio_value == 'FAHRENHEIT': 
     converted_temp = self.f_convert() 
    elif radio_value == 'CELSIUS': 
     converted_temp = self.c_convert() 
    elif radio_value == 'KELVIN': 
     converted_temp = self.k_convert() 
    self.answer.set(converted_temp) 
+0

Danke dafür, es hat mich auf die Spur gebracht, die ich anstrebte, und jetzt funktioniert alles gut (minus einige Fehler fangen). Ich merke, es braucht Refactoring, aber im Moment wollte ich nur etwas arbeiten und war auf diesem Teil fest. Vielen Dank. – mc92

+0

@ mc92 Schön, du bist willkommen :) – jDo

0

Sie bekommen den Fehler, weil Sie die get() Methode des self.from_radio Objekt des Typs zu verwenden, vergessen tkinter.StringVar seinen aktuellen Wert abzurufen. Aus diesem Grund ist keine der if-Anweisungen wahr, und die lokale Variable converted_temp ist nicht definiert, da ihr vor dem Verweis nie ein Wert zugewiesen wurde.

Im Folgenden wird eine modifizierte Version zeigt eine Möglichkeit, das Problem zu vermeiden:

# called by the convert_button, uses from_radio selection to 
    # decide what to convert into (i.e. which conversion function to call) 
     def do_convert(self): 
      converted_temp = '' # default if somehow there's no match 
      from_radio = self.from_radio.get() 
      if from_radio == 'FAHRENHEIT': 
       converted_temp = f_convert() 
      elif from_radio == 'CELSIUS': 
       converted_temp = c_convert() 
      elif from_radio == 'KELVIN': 
       converted_temp = k_convert() 

      self.answer.set(converted_temp)