bookI have been working in this book for a while already. This is why I have been posting so much about Kivy lately and I will continue doing. The posts are a complement to the book and some very interesting ideas that I have learned during the process. It is also a way collaborate to the amazing job that Mathieu Virbel and his team are doing with this platform. And, of course, it is also a way to promote my book to recover the time investment made on it.

I have seen Kivy growing faster and faster, and I am positive that it will become a main competitor in the market of the mobile application development. As the second-last Twitter post says:

“How come #Kivy is not one of the most spoken about #Python projects? Cross-platform mobile app development in Python!”.

I cannot agree more. Kivy is still just being discovered and it’s simple fabulous. There are many good reasons to say that, but I will just highlight the ones that I consider most important, just in case you haven’t heard about it:

  1. It is cross platform. I haven’t found anything more compatible than Kivy. It runs in Linux, Windows, MacOSX, Android and IOS; and recently in Raspberry.
  2. Built-in interactivity. Many of the features you expect to see in a mobile application are ready-to-use in Kivy: multi-touch support, gestures, all sorts of keyboards, touch and clock events (including the magical Kivy properties), animations.
  3. It is Python. Ok, you may say this is a bit subjective. I have worked with Java, C++, PHP and others, and just a couple of years ago with Python. It does make a difference

It feels like a short and long process at the same. It was one year and a half ago when Mathieu wrote me about an already old post to help them with the documentation. I would have loved to participate but I was really busy with uni. However, when Pack Publishing contacted me because of exactly the same post (it is strange that somehow we hit the right spot on the internet and a post suddenly scale on searches, the post is quite bad to be honest but I was lucky), it was a very different scenario

This time I was quitting the university and just thinking to free lance and having a more formal blog. So, it just came on the right place and the story a success. The book is already available. I hope those that get to buy it, enjoy as much as I enjoy writing it.

