James C
James C

Reputation: 919

Access kivy widgets from Python code using dynamic IDs

I have a kv file with several widgets, their IDs being numbers (in string representation). Let's say it's numbers from 1 - 10.

Can I somehow access those widgets from Python with a loop by using their ID in the method call (which is an integer in string form) instead of using the ID name explicitly? For example (as illustration, it doesn't really work), I would like to use something like:

for i in range (1, 11)
    self.root.ids.str(i).text = str(i*5)

instead of:

self.root.ids.1.text = str(5)
self.root.ids.2.text = str(10)
self.root.ids.3.text = str(15)
... etc

The reason is this list of widgets can grow large. Also the ranges (slices) I want to access can vary.

Upvotes: 1

Views: 712

Answers (1)

eyllanesc
eyllanesc

Reputation: 243897

For this case you can use getattr:

test.kv

BoxLayout:
    orientation: "vertical"
    Label:
        id: 1
    Label:
        id: 2
    Label:
        id: 3
    Label:
        id: 4
    Label:
        id: 5
    Button:
        text: "press me"
        on_press: app.testFn()

main.py

from kivy.app import App

class TestApp(App):
    def testFn(self):
        for i in range(1, 6):
            getattr(self.root.ids, str(i)).text = str(5*i)

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

Or take advantage of that self.ids is a dictionary where the key is the id and the value is the widget.

from kivy.app import App

class TestApp(App):
    def testFn(self):
        for i in range(1, 6):
            self.root.ids[str(i)].text = str(5*i)

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

Note: keep in mind that the past to self.ids[] must be a string.

Update:

calculation.kv

BoxLayout:

    CustomLabel1:
        id: 1

    CustomLabel2:
        id: 2

    CustomLabel3:
        id: 3

    CustomLabel4:
        id: 4

    CustomLabel5:
        id: 5

    Button:
        text: "Calculate values"
        on_press: app.calculate_values(2,4)

<CustomLabel1@Label>:
<CustomLabel2@Label>:
<CustomLabel3@Label>:
<CustomLabel4@Label>:
<CustomLabel5@Label>:

main.py

from kivy.app import App

class TestApp(App):
    def calculate_values(self, start, end):
        for i in range(start, end):
            self.root.ids[str(i)].text = str(5*i)

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

Upvotes: 3

Related Questions