温度转换器GUI UnboundLocalError / AttributeError问题

时间:2016-06-19 18:09:58

标签: python python-3.x tkinter local-variables

我使用Tkinter在Python中创建了一个相对简单的温度应用程序。

我设法让大多数部分工作,但实际处理答案的部分给了我麻烦。我认为这与我决定如何从" x温度单位"转换的方式有关。到温度单位",使用if / elif将我的程序指向适当的转换函数。在我目前的尝试中,我倾向于获得UnboundLocalError,据我所知,这意味着我在某种程度上尝试使用变量,在本例中为converted_temp,在我分配它之前。但是,我不知道如何解决这个问题,因为我已经尝试将其分配给某个占位符,并且最终不会输出任何内容。有没有办法用我编写程序的方式解决这个错误?

这是我写的:

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()

2 个答案:

答案 0 :(得分:0)

您因错误使用get()类型self.from_radio对象的tkinter.StringVar方法检索其当前值而导致错误。因为if个语句都不是真的,并且局部变量converted_temp未定义,因为它在引用之前从未赋值。

以下是修改后的版本,显示了避免此问题的一种方法:

    # 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)

答案 1 :(得分:0)

代码可以重新考虑 - 有很多重复 - 但我只是提到实际导致错误的两件事:

  1. 永远不会调用.get()的{​​{1}}方法。
  2. 在调用self.from_radioself等类方法之前缺少f_convert()个。
  3. 示例:

    c_convert()

    您可以将其重写为以下内容:

    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)