【问题标题】:Temperature Converter Issue温度转换器问题
【发布时间】:2012-10-16 22:30:55
【问题描述】:

我正在使用 GUI 为我的第一个主要项目制作温度转换器,即 Tkinter 模块。我在初始化 GUI 时没有任何问题。这很好用(据我所知)。我需要一些帮助来制作 IF 语句来调用与转换相关的每个函数。我遇到的问题是我不确定如何显示来自两个不同列表的两个项目之间的等价性。这是我的代码(我知道我遗漏了一些东西。显然是 if 语句。)

from tkinter import *

gui = Tk()
gui.title(string='Temperature Converter')
#create the GUI
fromUnit = StringVar()
#variable which holds the value of which unit is active in "units1"
toUnit = StringVar()
#variable which holds the value of which unit is active in "units2"
initialTemp = StringVar()
#the initial temperature entered in "enterTemp" entry
initialTemp.set('0')
#set the initial temperature to 0
convertedTemp = StringVar()
#used to display the converted temperature through "displayTemp" 
convertedTemp.set('0')
#set the converted temperature to 0

units1 = ('Celsius', 'Fahrenheit', 'Kelvin') #the units used in the OptionMenu
units2 = ('Celsius', 'Fahrenheit', 'Kelvin')

fromUnit.set(units1[0]) #set the active element to the item in index[0] of units1
toUnit.set(units2[0]) #set the active element to the item in index[0] of units2

# celsius-celcius conversion
def celsius_to_celsius():
    currentTemp = float(initialTemp.get())
    convertedTemp.set(currentTemp)

# celsius-kelvin conversion
def celsius_to_kelvin():
    currentTemp = float(initialTemp.get())
    currentTemp = (currentTemp + 273.15)
    convertedTemp.set(currentTemp)

# celsius-fahrenheit conversion
def celsius_to_fahrenheit():
    currentTemp = float(initialTemp.get())
    currentTemp = (currentTemp * (9/5))+32
    convertedTemp.set(currentTemp)

#fahrenheit-fahrenheit conversion
def fahrenheit_to_fahrenheit():
    currentTemp = float(initialTemp.get())
    convertedTemp.set(currentTemp)

#fahrenheit-celsius conversion
def fahrenheit_to_celsius():
    currentTemp = float(initialTemp.get())
    currentTemp = ((currentTemp - 32)*(5/9))
    convertedTemp.set(currentTemp)

#fahrenheit-kelvin conversion
def fahrenheit_to_kelvin():
    currentTemp = float(initialTemp.get())
    currentTemp = ((currentTemp - 32)*(5/9)+273.15)
    convertedTemp.set(currentTemp)

#kelvin-kelvin conversion
def kelvin_to_kelvin():
    currentTemp = float(initialTemp.get())
    convertedTemp.set(currentTemp)

#kelvin-celsius conversion
def kelvin_to_celsius():
    currentTemp = float(initialTemp.get())
    currentTemp = (currentTemp - 273.15)
    convertedTemp.set(currentTemp)

#kelvin-fahrenheit conversion
def kelvin_to_fahrenheit():
    currentTemp = float(initialTemp.get())
    currentTemp = (((currentTemp - 273.15)*(9/5))+32)
    convertedTemp.set(currentTemp)

#main function
#contains the if statements which select which conversion to use
def convert_Temp():
    currentTemp = float(initialTemp.get())
    if (fromUnit, toUnit) == ('Celsius','Celsius'):
        celsius_to_celsius()


gui.geometry('+100+100')
#set up the geometry

enterTemp = Entry(gui,textvariable=initialTemp,justify=RIGHT)
enterTemp.grid(row=0,column=0)
#Entry which receives the temperature to convert

convertFromUnit = OptionMenu(gui,fromUnit,*units1)
convertFromUnit.grid(row=0,column=1)
#Option Menu which selects which unit to convert from

displayTemp = Label(gui,textvariable=convertedTemp)
displayTemp.grid(row=1,column=0)
#Label which displays the temperature
#Takes text variable "convertTemp"

convertToUnit = OptionMenu(gui,toUnit,*units2)
convertToUnit.grid(row=1,column=1)
#Option Menu which selects which unit to convert to

convertButton = Button(gui,text='Convert',command=convert_Temp)
convertButton.grid(row=2,column=1)
#Button that starts the conversion
#Calls the main function "convert_Temp"

gui.mainloop()
#End of the main loop

感谢您的观看以及您提供的任何帮助和批评。没有知识是浪费的! 干杯

