如何在kivy中将属性从一个类传递到另一个类

时间:2014-09-22 10:16:02

标签: python properties kivy

在我的应用程序中,我有多个屏幕。每个屏幕对应一个类。现在我想显示在另一个屏幕上的某个类(屏幕)中计算的属性。下面是一个简化示例来概述我的问题。在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")

1 个答案:

答案 0 :(得分:4)

您可以将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,就会在&count;&_ 39;上调用setter函数(实际上是setattr())。 ScoreScreen的财产。

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

EDIT1不确定这是否是你想要的,但只要count_r属性发生变化,这段代码就会更新得分属性:

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