Codementor Events

Beginner Kivy Tutorial: Basic Crash Course for Apps in Kivy

Published Jan 31, 2017Last updated Jun 10, 2018
Beginner Kivy Tutorial: Basic Crash Course for Apps in Kivy

Kivy is an open source, cross-platform Python framework for the development of applications that make use of innovative, multi-touch user interfaces.


Prerequisites

In order to work with Kivy, you must be familiar with Python.

Content

This post will cover very basic applications (absolute beginners in Kivy) in which you just add (+1) or subtract (-1) using 2 buttons and update the new value to a label. By the end of this tutorial, you will have (I hope) some good knowledge and understanding of how to work with Kivy. Here are some of the things we will cover in this post:

  • Getting started
  • App( ) method & GridLayout in detail
  • What is build method and what does it do?
  • Structuring your app
  • What are on_release and id?
  • ObjectProperty

enter image description here


Getting started.

Alrighty then, let's start with a black window that does nothing.

Create a main.py file.

from kivy.app import App
from kivy.uix.gridlayout import GridLayout


class Container(GridLayout):
    pass


class MainApp(App):

    def build(self):
        self.title = 'Awesome app!!!'
        return Container()

if __name__ == "__main__":
    app = MainApp()
    app.run()

and create a main.kv file

<Container>:
    rows: 1

Current file structure:

Basic_app/
    -  main.py
    -  main.kv

and there you have it.

enter image description here

App( ) method & GridLayout in detail

Let's pause for a second and see what we did there.

from kivy.app import App

One of the things I love about Kivy is that it is very well documented and the documentations are very easy to understand. Visit kivy/app.py for more information. Back to the question, why did we do this?

enter image description here

this is why:

if __name__ == "__main__":
    app = MainApp()
    app.run()

using App.run() we started the application's life cycle.

let's move to next line:

from kivy.uix.gridlayout import GridLayout

You can find the above at: kivy/uix/gridlayout.py

enter image description here

It requires a column or row to display a widget. How do I do that?
Once again, we can visit the documentation for instructions.

enter image description here

Here it says that rows and cols represent the number of rows and columns, respectively, in the grid, which leads us to the reason why we did this in main.kv file:

<Container>:
    rows: 1

Following alright? Let's keep going.

What is build Method and What Does it Do?

First let's go through the kivy/app.py file once again and see what the documentation says:

enter image description here

Let's do the same for the build method:

enter image description here

Now we know the reason for doing this:

class MainApp(App):

    def build(self):
        self.title = 'Awesome app!!!'
        return Container()

I hope things are clearing up a bit by now. We still have a problem though — where are the buttons and the label?
Well, let's build them.

Structuring Your App

Let's create a new folder and a buttons.kv file in the following structure:

Structure

- kv
    - buttons.kv
- main.py
- main.kv

Buttons

from kivy.uix.button import Button

class AddButton(Button):
    pass


class SubtractButton(Button):
    pass

We just created two buttons (i.e AddButton and SubtractButton) but we haven't dealt with their styles.
We can play with their style via Python but I prefer doing the styling with .kv and the logic with Python.

Let's add something to our buttons.kv file.

<AddButton>:
    text: "+1"

<SubtractButton>:
    text: "-1"

Before we add something to the container class (GridLayout), we first need to tell Kivy to read from the buttons.kv file in the kv folder.

This is where builder comes in.

from kivy.lang import Builder

enter image description here

A simple but inefficient way to work with big projects is to load each .kv file individually.

Builder.load_file('./kv/buttons.kv')

We can automate this:

from os import listdir 
kv_path = './kv/'
for kv in listdir(kv_path):
    Builder.load_file(kv_path+kv)

Add as many .kv file in the kv folder and they will automatically be loaded by Builder 😉

So here we are — we have defined the buttons and the container; however, there is still nothing on the screen.
Let's proceed to add the buttons (finally)

Edit the main.kv file.

<Container>:
    display: display
    rows: 1
    BoxLayout:
        orientation: "vertical"
        AddButton:
            on_release: root.add_one()
        SubtractButton:
            on_release: root.subtract_one()
    Label:
        id: display
        font_size: dp(50)
        text: '0'

wait...we have one more problem...

What are on_release and id?

on_release and on_press are special methods that are part of the button behaviour (see kivy/uix/behaviors/button) whereas id is a property of every widget (see kivy/uix/widget.py).

enter image description here

Before we move ahead, spend some time on understanding "properties" in Kivy. Here are some resources to help clear things up:
Docs, stackoverflow, and kivy-wiki.

enter image description here

ObjectProperty

The following id will be used for ObjectProperty to communicate with Python side.

class Container(GridLayout):
    display = ObjectProperty()

    def add_one(self):
        value = int(self.display.text)
        self.display.text = str(value+1)

    def subtract_one(self):
        value = int(self.display.text)
        self.display.text = str(value-1)

Now we should have our final working app.

You can download the final working app from github.

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
from kivy.uix.gridlayout import GridLayout


from os import listdir
kv_path = './kv/'
for kv in listdir(kv_path):
    Builder.load_file(kv_path+kv)


class AddButton(Button):
    pass


class SubtractButton(Button):
    pass


class Container(GridLayout):
    display = ObjectProperty()

    def add_one(self):
        value = int(self.display.text)
        self.display.text = str(value+1)

    def subtract_one(self):
        value = int(self.display.text)
        self.display.text = str(value-1)


class MainApp(App):
    def build(self):
        self.title = 'Awesome app!!!'
        return Container()


if __name__ == "__main__":
    app = MainApp()
    app.run()

main.kv

<Container>:
    display: display
    rows: 1
    BoxLayout:
        orientation: "vertical"
        AddButton:
            on_release: root.add_one()
        SubtractButton:
            on_release: root.subtract_one()
    Label:
        id: display
        font_size: dp(50)
        text: '0'

kv/buttons.kv

<AddButton>:
    text: "+1"
    font_size: 50

<SubtractButton>:
    text: "-1"
    font_size: 50

Conclusion

Thank you for reading this post — I hope you found this helpful. You can find me on GitHub, LinkedIn and CodeMentor. If you have any questions, feel free to reach out to me!
More posts:

Discover and read more posts from Kuldeep
get started
post comments12Replies
Kaitain Jones
6 years ago

Where is the code that loads main.kv into builder? I had to add that into my code manually:

Builder.load_file(“main.kv”)

However, I was adding this stuff to a file that was NOT called main.py. Is that what made the difference? If you have main.py, does the system somehow know automagically to look for a corresponding main.kv file?

Without the line I added, my app just created a blank window with no buttons.

Vivek Singh
6 years ago

I copy pasted all the three files, but I see one row and 4 columns.

First column contains the two buttons (+1 and -1), second column contains display label, third and fourth columns are same as first and second columns respectively. I’m using Kivy 1.10.1. What could be the reason behind this?

Darien Schettler
6 years ago

Could you offer further clarification on what the display: display line does and how it works with id?

Great tutorial!

Thanks!

Kuldeep
6 years ago

Display is an object property which holds the reference of a widget. In this case the Label. In the class Container (Python side) I have defined display = ObjectProperty(). which provides a reference to the widget defined at the kivy side. Label: id: display

Show more replies