0

I'm designing a GUI application that converts between celsius and fahrenheit. For now, there're primarily two problems that I'm not able to tackle:

1) When I enter an integer that needs to be converted based on the given conversion formula, the Label from tkinter cannot display the output properly. In fact, it shows something like this:

<conversionModel.Conversion object at 0x1057b11d0>

which made it really difficult for debug to a beginner like me.

2) There's a quitButton, thought which we can destroy() the GUI application. The problem is that when I close the GUI by clicking the red cross of the window, the Shell says:

_tkinter.TclError: can't invoke "destroy" command: application has been destroyed

I checked answers to other questions regarding the same problem, it turned out that it was because this GUI application was destroyed before closing. I had no idea how to address this particular problem.

Below are three pieces of code written in Model/View/Controller form:

The Model in conversionModel.py:

class Conversion:

        """
        class Conversion is the Model for a celsius-fahrenheit conversion
        application. It converts celsius into fahrenheit and fahrenheit into
        celsius.
        """

        def toCelsius(self, temp):
            return (5 / 9) * (temp - 32)

        def toFahrenheit(self, temp):
            return ((9 / 5) * temp) + 32

The View in conversionView.py:

import tkinter

class MyFrame(tkinter.Frame):

def __init__(self, controller):
    tkinter.Frame.__init__(self)
    self.pack()
    self.controller = controller

    self.tempEntry = tkinter.Entry()
    self.tempEntry.insert(0, "0")
    self.tempEntry.pack({"side": "left"})        

    self.celsiusButton = tkinter.Button(self)
    self.celsiusButton["text"] = "Celsius"
    self.celsiusButton["command"] = self.controller.buttonToC
    self.celsiusButton.pack({"side": "left"})

    self.fahrenheitButton = tkinter.Button(self)
    self.fahrenheitButton["text"] = "Fahrenheit"
    self.fahrenheitButton["command"] = self.controller.buttonToF
    self.fahrenheitButton.pack({"side": "left"})

    self.labelForOutput = tkinter.Label(self)
    self.labelForOutput["text"] = 0
    self.labelForOutput.pack ({"side": "left"})

    self.quitButton = tkinter.Button(self)
    self.quitButton["text"] = "Quit"
    self.quitButton["command"] =  self.quit
    self.quitButton.pack({"side": "left"})

The Controller in controller.py:

import tkinter
import conversionView
import conversionModel

class Controller:

    def __init__(self):
        root = tkinter.Tk()
        self.model = conversionModel.Conversion()
        self.view = conversionView.MyFrame(self)
        self.value = float(self.view.tempEntry.get())
        self.view.mainloop()
        root.destroy()

    def buttonToC(self):
        self.model.toCelsius(self.value)
        self.view.labelForOutput["text"] = str(self.model) + " °C"

    def buttonToF(self):
        self.model.toFahrenheit(self.value)
        self.view.labelForOutput["text"] = str(self.model) + " °F"

if __name__ == "__main__":
    c = Controller()

1 Answer 1

3

For #1, you need to read the tempEntry control each time you do a conversion, and capture the result of the conversion for printing. As it is now you only read the tempEntry control on __init__, and str(self.model) just prints out the name of the model object. This should work:

def buttonToC(self):
    fahr = float(self.view.tempEntry.get())
    temp = self.model.toCelsius(fahr)
    self.view.labelForOutput["text"] = str(temp) + " °C"

def buttonToF(self):
    celsius = float(self.view.tempEntry.get())
    temp = self.model.toFahrenheit(celsius)
    self.view.labelForOutput["text"] = str(temp) + " °F"

For #2, I'm not familiar enough with Tk yet to know why the Quit button works correctly but the red X destroys the windows before you get around to calling root.destroy, but this should work around it:

self.view.mainloop()
 try:
    root.destroy()
except tkinter.TclError:
    pass

The Quit button needs the destroy, but the X button doesn't and throws an exception. This code just ignores the exception in the X button case.

Sign up to request clarification or add additional context in comments.

1 Comment

or add root.protocol("WM_DELETE_WINDOW", app.on_delete) where app.on_delete is what he wants to do when closing no?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.