Steve Hostetler
Steve Hostetler

Reputation: 356

Keyerror in Kivy Layout Language

I'm new to the kivy framework, and I don't think I am correctly understanding how id references between the kv file and the python work. When I coded this in pure python, it worked as expected, but I'm trying to learn to use the layout language. I have Dynamically generated scatter widgets, and I need to add them to a layout.

In the python.

class MainScreen(Screen):
    def on_enter(self):

        for index in xrange(numberOfWords):
                genColor = [255, 0, 0]
                shuffle(genColor)
                newWordWidget = WordWidget(genColor)
                if newWordWidget.label.color[0] == 255 and  newWordWidget.label.text != 'red': newWordWidget.trash = True
                if newWordWidget.label.color[1] == 255 and  newWordWidget.label.text != 'green': newWordWidget.trash = True
                if newWordWidget.label.color[2] == 255 and  newWordWidget.label.text != 'blue': newWordWidget.trash = True
                print("Trash:" + str(newWordWidget.trash))
                newWordWidget.scatter.pos = randint(0, Window.size[0]), randint(0, Window.size[1])
                self.ids.widgetscreen.add_widget(newWordWidget.scatter)

the kv file:

<FloatLayout>:
ScreenManagement:
    MainScreen:
<MainScreen>:
    FloatLayout:
        id: widgetscreen
        canvas:
            Color:
                rgba: 1, 1, 1, 1
            Rectangle:
                pos: self.pos
                size: self.size

I'm getting a keyerror on the line: id: widgetscreen.

Upvotes: 1

Views: 2075

Answers (2)

Kwarrtz
Kwarrtz

Reputation: 2753

The suggested way for doing element linking goes something like this.

KV:

<MainScreen>:
    widgetscreen: wdscreen
    FloatLayout:
        id : wdscreen
        ...

Python:

from kivy.properties import ObjectProperty # don't forget to add the import

class MainScreen(Screen):

    widgetscreen = ObjectProperty(None)
    ....

Let's take a look at what's happening here. First, in the Python code, we create a class attribute of MainScreen, widgetscreen, which defaults to None. Then, in our KV file, we set that attribute of MainScreen to wdscreen. In KV lang, ids work like variables, so when we set widgetscreen to wdscreen, we're actually setting it to the FloatLayout we defined with id wdscreen. At runtime, kivy will fill in our Python attribute with the appropriate widget.

With that, you should be able to access widgetscreen from within MainScreen as self.widgetscreen. You don't even need to use ids.

Upvotes: 2

Steve Hostetler
Steve Hostetler

Reputation: 356

This fixed my problem.

in the python from my original post:

from kivy.clock import mainthread

and...

class MainScreen(Screen):
    @mainthread
    def on_enter(self):

Nothing was wrong with the id reference. The issue was the kv file was loading after the id was referenced. @mainthread makes def on_enter() wait for the kv file to load.

Upvotes: 2

Related Questions