Search code examples
python-3.xkivykivy-languageindexoutofrangeexceptionlistproperty

Kivy - Accessing Elements of a ListProperty in .kv file


I have started programming with Kivy, the amazing open-source GUI library in Python.

I came accross a problem close to this topic but it has no satisfying answer.

I want to access the elements of a ListProperty attached to my widget in my .kv file but I get an error. I guess it comes from a misunderstanding of the KV syntax but I cannot quite figure out what's happening.

More precisely, I get the following error:

  • Builder exception: Parser: on the line I have commented (see below .kv file)
  • IndexError: list index out of range

It is as if the builder did not understand that my custom_list has indeed 3 elements indexed from 0 to 2.

Here is the simple example I coded to illustrate the situation :

example.py file

# Kivy modules
import kivy
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.app import App
from kivy.properties import ListProperty



class MyCustomLabel(Label):
    custom_list = ListProperty()


class MainWidget(BoxLayout):

    def generate_list(self):
        l = ["Hello","Amazing","World"]
        my_custom_label = MyCustomLabel()
        my_custom_label.custom_list = l
        self.add_widget(my_custom_label)


class MyApp(App):
    pass

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

my.kv file

<MainWidget>:
    orientation: "vertical"

    Button:

        # Aspect
        text: "CLICK ME"
        size_hint_y: None
        height: dp(60)

        # Event
        on_press: root.generate_list()


<MyCustomLabel>:

    ## This is working
    ## text: "{}".format(self.custom_list)

    ## But this is not working... Why ?
    text: "{}{}{}".format(self.custom_list[0], self.custom_list[1], self.custom_list[2])

MainWidget:

Thanks in advance for those who will take the time to answer,

M


Solution

  • The problem is caused because the transition list is not complete because first before changing the list it is empty causing certain index do not exist, so one option is to verify that it is not a list or at least of a certain size, For example, there are the following 2 options:

    text: "{}{}{}".format(self.custom_list[0], self.custom_list[1], self.custom_list[2]) if self.custom_list else ""
    

    text: "{}{}{}".format(self.custom_list[0], self.custom_list[1], self.custom_list[2]) if len(self.custom_list) >= 3 else ""
    

    Or use a join that is a better option:

    text: "".join(self.custom_list)