【问题讨论】:

  • DRY。如果你说的东西不止一次,你就说太多次了。另外,这属于codereview.stackexchange.com
  • 我会做这样的事情:codepad.org/xQ7HQ3ft(非常快速和肮脏,可以使用一些改进)
  • @NullUserException 我之前尝试过。然而,我刚开始编程,我还没有达到类和对象的水平。照原样,如果您运行代码,它不会更改标签。但是如果我删除 if 语句并做一些简单的事情,比如调用函数,我可以得到改变。但是,当我添加 if 语句时,我遇到了麻烦。我做了一些 quazi 调试,如果 IF 语句不正确,则会创建错误消息。
  • 执行IF语句时立即抛出错误信息。
  • 您可能会向我们展示您尝试过的(并引发错误)[而不是/除了]有效的方法...

标签: python function if-statement tkinter


【解决方案1】:

正如 cmets 中所指出的,您有一些架构缺陷(这是正常的,因为您正在学习)并且您可能会从 CodeReview 社区(它是 stackexchange 网络的另一个站点)获得有趣的反馈。

这里有几个选项可以用来执行您所谓的 If 语句。你的事实 已经将转换包含在函数中扩大了可能性。

1) 枚举 if 中的所有组合

你已经开始了,不同的是:使用fromUnit.get() 访问 tkinter 变量的值1

if (fromUnit.get(), toUnit.get()) == ('Celsius','Celsius'):
    celsius_to_celsius()
if (fromUnit.get(), toUnit.get()) == ('Celsius','Fahrenheit'):
    celsius_to_fahrenheit()
if (fromUnit.get(), toUnit.get()) == ('Celsius','Kelvin'):
    celsius_to_kelvin()

2) 嵌套 if

if fromUnit.get() == 'Celsius':
    if toUnit.get()) == 'Celsius':
        celsius_to_celsius()
    if toUnit.get()) == 'Fahrenheit':
        celsius_to_fahrenheit()
    if toUnit.get()) == 'Kelvin':
        celsius_to_kelvin()

3) 使用字典(关联数组)来存储函数

converters = {
    'Celsius' : {
        'Celsius' : celsius_to_celsius,
        'Fahrenheit': celsius_to_fahrenheit,
        'Kelvin': celsius_to_kelvin},
    'Fahrenheit' : {
        'Celsius' : fahrenheit_to_celsius,
        'Fahrenheit': fahrenheit_to_fahrenheit,
        'Kelvin': fahrenheit_to_kelvin},
    #...
}
#retrieve function, and call it (through the () at the end)
converters [fromUnit.get()] [toUnit.get()] ()

实际上,它使用嵌套字典。你也可以只用一本字典

converters = {
    ('Celsius', 'Celsius') : celsius_to_celsius,
    ('Celsius', 'Fahrenheit'): celsius_to_fahrenheit,
    ('Celsius', 'Kelvin'): celsius_to_kelvin,
}
converters [(fromUnit.get(), toUnit.get())] ()

4) 您使用的一致命名方案允许生成函数名称

function_name = fromUnit.get().lower() + "_to_" + toUnit.get().lower()
globals()[function_name] ()

5) 委托调度

通常,大型组合 if(或在存在的语言中切换)对重构具有吸引力。 例如,您可能会在 convertFromUnitfromUnit(分别为 *toUnit)上执行初步工作。

使用嵌套字典的机制非常接近 Python 对象内部使用的机制。

def fromUnitCallback():
    global _converter
    _converter = globals()[fromUnit.get()]()

def toUnitCallback():
    global _function_name
    _function_name = toUnit.get().lower()

def convert_Temp():
    currentTemp = float(initialTemp.get())
    _converter.set(currentTemp)
    converted = getattr(_converter, _function_name) ()
    convertedTemp.set(converted)

class Kelvin:
    def __init__(self, val=0):
        self.__kelvin = val

    def kelvin(self):
        return self.__kelvin

    def celsius(self):
        return self.__kelvin - 273.15

    def fahrenheit(self):
        return (self.__kelvin - 273.15)*1.8 + 32

    def set(self, val):
        self.__kelvin = val

class Celsius(Kelvin):
    def __init__(self, val):
        Kelvin.__init__(self)
        self.set(val)

    def set(self, val):
        Kelvin.set(self, val + 273.15)

class Fahrenheit:
    def __init__(self, val):
        Kelvin.__init__(self)
        self.set(val)

    def set(self, val):
        Kelvin.set((val - 32)*5/9 + 273.15)


1 Tkinter 变量是对象,即复合人工制品嵌入值和相关方法。除了它们可以是traced之外,它们的用途与常规变量相同,即被警告它们的值已更改。它们与 tkinter 小部件结合使用以简化操作。这里要比较fromUnit的内容和字符串'Celsius'的内容,所以需要通过get方法询问fromUnit这个字符串。更多详情请见http://effbot.org/tkinterbook/variable.htm

【讨论】:

  • 感谢您的精彩回复。我最终自己发现,我遇到的关键问题是我需要调用 '.get()' 方法。我找到了一种方法来测试它,而不是调用函数来打印转换后的温度,而是将标签的值更改为“单位”。当它没有返回值时,我意识到我做错了什么。然后我将代码调整为更简洁一些。
