Kivy is an open source library for rapid development of applications that make use of innovative user interfaces, such as multi-touch apps". It works very well except that the documentation is not fantastic. The introductory tutorial is excellent but after that things start to get complicated.
Specifically, Javier and me struggled with the design of the interface. After a weekend reading the documentation and even code, we finally came with a solution that still feels sort of hacked, specially the coordinates (x,y) of the events. However, there were also nice surprises that start to explain some (at the beginning) weird decisions in the kivy arquitecture.
Since it is difficult to enumerate all the mysteries that we solved out, I will got through the code. The first important thing that you should know about Kivy is that it is not merely python. They have their own Kivy language. Even though, it is possible to use all the library with python, there are several advantages of the Kivy languange that will save you lots of code.
The kivy code is saved in files .kv. To use this code, all you need is
from kivy.lang import Builder Builder.load_file ('path/to/file')
The other important thing is to distinguish between Apps, Widget, Canvas and Graphics.
- App is generally one and will control your program. It needs at least one Widget.
- Widgets. I would divide this in three types:
- Form components: any button, label, textfield or similar
- Layouts: these are basically panels in which you can sort other widgets (AnchorLayout, GridLayout, BoxLayout, etc)
- Image: in our particular application, the most important one
- Canvas. Here is where the confusion begins and I am still not sure if I am totally right. It seem that there is just one canvas and it corresponds to the "drawable" part of the App (the app, not the widget). And this brings problems because when you capture events it could be produce in any area of the App (except the areas occupy by widgets that captures their own events such as buttons). The problem is that you have to calculate your own relative coordinates from the absolute ones.
- Graphics. This are objects that you can draw in the canvas: rectangles, ellipses, etc.
A minimal application will look like this
from kivy.app import App from kivy.lang import Builder from kivy.uix.floatlayout import FloatLayout Builder.load_file('gamex.kv') class Controller(FloatLayout): # Class attributes.... def __init__(self, **kwargs): super(Controller, self).__init__(**kwargs) #some initial configuration but be very careful #because kivy is quite sensitive with the constructor #use the .kv instead class ControllerApp(App): def build(self): return Controller(info='Hello world') if __name__ in ('__android__', '__main__'): ControllerApp().run()
The file gamex.kv is actually the one that organize the interface which you can see in the next picture. Some details are missing but basically it has three components. The image, a right-side menu and a bottom menu.
I will try to give you some clues of the code:
- Line 1: it's mandatory and specify the kivy version.
- Line 3: it has to have the same name of the first widget of the application. Look in the previous python minimal example. The rest of the code is indented inside of this line so it belongs to controller
- Line 4 to 7: The right side of the assignations must be attributes in the class Controller. The second part of the assignation are ids for some of the components of the interfaces. I will be back to this at the end.
- Line 9 to 11: This correspond to the image component of the interface. Anchor layout means that the position is going to be set by two of five types of references: top, bottom, right, left and center. One of the references set the x axis and the other the y axis. So in total there are nine combinations. In the example the layout is going to use the top-left part of the widget.
- Line 15: We can reference the attributes of the class using the variable root. The nice thing is that if the attribute change, then the interface is updated automatically.
- Line 16: Complements the previous 9 to 11. The size_hint of the image (not the AnchorLayout as you would expect) is the one that stablish the size of the Layout.
- Line 19 to 40 are not important.
- Line 43: This is going to define the right list of buttons. The size hint is set in Line 49
- Line 47: Stablish a BoxLayout to organize the buttons. In this case the buttons are actually kivy images. The problem we found with the buttons is that if you assign and image to a button, then the image is distorted.
- Line 96: It has a very similar structure to line 43 and correspond to the bottom components. In this case we use buttons and labels since we didn't need to put images.
This kivy languages already have saved us a lot of code in our interface but also there is another important detail that I need to explain. It corresponds to lines 4 to 7. As I said these assignations corresponds to attributes inside the class and ids inside the kivy code. So, for example, the line 4 assigns the id _paint to the attribute paint (the attribute in the final code is here). The _paint is in line 14 and also you must add the attribute to the class. The previous python code will look like this:
I guess that's it. I didn't expect to say that much. Thanks.
Thanks for sharing this. I was struggling with anchorlayouts but this is an excellent usage example 🙂