1
Write a post

Beginner Kivy Tutorial: Basic Crash Course for Apps in Kivy

Published Jan 31, 2017
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 post helpful. My online existence is mainly here at Codementor. You can also find me on GitHub and LinkedIn. If you have any questions, feel free to reach out to me!

Discover and read more posts from Kuldeep
get started
Enjoy this post?

Leave a like and comment for Kuldeep

8
4
4Replies
James Cannon
2 days ago

Great tutorial I was trying this in Qpython but I could not get the grid to load. Are you familiar with Qpython?

Kuldeep
2 days ago

Thanks @James
Nope, Haven’t worked with Qpython yet.

Ganesh
22 days ago

A lucid introductory blog. Thanks

Kuldeep
20 days ago

I’m glad you like it.

Show more replies

Get curated posts in your inbox

Learn programming by reading more posts like this