Creating an Application in Kivy: Part 1

This is the first in what I expect to be a series of tutorials on creating user interfaces in Kivy. Kivy is a cross platform user interface framework that allows us to write applications in Python that run on various desktop operating systems, Android, and IOS.

I’ve wanted to write a tutorial on Kivy since hacking on Python 3 support during the dev sprints at Pycon 2013. My goal is to create a useful application that runs on multiple devices and highlights use of the KV Language to design user interfaces. I also want this multi-part series to describe end-to-end how to develop, maintain, and deploy a Kivy application. I intend it to be a model for newcomers to Kivy and even Python to develop their own cross platform or mobile applications in Python. Thus, it doesn’t just include code, but also deployment instructions and information on how to use the git version control system for basic history management.

Therefore, this tutorial series is written at a more basic level than a lot of my technical articles. My intended audience is new programmers who have some basic Python experience; perhaps having read The Python Tutorial and Learn Python The Hard Way, but possibly not the beginner-intermediate topics covered in my book, Python 3 Object Oriented Programming.

Having decided to write a tutorial, I needed to decide what kind of application to develop. This actually took quite a bit of thought. I decided on a Jabber client, as it has a user interface with reasonable complexity, and I am hoping that most of the difficult bits can be abstracted away into the SleekXMPP library. Finally, I had to settle on a name for the app; I chose Orkiv. I do not know why.

Table Of Contents

A blog isn’t the best platform for publishing a multi-part tutorial. I’ll include a Table Of Contents section in each part with references to all the other parts. Hopefully I’ll even keep it up to date!

  1. Part 1: Introduction to Kivy
  2. Part 2: Creating a Form
  3. Part 3: Handling Events
  4. Part 4: Code and Interface Improvements
  5. Part 5: Rendering a Buddy List
  6. Part 6: ListView Interaction
  7. Part 7: Receiving messages and interface fixes
  8. Part 8: Width based layout
  9. Part 9: Deploying your Kivy application

Prerequisites

Start by installing the following pre-requisites using standard operating system tools.

Python is the programming language and interpreter that Kivy programs are written in. Git is a version control system that we will use to track changes to our code. Virtualenv is a tool for creating isolated Python environments. Pip is an installer for installing python packages, in this case into the isolated virtualenv.

Note: Use of git is optional if you are more interested in learning to code than learning to manage a project. You are also welcome to use another version control system of your choice. At the level we will be working, the commands are virtually interchangeable.

Setting up the environment

Run the following commands in a terminal. (Note this tutorial was written using Arch Linux, and will probably work flawlessly on MacOS and other Linux distributions. However, you may need to do some experimenting to make Windows cooperate).

mkdir orkiv
cd orkiv
git init
virtualenv -p python2.7 venv
echo venv >> .gitignore
echo "*.pyc" >> .gitignore
git add .gitignore
git commit -m "Create .gitignore file. Ignores compiled python files and venv."
source venv/bin/activate

We’re creating a directory to hold our project and then initialize a git repository in there. We next create a virtualenv in a folder named venv. This folder will hold the isolated python files so that you can interact with Kivy without adding cruft to your system Python. I highly recommend creating a separate virtualenv for every project you work on.

Next, we set up a .gitignore file that tells git not to track certain files in our repository; in this instance all compiled python files, which end in .pyc, and the virtualenv directory we just created. We commit the changes to this file as our first commit in the git repository.

Finally, we “turn on” the virtualenv by sourcing its activate script. This essentially tells our shell to “use the isolated python for this project instead of system python”. When you are done working on this project, you should enter the command deactivate. When you come back to the project in the future, reenter the source venv/bin/activate command to turn on the isolated environment.

Note: If you maintain a lot of virtualenvs in a lot of different projects, as I do, you may be interested in a small script I wrote to facilitate switching between them.

Kivy Dependencies

Kivy depends on several Python libraries. Unfortunately, it does not have a setuptools-enabled setup.py to automatically install these dependencies into our virtualenv, so we have to do a little work ourselves. This takes a while, but if you copy paste these commands into your terminal, you should get lucky.

pip install cython
pip install pygame

Sadly, on Arch Linux, the last command, for pygame fails. I suspect it works fine on less bleeding edge operating systems, however, if you encounter an error about linux/videodev.h not existing, applying the Arch Linux patch to pygame may get you to the next step.

