Python的温度转换MVC风格:为什么我收到“类型错误:buttonPressed()失踪1个人需

2019-11-03 06:54发布

新手,想,这里的Python程序员。 我有一个家庭作业(即我无法获得),和现在的下课,我感觉很舒服寻求帮助这里。 我还是很好奇这个错误,我在做什么错?我敢肯定,这涉及到如何在控制器和视图都称呼对方,但我这个错误是我无法理解。 我一直停留在这个约三天。 我真的可以使用帮助 - 因为我真的想了解Python和MVC。

请参阅下面的背景下屏幕帽。

错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python33\lib\tkinter\__init__.py", line 1482, in __call__
    return self.func(*args)
TypeError: buttonPressed() missing 1 required positional argument: 'self'

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 = glue.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")  
        self.fahrenheitEntrySpace.pack({"side":"left"})

#Fahrenheit Value label
        self.fahrenheitLabel = tkinter.Label(self)
        self.fahrenheitLabel["text"] = ("Fahrenheit Degrees")
        self.fahrenheitLabel.pack({"side":"left"})

#Converter button 
        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")
        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()

MODEL:counter.py

import tkinter


class Convert: #the MODEL

    '''
    class counter is the MODEL for a simple program that exemplifies
    the MODEL/VIEW/CONTROLLER architecture.

    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 = fahrenheitEntrySpace.get()
        if fahrenheit != 0.0:
            celsius = (fahrenheit - 32) * 5 / 9
        else:
            celsius = -17.7777778 

    def convertTempC2F(self):
        celsius = celsiusEntrySpace.get()
        if celsius != 0.0:
            fahrenheit = (celsius *  9.0/5.0 + 32)          
        else:
            fahrenheit = 32

    def __str__(self):
        return str(self.counter)

控制器: “glue.py”

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(self.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.view.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()

屏幕帽

http://imgur.com/pAQc3Zw < -链接到屏幕帽(我不能发布的w / o 10的声誉。

编辑:固定自我裁判圈之后,我遇到了其他一些问题在这里看到: Python的MVC架构温度转换:为什么我会得到“NameError:全局名称‘视图’没有定义”

Answer 1:

MyFrame.__init__ ,你保存到一个参考Controller类:

self.controller = glue.Controller

但是你没有实际创建的实例Controller ,这意味着Controller.__init__永远不会被调用。 这可能不是你的意思做。

这也意味着,当你这样做:

    self.convertButton["command"]=self.controller.buttonPressed

你真正的意思

    self.convertButton["command"]= glue.Controller.buttonPressed

这意味着你正在做一个不受约束的方法回调的convertButton 。 未绑定意味着该方法不绑定到特定实例Controller ,这意味着self不会隐式地传递给它-因此你得到的错误。 您的程序创建一个Controller启动时的实例,那就是什么叫MyFrame.__init__ 。 你实际上是做正确的事的方式99% -你传递的Controller实例MyFrame.__init__

    self.view = myFrame.MyFrame(self) #instantiates the VIEW

所以,现在你需要做的就是分配一个实例self.controller控制器。 初始化 `:

def __init__(self, controller):
    """
    places the controls on the frame
    """
    tkinter.Frame.__init__(self)
    self.pack()
    self.controller = controller  # NOT glue.Controller


文章来源: Python Temperature conversion MVC style: why am I getting “TypeError: buttonPressed() missing 1 required positional argument: 'self'”