UfoRobot
UfoRobot

Reputation: 120

Kivy: Self-updating label text

Let's say I have 3 classes: a "woking class" where stuff takes place, a label class and a class to contain them. For example the label class could be a status bar showing the status of something going on the working class. I wish I could find a way to make the label self-update the value to show, since this value is a value of the working class being changed inside the latter.

Here I have an example code

Builder.load_string('''
<CustomLabel>
    text: 'Value is {}'.format(root.value)

<WorkingClass>:
    orientation: 'vertical'

    Button:
        text: 'Update'
        on_release: root.update()

<MainLayout>
    orientation: 'vertical'

''')

class CustomLabel(Label):
    value = NumericProperty()

class WorkingClass(BoxLayout):

    def __init__(self, *args, **kwargs):

        super(WorkingClass, self).__init__(*args, **kwargs)

        self.a = 5

    def update(self):
        self.a += 1
        print(self.a)

class MainLayout(BoxLayout):

    def __init__(self, *args, **kwargs):

        super(MainLayout, self).__init__(*args, **kwargs)

        self.workingClass = WorkingClass()
        self.customLabel = CustomLabel(value=self.workingClass.a)

        self.add_widget(self.customLabel)
        self.add_widget(self.workingClass)





class MyApp(App):
    def build(self):
        return MainLayout()

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

Is there a way of doing it with properties or whatever? Becouse I don't want to need to manually update (sommehow) the label each time I change the value. Anyway to achieve this?

Upvotes: 0

Views: 5116

Answers (1)

kitti
kitti

Reputation: 14794

You're updating a property on WorkingClass, but that doesn't update the value on CustomLabel since you did a direct assignment instead of binding it. But yes, you can use Propertys to make everything work automatically.

In WorkingClass:

class WorkingClass(BoxLayout):
    a = NumericProperty()

    def __init__(self, **kwargs): ...

This makes a into a Property which you can bind to.

Then in MainLayout's constructor:

self.workingClass = WorkingClass()
self.customLabel = CustomLabel(value=self.workingClass.a)
self.workingClass.bind(a=self.customLabel.setter('value'))

The last line says: "when the value of property a on self.workingClass changes, set the value property of self.customLabel to the same value"

Alternatively, you could just add the Property to WorkingClass above, then get rid of MainLayout's constructor and use kv instead:

<MainLayout>:
    orientation: 'vertical'

    WorkingClass:
        id: working_class

    CustomLabel:
        value: working_class.a  # assigning one property to another in kv automatically binds

Upvotes: 2

Related Questions