问题
This isn't a difficult question, but I can't wrap my head around it when dealing with MVC architecture (passing arguments between the VIEW, MODEL, and CONTROLLER).
Error in question:
Exception in Tkinter callback Traceback (most recent call last):
File "C:\Python33\lib\tkinter__init__.py", line 1482, in call return self.func(*args) File "C:\Users\Mike\Desktop\code\Assignment 6\glue.py", line 37, in buttonPressed self.model.convertTempF2C(view.fahrenheitEntrySpace.get) NameError: global name 'view' is not defined
The VIEW (myFrame.py)
"""writing event handlers"""
import tkinter
import glue
class MyFrame(tkinter.Frame): #creates window for controls in an object made
#from a class called "tkinter.Frame"
"""
Class myFrame is a tkinter.Frame...
It contains two buttons, two entry areas, and four labels:
one button a converter;
one button quits the program;
one entry is for celsius;
one entry is for fahrenheit;
and the labels prompt user for input, and label the entry values as needed.
"""
def __init__(self, controller):
"""
places the controls on the frame
"""
tkinter.Frame.__init__(self) #initilizes the superclass
self.pack() #required for the buttons to show up properly.
self.controller = controller #saves ref to controller to call methods on
#contoller object when user generates events
#Fahrenheit Input Prompt
self.fahrenheitLabel = tkinter.Label(self)
self.fahrenheitLabel["text"] = ("Enter Fahrenheit Value:")
self.fahrenheitLabel.pack({"side":"left"})
#Fahrenheit Entry Space
self.fahrenheitEntrySpace = tkinter.Entry(self)
self.fahrenheitEntrySpace == self.fahrenheitEntrySpace.insert(1, "0") #creates starting value of 0
self.fahrenheitEntrySpace.pack({"side":"left"})
#Fahrenheit Value label (double checked)
self.fahrenheitLabel = tkinter.Label(self)
self.fahrenheitLabel["text"] = ("Fahrenheit Degrees")
self.fahrenheitLabel.pack({"side":"left"})
#Converter button (double checked)
self.convertButton=tkinter.Button(self)
self.convertButton["text"]= "Convert"
self.convertButton["command"]=self.controller.buttonPressed
# an object that remembers both self and reply when later called
self.convertButton.pack({"side":"left"})
#Quit button
self.quitButton = tkinter.Button(self)
self.quitButton["text"] = "Press\nhere to\n***QUIT***"
self.quitButton["command"] = self.quit
#the statement above attaches the event handler
#self.quit() to the quit button
self.quitButton.pack({"side":"right"})
#Celsius Value label
self.celsiusLabel = tkinter.Label(self)
self.celsiusLabel["text"] = ("Celsius Degrees")
self.celsiusLabel.pack({"side":"right"})
#Celsius Entry Space
self.celsiusEntrySpace = tkinter.Entry(self)
self.celsiusEntrySpace["text"] == self.celsiusEntrySpace.insert(1, "0") #creates starting value of 0
self.celsiusEntrySpace.pack({"side":"right"})
#Celsius Input Prompt
self.celsiusLabel = tkinter.Label(self)
self.celsiusLabel["text"] = ("Enter Celsius Value:")
self.celsiusLabel.pack({"side":"right"})
#Test program
if __name__=="__main__":
root = tkinter.Tk()
view = MyFrame() #puts the frame onto the user's screen.
view.mainloop()
root.destroy()
The MODEL (counter.py)
import tkinter
import glue
class Convert: #the MODEL
'''
class counter is the MODEL for a simple program that exemplifies
the MODEL/VIEW/CONTROLLER achitecture.
It mostly just maintains two formulas that convert Fahrenheit to Celsius
and Celsius to Fahrenheit each time the f2C() or c2F methods are called.
in a real MVC app, the MODEL would contain all the business logic.
Note that the model never contains a reference to the VIEW.
'''
def __init__(self):
self.fahrenheitEntrySpace = 0
self.celsiusEntrySpace = 0
def convertTempF2C(self):
fahrenheit = controller.fahrenheitEntrySpace
if fahrenheit != 0.0:
controller.celsius = (fahrenheit - 32) * 5 / 9
else:
contoller.celsius = -17.7777778
def convertTempC2F(self):
celsius = celsiusEntrySpace.get()
if celsius != 0.0:
controller.fahrenheit = (celsius * 9.0/5.0 + 32)
else:
controller.fahrenheit = 32
def __str__(self):
return str(self.counter)
The Controller (glue.py)
#Event Handler for a button in tkinter is self.yourButton["Command"] = self.yourObject.yourObjectMethod()
import tkinter
import myFrame #the VIEW
import counter #the MODEL
class Controller():
"""
The CONTROLLER for an app that follows the MODEL/VIEW/CONTROLLER architecture.
When the user presses a button on the VIEW,
this controller calls the appropriate methods in the model.
The controller handles all the communication between the model and the view.
"""
def __init__(self):
"""
This starts the TK framework up;
instantiates the model;
instantiates the VIEW;
and states the event loop that waits for the user to press a button on the view
"""
root = tkinter.Tk() #This starts the TK framework up;
self.model = counter.Convert() #instantiates the model
self.view = myFrame.MyFrame(self) #instantiates the VIEW
self.view.mainloop() # states event loop waits for user to press button on view
root.destroy() #lets user quit
def buttonPressed(self):
"""
Convert F --> C
"""
self.model.convertTempF2C(view.fahrenheitEntrySpace.get)
#MODEL creates new celsius temp from(fahrenheit input)
self.view.celsiusEntrySpace.pop()
#replaces VIEW's old default celsius value
self.view.celsiusEntrySpace.insert(self.model.celsius)
#and insert's MODEL's newly converted (celsius) value
"""
Convert C --> F
"""
self.model.convertTempC2F(self.celsiusEntrySpace.get)
#MODEL creates new fahrenheit temp from (celsius input)
self.view.fahrenheitEntrySpace.pop()
#replaces VIEW's old default 0 fahrenheit value
self.view.fahrenheitEntrySpace.insert(self.model.fahrenheit)
#and insert's MODEL's newly converted (fahrenheit) value
if __name__=="__main__":
c = Controller()
As continued from: Python Temperature conversion MVC style: why am I getting "TypeError: buttonPressed() missing 1 required positional argument: 'self'"
回答1:
I think NamerError
happens, because of wrong folder structure.
You should have for example
app/
|__init__.py
|counter.py
|myFrame.py
and then put all glue.py code to __init__.py
, but change imports of counter.py
and myFrame.py
. Move imports to the end of __init__.py
:
from app import myFrame
from app import counter
来源:https://stackoverflow.com/questions/25276395/python-mvc-architecture-temperature-conversion-why-am-i-getting-nameerror-glo