wget http://www.pygame.org/ftp/pygame-1.9.1release.tar.gz
wget https://projects.archlinux.org/svntogit/packages.git/plain/trunk/pygame-v4l.patch?h=packages/python-pygame -O pygame-v4l.patch
tar xf pygame-1.9.1release.tar.gz
cd pygame-1.9.1release/
patch -Np1 -i ../pygame-v4l.patch
python setup.py install
cd ..
rm pygame* -r

And now, you should finally be ready to install Kivy itself: This will take a while, so grab a smoothie while it runs:

pip install kivy
python -c 'import kivy'

The latter command should output the kivy version (I’m working with 1.7.1). If it exits without failure, then you have successfully installed Kivy!

Now let’s create a basic Kivy app

Create a directory to hold the application code:

mkdir orkiv

This directory will contain your Python and Kivy source files. Our goal is to be able to always create a zipfile from this directory and be able to run it using python orkiv.zip. As long as the required dependencies are installed on the target system (as described above), the program should run. It will therefore be nice and self-contained.

There is a relatively unknown feature of recent versions of Python to support this. If a directory or zipfile contains a __main__.py, that module will be executed if python is called with that directory or zipfile as an argument. First, create a file inside the new orkiv directory named __main__.py. Create a simple “hello world” in this file to test that
it’s working:

(commit)

print("hello world!")

Now from the parent directory, run the command python orkiv. If you want to test it with a zipfile, try this:

cd orkiv
zip ../orkiv.zip *
cd ..
python orkiv.zip

It is possible to code Kivy applications in pure Python, but in my opinion, it is much better to use the amazing KV Language to do layouts. The basic approach is to have a Python file (in our case __main__.py above) that contains the logic for the application, and a KV Language file that contains the layout information. The KV Language is very similar to Python and you can learn it as you go.

Lets start by removing the print statement from our __main__.py and replacing it with the most basic possible Kivy application:

(commit)

from kivy.app import App


class Orkiv(App):
    pass

Orkiv().run()

This simply imports a Kivy App class and creates a subclass of it using Python’s notoriously simple inheritance syntax. Inheritance is a useful feature of Object Oriented Programming that basically means that a class can be defined that has all the functionality of the parent class. In this case, since we didn’t add anything to the subclass, that’s ALL it has. However, the true beauty of inheritance is that we can add new properties and methods (functions attached to objects) to the subclass or even change the functionality that comes with the parent class (App). The best part is, we don’t really have to know what is going on inside the App, and can assume the Kivy devs know what they are doing.

It doesn’t even add anything to the subclass! Then it instantiates an instance of that subclass and calls the run() method on the newly created object.

If you run python orkiv with the new code saved, you’ll see an empty window pop up.

As far as boilerplate goes, that’s pretty damn concise, don’t you think? The amazing thing is that we can start laying out KV Language widgets in a separate file without touching this boilerplate at all! Don’t believe me? Try saving the following as orkiv/orkiv.kv:

(commit)

Label:
    text: "hello world"

Now if you run python orkiv, you should see the “hello world” label centered in the window that pops up. It’s almost like magic, and if you’re like me, you’re probably wondering how that’s even possible.

When you create a subclass of a kivy.app.App, it introspects the name of the new class (we named it Orkiv). Then it looks for a file in the same directory that follows these rules:

  1. Ends with the .kv extension
  2. Starts with the name of the class converted to lowercase and with any
    trailing App stripped.

The Kivy documentation would have named the class OrkivApp and still used the orkiv.kv filename. Personally, I don’t see the redundant need to add App to the class name, since the inheritance structure clearly indicates that Orkiv is a App.

We’ll be working with the Kivy Language a lot as we proceed through each part of this tutorial. You’ll soon see that it’s possible to do more, a lot more, than add a label to a window!

A note on version control

At this point, you’ve created a logical related set of changes that are in a working state. I want to encourage you to experiment with these files, maybe change the contents of the label, try a different application and KV Language filename, or see if you can figure out how to group two labels into a single layout. But before doing that, you should record this known state that your repository is currently in so it’s easy to get back to. That way, you can be free to explore without fear of getting completely lost; you’ll always have a path straight back to your current state. You can do that from the command line using git:

git add orkiv/
git commit -m "A basic Kivy boiler plate"

You just made a commit on the master branch in git. First you listed the changes you wanted to include in the commit (the entirety of every file in the new orkiv directory), then you told git to record the current state of those files forever. It is generally recommended that you only save consistent, known-to-be-working state on the master branch. For the purposes of this tutorial, I suggest that you only save the code you copied from the tutorial to the master branch, and do your other development on other branches.

