Search code examples
kivykivy-language

Arising errors in Kivy when root widget comes from an instance from .kv file


I have a simple code working perfectly, and when I change my root class in .kv file to a root instance, it stop working (something already was working).

In .kv file there are already two lines to test differences between two cases, is a matter of comment one / uncomment the other one

I've asked in Kivy forum, used builder class with no results (because I don't understand where is the difference!). As newbie in Kivy, I have very little instinctive resources right now.

main.py:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty
from kivy.clock import Clock
from colorsys import hsv_to_rgb, rgb_to_hsv
from kivy.uix.gridlayout import GridLayout

class MoneyControl(Widget):
    cartel = ObjectProperty(None)

    lay = 3
    rainbow = [0.0,1.0,1.0,1.0]

    def hsva_to_rgba(self, hsva):
        rgba = hsv_to_rgb(hsva[0], hsva[1], hsva[2])
        rgba = list(rgba)
        rgba.append(hsva[3])
        return rgba

    def update(self, dt):
        self.lay += 1
        self.cartel.text = str(self.lay)
        self.rainbow[0] += self.lay*0.0001
        finalRgba = self.hsva_to_rgba(self.rainbow)
        self.cartel.color = finalRgba


class MoneyControlApp(App):
    def build(self):
        prog = MoneyControl()
        Clock.schedule_interval(prog.update, 1.0 / 60.0)
        return prog

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

kv file:

#:kivy 1.0.9

<MoneyControl@Widget>: #This works. Comment this line...
#MoneyControl:#RootWidget instance (as appears in documentation) # ...uncomment this one. It stops working.
    cartel: crt

    Label:
        id: crt
        font_size: 20
        center_x: root.width * 0.5
        top: root.height * 0.5
        text: "hola"
        color: 1, .3, .8, 1

The expected results would be after comment the first line of .kv file and uncomment the second one the example keeps working.

The actual results is, if you change the line, kivy arises an error about a property that is clearly working in the first case (so, no error).

I would like to know why is happening this, and of course, how to fix it (Only the fix without the reason of why happens this, would lead me/us to fall again in the same error).


Solution

  • The difference between the two version of your kv file is that <MoneyControl@Widget>: is a rule for how to create a MoneyControl widget. While MoneyControl: actually creates a MoneyControl widget (that is ignored by your code). You need to change MoneyControl: to <MoneyControl>: so that you are comparing rules. Then they both work.

    The docs a bit difficult to understand, but here are some key points:

    In the kv file, <> indicates a rule. So <MoneyControl>: is a rule, and in the python code any MoneyControl() will follow that rule (including in the build() method).

    A MoneyControl: in the kv file is instruction to build one instance of the MoneyControl widget. It is not a rule. It is only a root widget if it is not a child of any other rule or widget.

    In the python code (including inside the build() method), MoneyControl() will create an instance of MoneyControl. If the kv included a rule for MoneyControl, then that rule will be followed in creating the instance. If there is no rule, then a new instance of MoneyControl is created without regard to the kv file.

    In your App, if you have a build() method, then whatever that method returns is your apps root widget. You can call MoneyControl() in that method, and if there is a rule for it in the loaded kv, then that rule be followed. Or you can return the root widget from the kv file, if you captured the returned root widget from loading the kv file (or string). For example, theRoot = Builder.load_file('somefile.kv') and return theRoot.

    If your app does not have a build() method (or the build() method returns None), then a root widget from the appropriately named kv file will becode your apps root widget.