Python温度转换MVC样式:为什么我得到"TypeError:buttonPressed()缺少1个必需的位置参数:'self''"的信息? [英] Python Temperature conversion MVC style: why am I getting "TypeError: buttonPressed() missing 1 required positional argument: 'self'"

查看:124
本文介绍了Python温度转换MVC样式:为什么我得到"TypeError:buttonPressed()缺少1个必需的位置参数:'self''"的信息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

新手想在这里成为python程序员.我完成了一项家庭作业(无法完成),现在课程结束了,我很乐意在这里寻求帮助.我仍然对这个错误以及我在做什么错感到非常好奇...我确定这与CONTROLLER和VIEW如何相互引用有关,但是我这个错误超出了我的理解.我已经坚持了大约三天.我真的可以使用帮助-因为我真的想了解python和MVC.

newbie-wanna-be python-programmer here. I had a homework assignment (that I couldn't get) and now that the class is over, I feel comfortable asking for help here. I'm still really curious about this error and what I'm doing wrong... I'm sure it's related to how the CONTROLLER and the VIEW are referring to each other, but I this error is beyond my understanding. I've been stuck on this for about three days. I could really use help- because I really want to understand python and MVC.

有关上下文,请参见下面的屏幕截图.

Please see screen cap below for context.

错误:

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'

查看:myFrame.py

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

型号:counter.py

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"

CONTROLLER: "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 <-链接到屏幕截图(我可以不会发布10点声望.

screen cap

http://imgur.com/pAQc3Zw <-- link to screen cap (I can't post w/o 10 reputation.

修复self ref循环后,我遇到了其他问题,如下所示: Python MVC体系结构温度转换:为什么我要" NameError:未定义全局名称视图""

After fixing the self ref loop, I ran into other issues as seen here: Python MVC architecture Temperature Conversion: Why am I getting "NameError: global name 'view' is not defined"

推荐答案

MyFrame.__init__中,您正在保存对Controller类的引用:

In MyFrame.__init__, you're saving a reference to the Controller class:

self.controller = glue.Controller

但是您实际上并不是在创建Controller的实例,这意味着永远不会调用Controller.__init__.那可能不是你的本意.

But you're not actually creating an instance of Controller, which means Controller.__init__ is never called. That's probably not what you meant to do.

这也意味着您执行以下操作:

It also means that when you do this:

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

你是真的在说

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

这意味着您要使 unbound 方法成为convertButton的回调. Unbound表示该方法未绑定到Controller的特定实例,这意味着self不会隐式传递给它-因此会出现错误.您的程序在启动时正在创建一个Controller实例,这就是所谓的MyFrame.__init__.实际上,您已经99%地正确地完成了工作-您正在将Controller实例传递给MyFrame.__init__:

Which means you're making an unbound method the callback for convertButton. Unbound means that the method isn't bound to a particular instance of Controller, which means self won't implicitly be passed to it - hence the error you're getting. Your program is creating a Controller instance when it starts, and that is what's calling MyFrame.__init__. You're actually 99% of the way to do things properly - you're passing the Controller instance to MyFrame.__init__:

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

所以现在您要做的就是将该实例分配给self.controller Controller. init `:

So now all you need to do is assign that instance to self.controllerController.init`:

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

这篇关于Python温度转换MVC样式:为什么我得到"TypeError:buttonPressed()缺少1个必需的位置参数:'self''"的信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