【问题标题】:How to call a function within an instance? Python & Kivy如何在实例中调用函数?蟒蛇和基维
【发布时间】:2014-02-14 08:36:36
【问题描述】:

下午好,感谢您的任何见解......再次!

如何在实例中从def changetxt 调用def clearwidgets,如果我使用self.parent.clearwidgets,我收到锚布局不支持这个,这是正确的,因为最终父实例被命名为rootGameApp? 哪个是父级之上的父级。如果这有意义的话。

我想要实现的就像是一个屏幕管理器/控制器,可以从一种布局切换到另一种布局:开始菜单、主游戏区域、结束游戏、积分等。

我在 Github 上查看了演示游戏的 Kivy 源代码,但它们只是直接进入游戏区域,没有启动画面等。

我什至尝试在导入下添加root=anchorlayout 并在changetxt() 中使用全局root,但收到错误全局未找到。

再次感谢和赞赏

import kivy


from kivy.app import App
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.lang import Builder




class launchScreenMenu(FloatLayout):
    def __init__(self, **kwargs):
        super(launchScreenMenu, self).__init__(**kwargs)

        menuanchor = AnchorLayout(anchor_x='left',anchor_y='bottom')
        menu = StackLayout(orientation='bt-lr',size_hint=(0.5,1))
        about_btn = Button(text='About',size_hint=(0.3,0.1))
        help_btn = Button(text='Settings',size_hint=(0.3,0.1))
        settings_btn = Button(text='Help',size_hint=(0.3,0.1))

        menu.add_widget(about_btn)
        menu.add_widget(help_btn)
        menu.add_widget(settings_btn)
        menuanchor.add_widget(menu)
        return self.add_widget(menuanchor)

class launchScreenBtn(AnchorLayout):
    def __init__(self, **kwargs):
        super(launchScreenBtn, self).__init__(**kwargs)
        play_btn = Button(text="Play")
        self.anchor_x = 'center'
        self.anchor_y = 'center'
        self.size_hint = 0.2,0.2
        self.add_widget(play_btn)
        play_btn.bind(on_press=self.changetxt)


    def changetxt(self,play_btn):
        play_btn.text = 'Game Over'
        clearwidgets()

class GameApp(App):
    def build(self):
        root = AnchorLayout()
        root.add_widget(launchScreenMenu())
        root.add_widget(launchScreenBtn())

        return root

    def clearwidgets(self):
        root.clear_widgets()



if __name__=='__main__':
    GameApp().run()

【问题讨论】:

    标签: python class kivy instances


    【解决方案1】:

    面向对象编程(以及一般编程)的一个基本理念是,您需要保留对您想要使用的对象的引用。

    例如,在您的GameApp.build 方法中,您正在创建一个AnchorLayout 对象,将其分配给root 局部变量,然后通过该局部变量将小部件添加到它。

    您的问题似乎是,“在build 方法完成运行之后,我如何继续向该对象发出命令?”我注意到有人尝试在clearWidgets 方法中调用root.clear_widgets(),这当然不起作用,因为root 是一个 local 变量——它在方法之外不存在它被用于。

    这就是对象属性的用武之地。看,对象是可以在程序中传递的状态块。您可以为您创建的任何对象添加更多状态。例如,在您的launchScreenBtn 类的__init__ 方法中,您正在设置正在创建的实例的anchor_xanchor_ysize_hint 属性。只要您引用了launchScreenBtn 实例,就可以访问这些属性(例如my_lsbtn.anchor_x),无论您是否在函数/方法中。

    所以你想做的就是更多地利用这种机制。在您的 GameApp.build 方法中,您不想将 root 设为局部变量:您希望将其设为属性 (self.root = AnchorLayout())。这样,在您的 clearwidgets 方法中,您可以访问它,调用 self.root.clear_widgets()

    在您的应用程序的其余部分应用类似的原则:每当您想要继续操作的东西您已经退出它定义的方法之后,这是您想要实现它的标志一个属性。

    当您学习它时,您应该阅读一些有关面向对象编程的教程,因为看起来您对它的掌握是不稳定的。从 Python 教程中关于类的部分开始:http://docs.python.org/2/tutorial/classes.html

    【讨论】:

    • 谢谢你 :) ,给它一个 bash,我完全同意你的看法,我真的很难理解 oop 和类,我认为今天另一个主题添加了相同的参考,所以会继续阅读今晚。再次感谢您的帮助:)
    • 谢谢,我发现你的解释和 Ryan G 的例子混合在一起,加上在 changetxt 函数中添加 app = App.get_running_app() app.clearwidgets() 让它工作了,但我会去的回到基础,我可以尝试重构代码。干杯
    【解决方案2】:

    当您为和launchScreenBtn() 添加小部件时,您可以修改类以接受self 的GameApp 实例吗?

    class launchScreenBtn(AnchorLayout):
        def __init__(self, mainApp,**kwargs):
            super(launchScreenBtn, self).__init__(**kwargs)
            self.mainApp = mainApp # Local variable to reference parent
            self.play_btn = Button(text="Play")
            self.anchor_x = 'center'
            self.anchor_y = 'center'
            self.size_hint = 0.2,0.2
            self.add_widget(play_btn)
            self.play_btn.bind(on_press=self.changetxt)
    
    
        def changetxt(self,play_btn):
            self.play_btn.text = 'Game Over'
            self.mainApp.clearwidgets()
    
    class GameApp(App):
        def build(self):
            self.root = AnchorLayout()
            self.root.add_widget(launchScreenMenu())
            self.root.add_widget(launchScreenBtn(self)) # Add GameApp reference self to Btn Class
    
            return self.root
    
        def clearwidgets(self):
            self.root.clear_widgets()
    

    这通常是我在 wxPython 中处理此类事情的方式,我相信它也应该在这里工作。

    【讨论】:

    • 您需要将root 作为一个属性,而不仅仅是一个局部变量,正如@Max Noel 所指出的那样。
    • 正确。重新查看代码后,这些方法需要一些工作,因为 clearwidgets 不知道 root 是什么,除非它在 ​​build 方法中实例化为 self.root 并在 clear 小部件中引用为 self.root。 “如有疑问,请添加自我。”
    • 嘿,正如上面的评论 :),这似乎工作 app = App.get_running_app() app.clearwidgets(),以及你的代码和最大 noels 解释的混合
    猜你喜欢
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 1970-01-01
    • 2022-11-06
    • 1970-01-01
    • 2010-10-19
    相关资源
    最近更新 更多