1

I have three NumericProperteis that i wanna update every second. I tried to use Clock.schedule_interval(), becouse it similar to what i want. How can I update NumericProperteis? Can I use another event that runing in Kivy MainLoop? Or maybe I'm not changing NumericProperty correctly?

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty
from kivy.properties import StringProperty
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.clock import Clock


Builder.load_string("""
<MyLabel>
    text: "{}: {}".format(self.title, self.value)

<UpdatingLabels>
    GridLayout:
        rows: 1
        pos: 0, 0
        size: root.size
        MyLabel:
            id: lb0
            title: "value 0"
        MyLabel:
            id: lb1
            title: "value 1"
        MyLabel:
            id: lb2
            title: "value 2"
""")


class UpdatingLabels(Widget):
    pass


class MyLabel(Label):
    value = NumericProperty(0)
    title = StringProperty('')

# This not working but the same what i wanna do
# In real case i have values genereted every second
# def clock_def(dt):
#     MyLabel.ids.lb0.value += 1 # or MyLabel.ids.lb0.value = genereted_value_1
#     MyLabel.ids.lb1.value += 2
#     MyLabel.ids.lb2.value += 3

# event = Clock.schedule_interval(clock_def, 1)


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

        return UpdatingLabels()


if __name__ == '__main__':
    MyApp().run()
jfultr
  • 15
  • 4
  • check this [QA](https://stackoverflow.com/questions/474528/what-is-the-best-way-to-repeatedly-execute-a-function-every-x-seconds-in-python) – Hadi Farhadi Oct 22 '19 at 13:16

2 Answers2

2

The "ids" are attributes of the instance, not of the class, so if you want to access them, use the created object or self within the class. So you can't access ids using MyLabel.

The solution is to implement the logic within the UpdatingLabels class.

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty
from kivy.properties import StringProperty
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.clock import Clock


Builder.load_string(
    """
<MyLabel>
    text: "{}: {}".format(self.title, self.value)

<UpdatingLabels>
    GridLayout:
        rows: 1
        pos: 0, 0
        size: root.size
        MyLabel:
            id: lb0
            title: "value 0"
        MyLabel:
            id: lb1
            title: "value 1"
        MyLabel:
            id: lb2
            title: "value 2"
"""
)


class UpdatingLabels(Widget):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        event = Clock.schedule_interval(self.clock_def, 1)

    def clock_def(self, dt):
        self.ids.lb0.value += 1
        self.ids.lb1.value += 2
        self.ids.lb2.value += 3


class MyLabel(Label):
    value = NumericProperty(0)
    title = StringProperty("")


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


if __name__ == "__main__":
    MyApp().run()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
1

The solution by Eyllanesc is correct, but it's of course not the only one, an alternative if you want to keep the logic on the app, is to use the ids from the root widget.

Since your root class is UpdatingLabels and you want to update widgets inside that that have id, you can access them through app.root, which always refers to the widget that was returned by the build method.

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty
from kivy.properties import StringProperty
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.clock import Clock


Builder.load_string("""
<MyLabel>
    text: "{}: {}".format(self.title, self.value)

<UpdatingLabels>
    GridLayout:
        rows: 1
        pos: 0, 0
        size: root.size
        MyLabel:
            id: lb0
            title: "value 0"
        MyLabel:
            id: lb1
            title: "value 1"
        MyLabel:
            id: lb2
            title: "value 2"
""")


class UpdatingLabels(Widget):
    pass


class MyLabel(Label):
    value = NumericProperty(0)
    title = StringProperty('')




class MyApp(App):
    def build(self):
        Clock.schedule_interval(self.clock_def, 1)
        return UpdatingLabels()

    def clock_def(self, dt):
        self.root.ids.lb0.value += 1
        self.root.ids.lb1.value += 2
        self.root.ids.lb2.value += 3

if __name__ == '__main__':
    MyApp().run()
Tshirtman
  • 5,859
  • 1
  • 19
  • 26