Designing with the Kivy Language

The code goes in main.py

Let’s start with a little example. First, the Python file named main.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import kivy
kivy.require('1.0.5')

from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty


class Controller(FloatLayout):
    '''Create a controller that receives a custom widget from the kv lang file.

    Add an action to be called from the kv lang file.
    '''
    label_wid = ObjectProperty()
    info = StringProperty()

    def do_action(self):
        self.label_wid.text = 'My label after button press'
        self.info = 'New info text'


class ControllerApp(App):

    def build(self):
        return Controller(info='Hello world')

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

In this example, we are creating a Controller class, with 2 properties:

  • info for receving some text
  • label_wid for receving the label widget

In addition, we are creating a do_action() method, that will use both of these properties. It will change the info text, and change text in the label_wid widget.

The layout goes in controller.kv

Executing this application without a corresponding .kv file will work, but nothing will be shown on the screen. This is expected, because the Controller class has no widgets in it, it’s just a FloatLayout. We can create the UI around the Controller class in a file named controller.kv, which will be loaded when we run the ControllerApp. How this is done and what files are loaded is described in the kivy.app.App.load_kv() method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#:kivy 1.0

<Controller>:
    label_wid: my_custom_label

    BoxLayout:
        orientation: 'vertical'
        padding: 20

        Button:
            text: 'My controller info is : ' + root.info
            on_press: root.do_action()

        Label:
            id: my_custom_label
            text: 'My label before button press'

One label and one button in a vertical BoxLayout. Seems very simple. There are 3 things going on here:

  1. Using data from the Controller. As soon as the info property is changed in the controller, the expression text: 'My controller info is : ' + root.info will automatically be re-evaluated, changing the text in the Button.

  2. Giving data to the Controller. The expression id: my_custom_label is assigning the created Label the id of my_custom_label. Then, using my_custom_label in the expression label_wid: my_custom_label gives the instance of that Label widget to your Controller.

  3. Creating a custom callback in the Button using the Controller‘s on_press method.

    • root and self are reserved keywords, useable anywhere. root represents the top widget in the rule and self represents the current widget.
    • You can use any id declared in the rule the same as root and self. For example, you could do this in the on_press():
    Button:
        on_press: root.do_action(); my_custom_label.font_size = 18
    

And that’s that. Now when we run main.py, controller.kv will be loaded so that the Button and Label will show up and respond to our touch events.