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
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.
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?
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
It requires a column or row to display a widget. How do I do that?
Once again, we can visit the documentation for instructions.
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.
build
Method and What Does it Do?
What is First let's go through the kivy/app.py file
once again and see what the documentation says:
Let's do the same for the build method:
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
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...
on_release
and id
?
What are 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).
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.
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:
- Customizing your Navigation Drawer in Kivy & KivyMD
- Plyer: Platform independent compatibility layer
- Texture management in Kivy using atlas
- Beginner Kivy Tutorial: Basic Crash Course for Apps in Kivy
- Redux, Store, Actions, Reducers and logger: Get Started and a little further (1)
- Redux, Reactotron, Actions, Reducers and Sagas (2)
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.
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?
Could you offer further clarification on what the display: display line does and how it works with id?
Great tutorial!
Thanks!
Display
is an object property which holds the reference of a widget. In this case theLabel
. In the class Container (Python side) I have defineddisplay = ObjectProperty()
. which provides a reference to the widget defined at the kivy side.Label: id: display