简体   繁体   中英

How to bind a widget to a value from Kivy App

I have the following Kivy app and I'm trying to change the text of a Label based on another widget's variable.

I mean, if the variable testing of the class TestApp changes, I want also the value of the variable text of the class TestLabel to change.

To do so, I've created a BooleanProperty in the TestLabel class that points to the testing variable of the TestApp class. The problem is that this callback is never executed despite being changing it each time I press the button.

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import BooleanProperty

Builder.load_string('''
<MainApp>:
    orientation: 'horizontal'
    rows: 2

    TestButton:
        text: 'Change value'
        on_release: self.change_value()
    TestLabel:
''') 


class TestLabel(Label):
    testing = BooleanProperty()

    def __init__(self, **kwargs):
        super(TestLabel, self).__init__(**kwargs)
        self.app = App.get_running_app()
        self.testing = self.app.testing
        self.bind(testing=self.changed_value)

    def changed_value(self, _instance, newvalue):
        self.text = str(newvalue)


class TestButton(Button):

    def __init__(self, **kwargs):
        super(TestButton, self).__init__(**kwargs)
        self.app = App.get_running_app()

    def change_value(self):
        self.app.testing = not self.app.testing


class MainApp(BoxLayout):
    pass


class TestApp(App):
    testing = BooleanProperty(False)

    def build(self):
        return MainApp()


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

It is not necessary to create a testing property in TestLabel since when you do: self.bind(testing = self.changed_value) you are connecting the testing of TestLabel and not the testing of TestApp , so as it never changes testing after the bind then it never gets call the callback.

The bind has to be done using the object that has that property, and in your case the testing belongs to the App, so you must the App.

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import BooleanProperty

Builder.load_string('''
<MainApp>:
    orientation: 'horizontal'
    rows: 2

    TestButton:
        text: 'Change value'
        on_release: self.change_value()
    TestLabel:
''') 


class TestLabel(Label):
    def __init__(self, **kwargs):
        super(TestLabel, self).__init__(**kwargs)
        self.app = App.get_running_app()
        self.app.bind(testing=self.changed_value)

    def changed_value(self, _instance, newvalue):
        self.text = str(newvalue)


class TestButton(Button):
    def __init__(self, **kwargs):
        super(TestButton, self).__init__(**kwargs)
        self.app = App.get_running_app()

    def change_value(self):
        self.app.testing = not self.app.testing


class MainApp(BoxLayout):
    pass


class TestApp(App):
    testing = BooleanProperty(False)
    def build(self):
        return MainApp()


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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM