pythondynamiclabelkivykivy-language

How to update the text attribute of Kivy Label dynamically using bind


My question is simple and straight forward. I am trying to dynamically update a widget's attribute using bind function in Kivy. Is it possible? And how?

Overview:

The following snippet is a basic Kivy app that adds a Label widget with some text to the screen. It works! But if I wanted to use bind to change the text dynamically (as you can see with the commented line), I get the following error message:

AssertionError: 'Updated Text' is not callable

from kivy.app import App
from kivy.uix.label import Label


class TestApp(App):
    def build(self):
        my_label = Label(text='Initial Text')
        # my_label.bind(text='Updated Text')
        return my_label


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

PS: I've seen all related questions and done lots of research online, including using callbacks that are callable to attributes (i.e. on_press, on_press etc). However, I couldn't find an answer for my specific question. I am hoping someone will guide me to the right answer and maybe touch on how Kivy/Python deal with dynamic widget modification since I am still new to them.

Thank you


Solution

  • You just set the text attribute to whatever you want. For example,

    my_label.text='new text'
    

    but that will only work in the build method because my_label is local to that method. Elsewhere, you will need to have a reference to the Label instance. Since, in your example, the Label is the root of the TestApp display, you can change the text using

    App.get_running_app().root.text='new text'
    

    or if you do it in a method of TestApp, it could be

    self.root.text='new text'

    You can also use binding, typically by creating a StringProperty and binding to that property. The bound method would be code that sets the text attribute of the Label to the changed StringProperty. This can all be done in Python, but is more often (and more easily) done in a kv file:

    ScreenManager:
        myText: 'Abba'
        Screen:
            name: 'the_screen'
            Label:
                text: root.myText
    

    The myText: 'Abba' line creates a StringProperty in the ScreenManager. The text: root.myText line sets the initial Label text to "Abba", and arranges the above mentioned binding for you. So anytime the myText property of ScreenManager is changed, the Label text will automatically be updated to the changed StringProperty.