【解决方案2】:

这是我上面启动的程序的最终源代码。

from tkinter import *

gui = Tk()
gui.title(string='Temperature Converter')
#create the GUI
fromUnit = StringVar()
#variable which holds the value of which unit is active in "units1"
toUnit = StringVar()
#variable which holds the value of which unit is active in "units2"
initialTemp = StringVar()
#set the initial temperature to 0
convertedTemp = StringVar()
#used to display the converted temperature through "displayTemp" 
convertedTemp.set('0')
#set the converted temperature to 0

units1 = ('Celsius', 'Fahrenheit', 'Kelvin') #the units used in the OptionMenu
units2 = ('Celsius', 'Fahrenheit', 'Kelvin')

fromUnit.set(units1[0]) #set the active element to the item in index[0] of units1
toUnit.set(units2[0]) #set the active element to the item in index[0] of units2

#main function
#contains the if statements which select which conversion to use
def convert_Temp():
    currentTemp = float(initialTemp.get())
    cu1 = fromUnit.get()
    cu2 = toUnit.get()

    if (cu1, cu2) == ('Celsius', 'Celsius'):
        c_c()
    elif (cu1, cu2) == ('Celsius', 'Kelvin'):
        c_k()
    elif (cu1, cu2) == ('Celsius', 'Fahrenheit'):
        c_f()
    elif (cu1, cu2) == ('Fahrenheit', 'Fahrenheit'):
        f_f()
    elif (cu1, cu2) == ('Fahrenheit', 'Celsius'):
        f_c()
    elif (cu1, cu2) == ('Fahrenheit', 'Kelvin'):
        f_k()
    elif (cu1, cu2) == ('Kelvin', 'Kelvin'):
        k_k()
    elif (cu1, cu2) == ('Kelvin', 'Celsius'):
        k_c()
    elif (cu1, cu2) == ('Kelvin', 'Fahrenheit'):
        k_f()
    else:
        messagebox.showerror(title='ERROR', message='Error in the IF statements')

# celsius-celcius conversion
def c_c():
    currentTemp = float(initialTemp.get())
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

# celsius-kelvin conversion
def c_k():
    currentTemp = float(initialTemp.get())
    currentTemp = (currentTemp + 273.15)
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

# celsius-fahrenheit conversion
def c_f():
    currentTemp = float(initialTemp.get())
    currentTemp = (currentTemp * (9/5))+32
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

#fahrenheit-fahrenheit conversion
def f_f():
    currentTemp = float(initialTemp.get())
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

#fahrenheit-celsius conversion
def f_c():
    currentTemp = float(initialTemp.get())
    currentTemp = (currentTemp - 32)*(5/9)
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

#fahrenheit-kelvin conversion
def f_k():
    currentTemp = float(initialTemp.get())
    currentTemp = ((currentTemp - 32)*(5/9)+273.15)
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

#kelvin-kelvin conversion
def k_k():
    currentTemp = float(initialTemp.get())
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

#kelvin-celsius conversion
def k_c():
    currentTemp = float(initialTemp.get())
    currentTemp = (currentTemp - 273.15)
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)

#kelvin-fahrenheit conversion
def k_f():
    currentTemp = float(initialTemp.get())
    currentTemp = (((currentTemp - 273.15)*(9/5))+32)
    currentTemp = round(currentTemp, 2)
    convertedTemp.set(currentTemp)


gui.geometry('+100+100')
#set up the geometry

enterTemp = Entry(gui,textvariable=initialTemp,justify=RIGHT)
enterTemp.grid(row=0,column=0)
#Entry which receives the temperature to convert

convertFromUnit = OptionMenu(gui,fromUnit,*units1)
convertFromUnit.grid(row=0,column=1)
#Option Menu which selects which unit to convert from

displayTemp = Label(gui,textvariable=convertedTemp)
displayTemp.grid(row=1,column=0)
#Label which displays the temperature
#Takes text variable "convertTemp"

convertToUnit = OptionMenu(gui,toUnit,*units2)
convertToUnit.grid(row=1,column=1)
#Option Menu which selects which unit to convert to

convertButton = Button(gui,text='Convert',command=convert_Temp)
convertButton.grid(row=2,column=1)
#Button that starts the conversion
#Calls the main function "convert_Temp"

gui.mainloop()
#End of the main loop

【讨论】:

  • 欢迎使用 Stackoverflow!它是一个问答网站(不仅仅是一个论坛),因此我们尽量保持问题和答案的通用性,因此避免在问答正文中出现问候。感谢人们的常用方式是投票(cmets,答案)或接受答案。你可以看看stackoverflow.com/aboutstackoverflow.com/faq
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多