Are you confused by what a branch is, exactly? Think of it like walking down a forest path in a national park. You are following signs for a marked trail; that’s this tutorial. As you walk, you see things that you want to remember, so you take a photo. That’s like making a commit on the master branch. However, you also see side paths that you would like to explore on your own. You can go down that path as far as you want, or even take other random paths without fear of getting lost. You can even take photos on those paths, knowing they won’t get mixed in with the photos from the main trail. Then when you want to return to the point where you left the main trail, you can magically teleport back to it (or indeed, to any of the other branches you walked down in your exploration).

You probably won’t be doing it for this tutorial, but the most import aspect of version control is that if you are in unmarked forest rather than a national park, you can walk down all the paths and decide which one you’re going to choose as the main path. You can even merge paths back into each other so that the photos (code commits) taken on each of them end up in the same final presentation.

Enough digressing! For your purposes, the first thing you should do is create a new branch in git:

git checkout -b my_exploration

You are now on a new branch named my_exploration (you can call each branch whatever you want, of course) that is exactly the same as the master branch as you last saw it. But you can make changes on that branch to your heart’s content; you can add and commit them as above if you want to remember them for later. When you’re ready to come back to the tutorial, you can use this command to return to the current state of the master branch:

git checkout master

From there, you could continue with the next part of the tutorial, or you could create a new branch and explore in a different direction.

Browsing the examples

I am maintaining my own version of the code developed in this tutorial at https://github.com/buchuki/orkiv/. However, it’s not likely to be the same as your repository, since I’m not making commits at the same time that I’m suggesting you make commits. Instead, my master branch contains a separate commit for each example in the tutorial. I also create git tags for each part of the tutorial so it’s fairly easy to see from commit history what was covered in each part. If you browse the Commit History you can see each example and how it evolved from top to bottom. You can view the list of tags here.

Monetary feedback

When I wrote this tutorial, I didn’t expect it to be big or popular enough to publish as a book. However, the series caught O’Reilly’s eye, and I have since written an entire book on Kivy. If you want to support me and learn more about Kivy, you and I both will be delighted if you buy it.

If you like the tutorial and would like to see similar work published in the future, this isn’t the only way to support me. I hope to one day reduce my working hours at my day job to have more time to devote to open source development and technical writing. If you think this article was valuable enough that you would have paid for it, please consider thanking me in one or more of the following ways:

If you aren’t in the mood or financial position to help fund this work, at least share it on your favorite social platforms!

