【问题标题】:How to pass properties from one class to another in kivy如何在kivy中将属性从一个类传递到另一个类
【发布时间】:2014-11-16 06:37:03
【问题描述】:

在我的应用程序中,我有多个屏幕。每个屏幕对应一个类。现在我想在另一个屏幕上显示在某个类(屏幕)中计算的属性。以下是概述我的问题的简化示例。在 WordComprehension 类中,每次按下按钮时,NumericProperty count_r 都会递增。现在,我想在 ScoreScreen 中显示这个计算的结果。感谢您的建议。 这是.py:

import kivy
from kivy.app import App

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.button import Button

from kivy.properties import ObjectProperty
from kivy.properties import NumericProperty


class AppScreen(FloatLayout):
    app = ObjectProperty(None)

class MainMenu(AppScreen):
    pass

class ScoreScreen(AppScreen):

    score = NumericProperty(0)
    def get_score(self):
        wordcomp = WordComprehension()
        self.score = wordcomp.count_r


class WordComprehension(AppScreen):
    count_r = NumericProperty(0)
    count_w = NumericProperty(0)

    def do_something(self):
        self.count_r += 1


class InterfaceApp(App):
    def build(self):
        self.screens = {}
        self.screens["wordcomp"] = WordComprehension(app=self)
        self.screens["menu"] = MainMenu(app=self)
        self.screens["score"] = ScoreScreen(app=self)
        self.root = FloatLayout()
        self.goto_screen("menu")
        return self.root

    def goto_screen(self, screen_name):
        self.root.clear_widgets()
        self.root.add_widget(self.screens[screen_name])


if __name__ == "__main__":
    InterfaceApp().run()

和.kv:

#:kivy 1.8.0

<MainMenu>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: "Choose Category"
            font_size: 30 
        Button:
            text: 'Word Comprehension'
            on_press: root.app.goto_screen("wordcomp")
        Button:
            text: 'Highscore'
            on_press: root.app.goto_screen("score")
            disabled: False

<ScoreScreen>:
    BoxLayout:
        orientation: 'vertical'
        Button:
            text: 'get score'
            on_press: root.get_score()
        Label:
            text: "Word Comprehension right answers:" + str(root.score)
        Button:
            text: 'Main Menu'
            on_release: root.app.goto_screen("menu")


<WordComprehension>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: str(root.count_r)
        Button:
            text: 'Do something'
            on_release: root.do_something()
        Button:
            text: 'Menu'
            on_press: root.app.goto_screen("menu")

【问题讨论】:

    标签: python properties kivy


    【解决方案1】:

    您可以将 kivy 属性相互绑定,这样当一个更改时,另一个也会更改。为此,您绑定到类的 setter() 函数。 (http://kivy.org/docs/api-kivy.event.html)

    这是你需要做的:

    1) 在 ScoreScreen 中为 count_r 创建一个 NumericProperty。 2) 将 WordComprehension 中的 count_r NumericProperty 绑定到 ScoreScreen 中的 NumericProperty,如下所示: '''in class WordComprehension ''' self.bind(count_r=self.score_screen.setter('count_r')

    现在的诀窍是您需要在 WordComprehension 类中引用 ScoreScreen 实例。在我的示例中,我假设您在 self.score_screen 中有对它的引用。我将由您决定如何分配该引用。

    现在,每当 WordComprehension 中的 count_r 发生变化时,就会在 ScoreScreen 的“count_r”属性上调用 setter 函数(本质上是一个 setattr())。

    另一件事:get_score() 中的 wordcomp = WordComprehension() 行没有引用您想要的同一个 WordComprehension 实例。您正在创建一个 WordComprehension 类的新对象并引用它的 count_r 这将是它的默认值。

    EDIT1 不确定这是否是您想要的,但只要更改 count_r 属性,此代码就会更新 score 属性:

    import kivy
    from kivy.app import App
    
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.label import Label
    from kivy.uix.button import Button
    
    from kivy.properties import ObjectProperty
    from kivy.properties import NumericProperty
    
    
    class AppScreen(FloatLayout):
        app = ObjectProperty(None)
    
    class MainMenu(AppScreen):
        pass
    
    class ScoreScreen(AppScreen):
        count_r = NumericProperty(0)
        score = NumericProperty(0)
    
        # This is making a new WordComprehension object, and thus will not have
        # the correct value of score. We no longer need this is we are binding properties
        # together.
        #def get_score(self):
        #    wordcomp = WordComprehension()
        #    self.score = wordcomp.count_r
    
    
    class WordComprehension(AppScreen):
        count_r = NumericProperty(0)
        count_w = NumericProperty(0)
    
        def do_something(self):
            self.count_r += 1
    
    
    class InterfaceApp(App):
        def build(self):
            self.screens = {}
            self.screens["wordcomp"] = WordComprehension(app=self)
            self.screens["menu"] = MainMenu(app=self)
            self.screens["score"] = ScoreScreen(app=self)
            self.root = FloatLayout()
            self.goto_screen("menu")
    
            # Bind the two properties together. Whenever count_r changes in the wordcomp
            # screen, the score property in the score screen will reflect those changes.
            self.screens["wordcomp"].bind(count_r=self.screens["score"].setter('score'))
    
            return self.root
    
        def goto_screen(self, screen_name):
            self.root.clear_widgets()
            self.root.add_widget(self.screens[screen_name])
    
    
    if __name__ == "__main__":
        InterfaceApp().run()
    

    【讨论】:

    • 非常感谢您的回复。我仍然不太确定如何将您的改进集成到代码中。抱歉,我对 Python 和 Kivy 完全陌生。您能否发布一个完整的代码,包括您的更改?
    • 这正是我想要的。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 2012-01-01
    • 1970-01-01
    相关资源
    最近更新 更多