从现有实例调用方法

时间:2014-06-02 12:09:34

标签: android python python-2.7 kivy

我对面向对象编程的理解有点不稳定,所以如果你有任何有助于解释这些概念的链接,那么看它们会很棒!

我稍微缩短了代码。基本原则是我有一个以Controller主类实例开头的游戏。打开游戏时,将打开Popup类。事件发生如下:

  1. 点击弹出窗口上的开始按钮
  2. 方法start_click()运行
  3. 调用Controller实例中的方法start_game()
  4. 反过来又将原始Controller实例中的游戏状态更改为“True”
  5. 我的问题在于第3步。我得到的错误信息是:

    TypeError: unbound method start_game() must be called with Controller 
    instance as first argument (got nothing instead)
    

    我想在StartPopUp类中需要对Controller类进行一些引用。但我不太明白如何创建该引用?

    import kivy
    kivy.require('1.8.0')
    
    from kivy.app import App
    from kivy.uix.widget import Widget
    from kivy.clock import Clock
    from kivy.properties import BooleanProperty, NumericProperty, ObjectProperty
    from kivy.uix.popup import Popup
    from kivy.lang import Builder
    
    Builder.load_string('''
    <StartPopUp>            
        size_hint: .2, .2
        auto_dismiss: False
        title: 'Welcome'
        Button:
            text: 'Play'
            on_press: root.start_click()
            on_press: root.dismiss()
    
    ''')
    
    class StartPopUp(Popup):
    
        def __init__(self, **kw):
            super(StartPopUp, self).__init__(**kw)
    
        def start_click(self):
            Controller.start_game()                    
    
    class Controller(Widget):
        playing_label = BooleanProperty(False)          #Intitial phase of game is off
    
        def __init__(self, **kw):
            super(Controller, self).__init__(**kw)        
    
        def start_popup(self, dt):    
            sp = StartPopUp()
            sp.open()
    
        def start_game(self):
            self.playing_label = True
            print self.playing_label   
    
    class MoleHuntApp(App):
    
        def build(self):
            game = Controller()
            Clock.schedule_once(game.start_popup, 1)
            return game
    
    if __name__ == '__main__':
        MoleHuntApp().run() 
    

    提前致谢!

4 个答案:

答案 0 :(得分:2)

您可以像这样传递实例

class StartPopUp(Popup):

    def __init__(self, controller, **kw):
        super(StartPopUp, self).__init__(**kw)
        self.controller = controller

    def start_click(self):
        self.controller.start_game()

和控制器

def start_popup(self, dt):    
    sp = StartPopUp(self)
    sp.open()

答案 1 :(得分:1)

您需要在start_game()课程的实例上调用Controller。例如,

def start_click(self):
    controller = Controller()
    controller.start_game()

这样,startgame()的{​​{1}}参数将指向self对象。但是,您需要跟踪创建的controller实例,以便以后能够再次修改它。在这种情况下,没有理由将Controller作为静态变量。

你可能想要的是一个静态方法,可以在不必拥有playing_label类的实例的情况下调用它。为此,您可以使用staticmethod decorator使Controller成为静态方法,如下所示:

start_game()

然后,您可以继续使用@staticmethod def start_game(): Controller.playing_label = True print Controller.playing_label

答案 2 :(得分:1)

从错误消息中可以明显看出,必须为控制器类的特定实例调用方法start_game()。您可以为控制器类添加getInstance()方法,该方法返回控制器的当前活动实例。在调用start_click()之前,从start_game()方法中调用此方法。假设它返回instanceC。然后,您可以start_game()instanceC.start_game()方法称为start_click()

答案 3 :(得分:1)

尝试在创建StartPopUp对象时传递游戏对象并使StartPopUp保持对它的引用,以便稍后可以将此实例用于start_click()方法,如下所示:

class StartPopUp(Popup):

    def __init__(self, game_ctrl, **kw):
        super(StartPopUp, self).__init__(**kw)
        self.game_ctrl = game_ctrl

    def start_click(self):
        self.game_ctrl.start_game()                    

class Controller(Widget):
    playing_label = BooleanProperty(False)          #Intitial phase of game is off

    def __init__(self, **kw):
        super(Controller, self).__init__(**kw)        

    def start_popup(self, dt):    
        sp = StartPopUp(self)
        sp.open()

    def start_game(self):
        self.playing_label = True
        print self.playing_label