40 Comments

  1. pyuser says:

    Nice, but please tutorial how to create “shopping list” app with database. Is it possible?

    • Dusty Phillips says:

      A shopping list app would be pretty easy to cover. If this tutorial goes over well (it’s going to take a few weeks to get it all written and published), I could do something like that next.

  2. I think you meant to put:

    echo “*.pyc” >> .gitignore

    instead of

    echo *.pyc

    in the first code block.

    • Dusty Phillips says:

      Thanks, fixed!

      • Not sure if it’s just me, but on zsh:

        echo *.pyc >> .gitignore

        Will return:

        zsh: no matches found: *.pyc

        Thus the quotation marks:

        echo “*.pyc” >> .gitignore

        Thanks for the great tutorial by the way, keep it coming! I had been looking for exactly this. Great blog.

  3. cippaciong says:

    This is really a nice idea! As a complete newbye at this, I will follow your guides with interest.

  4. chtr says:

    Looks good so far.

    A while ago I tried kivy a bit but I really found no good documentation on listviews and adapters and how to use them. Right now I skimmed the documentation and it looks much better now with examples and stuff. It would probably still be good if you’d cover it in the course of this series.

    • Dusty Phillips says:

      The Kivy documentation is improving quickly. I am hoping to delve into it myself and submit a few pull requests at some point. I’m not sure if a listview will fit in with the goals of this tutorial (I’ll probably use it for the Buddy List, but I haven’t thought ahead that far, yet), but I’ll keep it in mind for a future one. If I don’t find a use for one, I’ll at least improve the stock documentation.

  5. kkt says:

    Your table of contents link appears to be broken.

    • Dusty Phillips says:

      Already!? I wasn’t expecting the TOC to get out of sync until at least part 3! I’ve fixed it, thanks for letting me know.

  6. Bryan Lott says:

    This is a *great* tutorial and I’m really looking forward to the rest of it. I tried learning kivy but ended up getting lost in the documentation, specifically how the layout works and how to write a .kv file. Love the fact that you’re developing both the .py and .kv side by side.

  7. Dave C says:

    Working on Debian Wheezy, I needed to install python-dev package (I also installed gcc, not sure if that was actually necessary though) in order for pillow to install.

    I’m getting a message ‘no distributions at all found’ for pygame though.

    Thank you for this tutorial, I’ve been studying python, but this has prompted me to also get started on git and virtualenv.

  8. [...] article continues the tutorial we started in Part 1. In the first part, we set up a Kivy project and developed a very basic Kivy application. We also [...]

  9. Dusty Phillips says:

    Note: I removed some of the dependencies from the pip install line, as they are not required in Kivy 1.7, which is what this tutorial is written for. Thanks to Mathieu Virbel, Kivy developer, for pointing this out.

  10. Adrian Klaver says:

    Somewhat confused by the directory structure.
    You have:

    mkdir orkiv
    cd orkiv
    git init
    virtualenv -p python2.7 venv
    echo venv >> .gitignore
    echo “*.pyc” >> .gitignore
    git add .gitignore
    git commit -m “Create .gitignore file. Ignores compiled python files and venv.”
    source venv/bin/activate

    then:

    mkdir orkiv

    So is the structure:
    orkiv
    venv
    orkiv
    with git initialized in the top orkiv/?

    • Dusty Phillips says:

      I think you’ve got the right idea. Yes there is an orkiv source code directory inside the orkiv project directory. Here’s the directory listing I have as of part 3:

      dusty:~ $ cd code/orkiv/
      (master) dusty:orkiv $ ls
      orkiv tutorial venv
      (master) dusty:orkiv $ ls -a
      . .. .git .gitignore orkiv tutorial venv
      (master) dusty:orkiv $ ls orkiv
      __main__.py orkiv.kv sleekxmpp_buddylist.py
      (master) dusty:orkiv $

      Hope that helps!

      • Adrian Klaver says:

        Alright. Seems there is a typo

        If you run python kivy with the new code saved, you’ll see an empty window pop up.

        should be:

        If you run python orkiv with the new code saved, you’ll see an empty window pop up.

  11. Adrian Klaver says:

    Finally got pygame tamed and the sample code working. Thanks for the tutorial. Kivy is something I have been wanting to try out for some time. Never was quite sure how to start, this definitely helps.

  12. [...] trying to install pygame using pip in a virtualenv. I’m following this tutorial on using Kivy. However, running pip install pygame returns Downloading/unpacking pygame [...]

  13. [...] trying to install pygame using pip in a virtualenv. I’m following this tutorial on using Kivy. However, running pip install pygame returns Downloading/unpacking pygame [...]

  14. Gour says:

    Hiya Dusty,

    I like your OOP book and now found out you’re tinkering with Kivy, so wonder do you consider it could be used instead of e.g. PyQt for more desktop app (although being able to have it on Droid phone would be cool) in regards to its features, iow. widget-wise and performance-wise?

    Sincerely,
    Gour

    • Dusty Phillips says:

      Hi Gour,

      Thanks for the accolades, much appreciated!

      Personally, I’d use Kivy for all desktop apps. It’s the only graphical user interface I have ever taken delight in working with, rather than feeling like I was constantly fighting with it. Over the years, I’ve used Visual Basic, Java AWT, Java Swing, HTML+CSS, WXPython, PyGTK, PyQT, and TKInter. They were all annoying and frustrating in different ways. Kivy truly circumvents that.

      However, there are a few caveats. As an earlier commenter pointed out, Kivy doesn’t support native or native-looking OS widgets. Also, Kivy’s widget library, while extensive, is not as big as some other libraries, and many of those that it does provide are multi-touch oriented. This means you may be developing more custom widgets. This issue is alleviated by the fact that it’s so easy to build a custom widget in Kivy! Finally, Kivy’s API is deliberately very simple. That doesn’t mean that there are things you can’t do with Kivy, since the API is also extensible, but on occasion, it means you’ll have to go to a bit extra work to make things happen. You’ll see an example of this in part 4 of this tutorial.

      Performance-wise, I think Kivy may have an edge for advanced graphics rendering because it’s backed by hardware accelerated SDL and OpenGL, and all the critical parts are compiled Cython. For basic widgets, I wouldn’t expect performance to be a bottleneck in any toolkit.

  15. Gour says:

    Hello Dusty,

    > Thanks for the accolades, much appreciated!

    I forgot to tell you I’m very glad you are over with your health issues!!

    > Personally, I’d use Kivy for all desktop apps. It’s the only graphical user interface I have ever taken delight in working with, rather than feeling like I was constantly fighting with it.

    I’m delighted to hear it. ;)

    > Over the years, I’ve used Visual Basic, Java AWT, Java Swing, HTML+CSS, WXPython, PyGTK, PyQT, and TKInter. They were all annoying and frustrating in different ways. Kivy truly circumvents that.

    That’s great to hear. Let me say that was/am also considering to use some statically typed/compiled language and tried quite a few…starting from Haskell some years ago, then D, considered Ada, OCaml as well as some obscure ones (with Pythonic syntax) like Nimrod & Cobra…Lastly I was taking look at F#…but, many languages although being nice/interesting in themselves, are lacking in their ecosystem (“batteries included”) and reduce the choice of GUI mostly to GTK only, which is, imho, not the greatest multi-platform option.

    > However, there are a few caveats. As an earlier commenter pointed out, Kivy doesn’t support native or native-looking OS widgets.

    Well, Qt is also not 100% native, right, while being quite huge, isn’t it?

    > Also, Kivy’s widget library, while extensive, is not as big as some other libraries, and many of those that it does provide are multi-touch oriented. This means you may be developing more custom widgets. This issue is alleviated by the fact that it’s so easy to build a custom widget in Kivy! Finally, Kivy’s API is deliberately very simple. That doesn’t mean that there are things you can’t do with Kivy, since the API is also extensible, but on occasion, it means you’ll have to go to a bit extra work to make things happen. You’ll see an example of this in part 4 of this tutorial.

    OK. Sounds good.

    > Performance-wise, I think Kivy may have an edge for advanced graphics rendering because it’s backed by hardware accelerated SDL and OpenGL, and all the critical parts are compiled Cython.

    What do you think about Nuitka/mypy attempts?

    > For basic widgets, I wouldn’t expect performance to be a bottleneck in any toolkit.

    Good. I must say that I like idea of using Kivy – it would allow me to stay within Python domain since I plan to use Django for *some* of my web needs while the rest probably via some Python static generators. :-)

    Let me not forget: +1 for writing and publishing Rapid NUI Programming with Python and Kivy book. ;)

    Sincerely,
    Gour

    • Dusty Phillips says:

      I hadn’t heard of Nuitka, so can’t comment too much. I’m glad people are still experimenting in this space and hope something will be successful. Right now the only really viable product in the compiled/faster python space is Cython. Pypy always looks like it’s “almost there” but every time I want to use it, it isn’t quite the right tool for the job.

      Mypy strikes me as a “let’s write a version of Go that has a pythonic syntax.” If they pull it off, I’m all for it! I’ve been working with a variety of parallelism and concurrency issues in Python in the last 18 months and I’ve come to the conclusion that Python is not the right tool for the job when multiple processors are involved. I want to rewrite everything in Go. But a more pythonic looking Go would be quite ideal.

      • Gour says:

        > I want to rewrite everything in Go.

        But then there is no more Kivy, right? Moreover, GTK seems to be the only option there…

        • Dusty Phillips says:

          I meant using Go only for concurrent apps. I prefer the syntax of Python in the general case. But when it comes to parallelism, Python is abysmal. It’s a bit better for concurrency on a single CPU, but I think Go is much nicer to work with for both use cases.

          I’d never dream of using Go for graphical interfaces. While they are event driven, they don’t generally need to be highly parallel and the async loop model has been demonstrated to work very well for them. Kivy handles this very elegantly, but I’d say any of the Python libraries are more suitable to graphical development than Go + GTK.

  16. [...] Remember to create and activate a virtualenv populated with the appropriate dependencies, as discussed in part 1. [...]

  17. Vincent says:

    Thats for this tutorial. Now if only I can find the time to follow along.

  18. chaiyachaiya says:

    Hello Dusty,
    No need to invent a new script to switch from a virtualenv to another. Take a look at *virtualenvwrapper*.
    Very usefull. You just do not wanna hear from virtualenv without this tool when you tried it.
    http://virtualenvwrapper.readthedocs.org/en/latest/

    • Dusty Phillips says:

      Personally, I’ve never liked virtualenvwrapper because it puts all the virtualenvs in one place and I have to think about naming them properly. However you are right that I should have mentioned it in the article, as it’s very useful and popular among people who prefer a different workflow.

  19. [...] stumbled across this tutorial, welcome to the middle of something! You might want to jump back to the beginning if that’s the case. Don’t worry, we’ll wait for you to catch [...]

  20. [...] Remember to create and activate a virtualenv populated with the appropriate dependencies, as discussed in part 1. [...]

  21. [...] Remember to create and activate a virtualenv populated with the appropriate dependencies, as discussed in part 1. [...]