I will continue doing Kivy posts. I hope more often now that the book is not sucking my time. Feel free to write me about any question related to the book or, well, anything in general. I have been also replying some questions in [StackOverflow](http://stackoverflow.com/users/1060349/toto-tico), so you can just post there were I frequently hang around.

As for today, I am glad of contributing with this great project. Thanks to the editorial and its team, and thanks to the Kivy team for this great library.

Long live to Kivy!

I have been insisting in the importance of PushMatrix and PopMatrix to control the use of the canvas in Kivy in:

In today’s post I explain a very specific example of how to rotate an Image without affecting the whole interface. I start with the common problem that the novice will experience and explain how to fix it:

 

1. The Initial Interface:

This is the screenshot of the interface we are going to work with. We want to rotate the image on the top-right of the layout.

GridLayout with one Button (top-left), one Image (top-right) and another Button (bottom-left)

This is the respective code:

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

Builder.load_string("""
<KivyImage@Image>:
    source: 'kivy.png'
    pos: self.parent.pos
    size_hint: .5,.4
    canvas:
        Color:
            rgba: 1,0,0,.5
        Line:
            rectangle: self.x, self.y, self.width, self.height

<TestApp>:
    cols: 2
    Button:
        text: "Place Holder 1"
    FloatLayout:
        KivyImage:
    Button:
        text: "Place Holder 2"
""")

class TestApp(App, GridLayout):
    def build(self):
        return self

if __name__ == "__main__":
    TestApp().run()

The interface is very simple. A GridLayout with 2 columns and 3 widgets. A Button (Place Holder 1), a FloatLayout with an Image inside and another Button (Place Holder 2). The FloatLayout contains the KivyImage class that we are going to be working with. The KivyImage also contains a rectangular border as a reference to follow our notations.

 

2. The Problem:

The instruction we need to use for rotating is Rotate. We use three parameters for it: axis that sets the axis are we going to use for the rotation, usually z since; angle that sets the amount of degrees we want to rotate. After using the Rotate instruction, our code will look like this:

<KivyImage@Image>:
    source: 'kivy.png'
    pos: self.parent.pos
    size_hint: .5,.4
    canvas:
        Rotate:
            axis: 0,0,1
            angle: 60
            origin: self.center
        Color:
            rgba: 1,0,0,.5
        Line:
            rectangle: self.x, self.y, self.width, self.height

Here is the result:

After the Rotation

As you can see, after applying the instruction, everything is rotated (including the last Button). This means, that when we use context instructions (Scale, Rotate and Translate), the whole coordinate space is affected.

More over, our image didn’t Rotate just the Rectangle!

 

3. Avoiding a global rotation:

We need to control the rotation, so the whole interface after the Rotate instruction is not affected. One way would be manually un-rotate with something like:

        Rotate:
            axis: 0,0,1
            angle: -60
            origin: self.center

Of course, that will be quite tedious. Instead, we are going to use two important instructions: PushMatrix, that saves the current context, and PopMatrix, that recovers the last saved context. Now the code looks like this:

<KivyImage@Image>:
    source: 'kivy.png'
    pos: self.parent.pos
    size_hint: .5,.4
    canvas:
        PushMatrix
        Rotate:
            axis: 0,0,1
            angle: 60
            origin: self.center
        Color:
            rgba: 1,0,0,.5
        Line:
            rectangle: self.x, self.y, self.width, self.height
        PopMatrix

And our new output should look like the following:

Using PushMatrix and Pop

Almost there, except that our images continues in the same original position. Let’s finally Rotate the image.

 

4. Rotate the image for once!:

Sorry, I tell you why the image is not rotated. In the 2nd step, even though the whole context where rotated, the image didn’t. The only explanation is that the Rotate where executed after the image is display on the screen.

Somehow, we need to guarantee that our Rotate instruction gets executed before. There is three sets of canvas instructions: canvas.before, canvas and canvas.after. Their names are intuitive, so let’s reorganize our instructions:

<<KivyImage@Image>:
    source: 'kivy.png'
    pos: self.parent.pos
    size_hint: .5,.4
    canvas.before:
        PushMatrix
        Rotate:
            axis: 0,0,1
            angle: 60
            origin: self.center
    canvas:
        Color:
            rgba: 1,0,0,.5
        Line:
            rectangle: self.x, self.y, self.width, self.height
    canvas.after:
        PopMatrix

And finally we got our image rotated without affecting the rest of the interface:

Rotated Image

It is not strictly necessary to move the PopMatrix to the canvas.after section. The difference would be in the children of the image. In this case, it doesn’t have. But in case it has children, then they will be rotated if the PopMatrix is in the canvas.after section.

Read more about the canvas in 10 things you should know about the Kivy canvas.

Top-bar main menu is a big screen as bottom-bar main menu is an small phone screens. Here is an example of how to build a smartphone interface with multiple interfaces. I just added two interfaces the first screen has a welcoming message. The second on a keyboard to dial.

Screen 1. Welcome Message
Screen 1. Welcome Message
Screen 2. Keyboard
Screen 2. Keyboard
 

The buttons controls the screens through the ScreenManager and the current property. All we have to do is assign a a name to the screens and change `current` property to the desire screen when the `on_press` event is triggered, like this:

    on_press: _screen_manager.current = 'screen1'

_screen_manager is just a kivy id so we can reference it (the ScreenManager)inside the Kivy Language. So, here is the code.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout

Builder.load_string("""
<Phone>:
    AnchorLayout:
        anchor_x: 'center'
        anchor_y: 'top'
        ScreenManager:
            size_hint: 1, .9
            id: _screen_manager
            Screen:
                name: 'screen1'
                Label: 
                    markup: True
                    text: '[size=24]Welcome to [color=dd88ff]THE APP[/color][/size]'
            Screen:
                name: 'screen2'
                GridLayout: 
                    cols: 3
                    padding: 50
                    Button:
                        text: "1"
                    Button:
                        text: "2"
                    Button:
                        text: "3"
                    Button:
                        text: "4"
                    Button:
                        text: "5"
                    Button:
                        text: "6"
                    Button:
                        text: "7"
                    Button:
                        text: "8"
                    Button:
                        text: "9"
                    Button:
                        text: "*"
                    Button:
                        text: "0"
                    Button:
                        text: "#"
    AnchorLayout:
        anchor_x: 'center'
        anchor_y: 'bottom'
        BoxLayout:
            orientation: 'horizontal'
            size_hint: 1, .1
            Button:
                text: 'Go to Screen 1'
                on_press: _screen_manager.current = 'screen1'
            Button:
                text: 'Go to Screen 2'
                on_press: _screen_manager.current = 'screen2'""")

class Phone(FloatLayout):
    pass

class TestApp(App):
    def build(self):
        return Phone()

if __name__ == '__main__':
    TestApp().run()

Hope somebody found it useful.

I already posted before about the how to use transformations with Kivy. There was still some gaps in the explanation. After a while of being working with Kivy I have a much better understanding of what it is happening so I came with a list of 10 things that you should know about the Kivy canvas.

  1. A Kivy canvas is not the space in which you paint. 

    The major problems I had at the beginning with the canvas were due to its name. Particularly considering all the buzz about HTML5 canvas. I initially visualize the canvas as the cloth that painters paint. Since all the widgets has one canvas, I started to get confused and asked why did the Widget seem to share the same canvas?

  2. The answer needs, first, to clarify what is the canvas? (2nd bullet point) and where is it that the widgets share? (3rd bullet point)

  3. A Kivy canvas is a set of instructions! 

    A canvas is basically a container of instructions. More like a recipe that tells you how to draw, rather than a place to draw. In other words the bitmap is not saved (like .bmp), but the vectors (like .gif). The canvas of the Widget basically keep the instructions to draw that performs the drawing.

  4. The widgets share the same coordinate space, not the same canvas.

    The final answer to my previous question is that all the widgets have a different canvas but all the canvas draw in exactly the same drawing space, i.e. the coordinate space. Moreover, the drawing space is not limited to the position and size of the widget. The 0,0 of the drawing space is always (except for the RelativeLayout and the ScatterLayout ) the bottom-left corner. If we want to draw a Rectangle that covers the whole area of the Widget we should do something like this:

    ...
    Widget:
        canvas:
            Rectangle:
                pos: self.pos
                size: self.size

    Notice that we need to specify explicitly that the size and pos of the Rectangle is the same of the Widget. There lies…

  5. … the little secret of RelativeLayout.

    The previous code doesn’t work with RelativeLayout. Instead we actually use the coordinate (0,0) to achieve the same result:

    ...
    Widget:
        canvas:
            Rectangle:
                pos: 0,0
                size: self.size

    The RelativeLayout includes a Translate instruction:

    Translate:
        xy: self.pos
    

    That instruction is going to translate the canvas to the self.pos position. In other words, the (0,0) is now self.pos.

  6. PushMatrix and PopMatrix to control the effects of sharing the same drawing space.

    Sharing the same drawing space has its consequences. The problem is that the instructions of one Widget canvas may affect the next one. If I rotate the drawing space, the drawing space will be rotated until some other instructions rotate it back again. It is up to us to guarantee that the context of the drawing space remains the same when the canvas stop drawings. Kivy provides two instructions PushMatrix and PopMatrix. RelativeLayout uses a PushMatrix before the instructions of the canvas and a PopMatrix after it.

    PushMatrix:
    ...
    Translate:
        xy: self.pos
    ...
    PopMatrix:
    

    The PushMatrix saves the current context state (rotations, translations, zoomings) and the PopMatrix recovers it and let thing as they were before.

  7. The color is an exception.

    That said, PushMatrix and PopMatrix doesn’t have an effect over the Color instruction.

    PushMatrix:
    Color:
        rgb: 1,0,0
    Rectangle:
        ...
    PopMatrix:
    Line:
        ... 
    

    It doesn’t matter which was the previous Color before PushMatrix, the Rectangle and and the Line would be red (rgb: 1,0,0).

  8. The order in which canvas instructions are executed.

    The execution order follow a traversal order. There is recursivity involved but, let’s stick with what you have to consider. When you are using a Widget canvas, the instructions of all the canvas of the parent and grandparents were executed. Also the instructions of the canvas of the first added siblings. The instructions of the canvas children hasn’t been executed yet. Neither the ones of the siblings added after. When you are coding you actually perceive a normal top-down execution and thinking that way is ok for most of the cases. When you start using dynamic interfaces, adding and removing children, strange things seem to happen and you will need to remember the order of execution. Perhaps, more important is to know how to do to manipulate this order.

  9. Drawing after the children with canvas.after

    What happens if we want to execute instructions after the children were added. In that case we have another canvas (called canvas.after) that is called after traverse all the children.

    Widget:
        canvas:
            ...
        canvas.after:
            ...
        Button:
            canvas.before:
               ...
            canvas:
               ...
            canvas.after:
               ...
    

    The canvas execution order is as follows:
    (1) The Widget canvas
    (2) All the Button canvas (canvas.before, canvas, canvas.after)
    (3) The Widget canvas.after
    Notice that all the canvas of the Button are executed in between canvas and canvas.after.

  10. What about canvas.before?

    You probably notice that there is a third canvas (canvas.before). It executes just before the canvas. I found the canvas.before particularly useful when
    (1) I need to manipulate the Color of an instance and, (2) I need to manipulate inheritance. Let’s say I have MyWidget that draws a Rectangle inside.

    <MyWidget@Widget>:
        canvas:
            Rectangle:
            ...
    

    So I can modify the Color of a particular instance doing something like this:

        ...
        mywidget = MyWidget
        mywidget.canvas.before:
            Color(rgba=(1,0,0,0))
    

    If I use canvas instead of canvas.before in RedWidget, the instruction is going to be executed after the Rectangle, so it won’t apply to the Rectangle.
    (2) Similarly, when I need to manipulate inheritance. Let’s say I have MyWidget that draws a Rectangle inside. I can do the following to change the color of the base class Rectangle:

    <RedWidget@MyWidget>:
        canvas.before:
            Color:
                rgb: 1,0,0
    

    The RedWidget inherits from MyWidget and I would have the same problem if I just use the canvas. Of course, similar applications goes for the canvas.after.

  11. Drawing on top of a Button Widget with canvas.after.

    This works for any other Widget and not just for the Label but it is probably the most common case. If you want to draw over the Button background you can use the canvas.after. Otherwise the background will cover your drawings:

    Button:
        text:
        canvas.after:
            Rectangle:
                pos: self.pos
                size: self.size
    

    The rectangle of the previous code will actually cover its text.

This post turned out to be longer than I was expected. I hope I didn’t make any mistake in my explanation. If so, please let me know.

In my previous post I explain how to create a smooth translation using the Kivy Clock and Properties. There is actually an easier way for doing this.

We can use Kivy animations. It is the simplest way. Below is the code. The interesting thing about the Animation class is that we can send any widget property as the animation parameter. For example, we can send the Label‘s font_size as the Animation‘s parameter. Moreover we can send two or more parameters.

label = Label(text = "increase and move", pos=(0,0))
animation = Animation(x=500, y=500, font_size=72px, d=2, t='in_out_quad');
animation.start(label) 

As you can see, I am sending three properties (x, y, and font_size). I added the t='in_out_quad' as a small surprise to add a transition. Just ask me if you have any question.

Here is the full example of my previous post but using animations:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.animation import Animation

Builder.load_string("""
<PongBall@Widget>:
    size: 50, 50 
    canvas:
        Ellipse:
            pos: self.pos
            size: self.size

<PongGame>:
    ball: pong_ball

    PongBall:
        id: pong_ball
        pos: 0,0
""")


class PongGame(Widget):
    def animate(self):
        animation = Animation(pos=(Window.size), d=3)
        animation.start(self.ball)

class PongApp(App):
    def build(self):
        game = PongGame()
        game.animate()
        return game

if __name__ == '__main__':
    PongApp().run()