Kivy Contest 2014

Just to announce here for anyone that hasn’t seen already…Kivy recently announced the Kivy org second programming contest! You can check out all the details at http://kivy.org/#contest!

To cover the key details here, entries are open now (you can sign up at the link above), and the contest starts in full on 15th April. There will be a broad theme, announced on that day, but many different kinds of app will be possible. You’ll have 4 weeks from the start date to complete your entry.

Entries will be judged on a range of criteria, so don’t be afraid to jump in!

Kivy Contest 2014

Just to announce here for anyone that hasn’t seen already…Kivy recently announced the Kivy org second programming contest! You can check out all the details at http://kivy.org/#contest!

To cover the key details here, entries are open now (you can sign up at the link above), and the contest starts in full on 15th April. There will be a broad theme, announced on that day, but many different kinds of app will be possible. You’ll have 4 weeks from the start date to complete your entry.

Entries will be judged on a range of criteria, so don’t be afraid to jump in!

Kivy’s bind method

One of the most common problems for new Kivy users is misunderstanding how the bind method works, especially amongst newer Python users who haven’t fully formed their intuition about function calls. For instance, a user will write code like:

some_screenmanager.bind(current=a_function(arg1, arg2))

Here, the idea is that when the current property changes, it will call a_function with the arguments arg1 and arg2.

The problem is that Python itself doesn’t work like this; the bind method doesn’t know about the existence of a_function or its arguments, it only receives the result of this function call. This often leads to confusion when a user doesn’t understand why the binding is only called once, during the declaration of the binding.

Stepping back, our real goal is to call a_function with the given arguments, but bind needs to be passed a function if it is to work correctly. That means we can solve our problem by creating a new function with these arguments already passed (and discarding the extra arguments automatically passed by bind).

It’s usually convenient to do this with the partial function from the functools module:

from functools import partial
some_screenmanager.bind(current=partial(a_function,arg1, arg2))

partial returns a new function that will automatically be passed arg1 and arg2, exactly as we want. You can also pass kwargs this way.

This isn’t the only way to solve the problem, we could have created a lambda function (though the syntax is longer and can have scope problems) or an entire new function with def syntax, but both of these are more complicated than the simple use of partial. So if you need to do a binding in Python, look at this way first!

Kivy’s bind method

One of the most common problems for new Kivy users is misunderstanding how the bind method works, especially amongst newer Python users who haven’t fully formed their intuition about function calls. For instance, a user will write code like:

some_screenmanager.bind(current=a_function(arg1, arg2))

Here, the idea is that when the current property changes, it will call a_function with the arguments arg1 and arg2.

The problem is that Python itself doesn’t work like this; the bind method doesn’t know about the existence of a_function or its arguments, it only receives the result of this function call. This often leads to confusion when a user doesn’t understand why the binding is only called once, during the declaration of the binding.

Stepping back, our real goal is to call a_function with the given arguments, but bind needs to be passed a function if it is to work correctly. That means we can solve our problem by creating a new function with these arguments already passed (and discarding the extra arguments automatically passed by bind).

It’s usually convenient to do this with the partial function from the functools module:

from functools import partial
some_screenmanager.bind(current=partial(a_function,arg1, arg2))

partial returns a new function that will automatically be passed arg1 and arg2, exactly as we want. You can also pass kwargs this way.

This isn’t the only way to solve the problem, we could have created a lambda function (though the syntax is longer and can have scope problems) or an entire new function with def syntax, but both of these are more complicated than the simple use of partial. So if you need to do a binding in Python, look at this way first!

Kivy’s bind method

One of the most common problems for new Kivy users is misunderstanding how the bind method works, especially amongst newer Python users who haven’t fully formed their intuition about function calls. For instance, a user will write code like:

some_screenmanager.bind(current=a_function(arg1, arg2))

Here, the idea is that when the current property changes, it will call a_function with the arguments arg1 and arg2.

The problem is that Python itself doesn’t work like this; the bind method doesn’t know about the existence of a_function or its arguments, it only receives the result of this function call. This often leads to confusion when a user doesn’t understand why the binding is only called once, during the declaration of the binding.

Stepping back, our real goal is to call a_function with the given arguments, but bind needs to be passed a function if it is to work correctly. That means we can solve our problem by creating a new function with these arguments already passed (and discarding the extra arguments automatically passed by bind).

It’s usually convenient to do this with the partial function from the functools module:

from functools import partial
some_screenmanager.bind(current=partial(a_function,arg1, arg2))

partial returns a new function that will automatically be passed arg1 and arg2, exactly as we want. You can also pass kwargs this way.

This isn’t the only way to solve the problem, we could have created a lambda function (though the syntax is longer and can have scope problems) or an entire new function with def syntax, but both of these are more complicated than the simple use of partial. So if you need to do a binding in Python, look at this way first!

Creating a Kivy layout: the SparseGridLayout

I thought for a change I’d try for a shorter post on a single quick subject, so I’m going to quickly explain a simple Kivy layout I created, the SparseGridLayout. The post is standalone, but would go well with ideas from my Kivy Crash Course, especially the recent videos trying to draw ideas together to make widgets or specifically focusing on layouts.

The point here is that Kivy has a built in GridLayout, but it doesn’t cover all use cases for widgets in a grid, which is sometimes confusing to users who’ve seen grid widgets in other places and expected a slightly different behaviour. The problem is that the GridLayout fills widgets in from the top. That means for instance if there are 3 columns, you can’t place a widget in the third row without first adding 6 widgets to fill the first two rows. That’s just inefficient and wasteful if all you wanted was a small number of widgets in a grid.

So, my SparseGridLayout is a very simple layout that has a number of rows or columns, and checks its children for a row and column property. It then resizes them automatically to be placed in the right grid cell. That means we don’t need any extra widgets, which is much more efficient if we want a grid with not many entries, hence sparse grid layout.

We can start with a FloatLayout base, then all we need to do is set our grid children’s size_hint and pos_hint properties appropriately for the grid and call the FloatLayout‘s normal layout method to actually place them in the grid positions/shapes for us.

We can start by making our layout class:

from kivy.uix.floatlayout import FloatLayout
from kivy.properties import NumericProperty, ReferenceListProperty

class SparseGridLayout(FloatLayout):
    rows = NumericProperty(1)
    columns = NumericProperty(1)
    shape = ReferenceListProperty(rows, columns)

That creates a basic class that doesn’t have any more actual behavior than the FloatLayout alone, but has a few new properties. It’ll hopefully all make sense if you’ve used Kivy a little or followed my crash course, though the ReferenceListProperty may be new - this takes multiple other properties and lets us access them as a list, so for instance referencing or setting shape[0] really updates the rows property, including calling all its associated events etc.. At the same time, the shape is also a real property, with its own events. Do experiment with this if the explanation is not clear.

Now, to make our layout actually rearrange its children to the grid, we need to override its do_layout method, which is what’s called whenever it or its children are updated.

def do_layout(self, *args):
    shape_hint = (1. / self.columns, 1. / self.rows)
    for child in self.children:
        child.size_hint = shape_hint
        if not hasattr(child, 'row'):
            child.row = 0
        if not hasattr(child, 'column'):
            child.column = 0

        child.pos_hint = {'x': shape_hint[0] * child.row,
                          'y': shape_hint[1] * child.column}
    super(SparseGridLayout, self).do_layout(*args)

This iterates over all the SparseGridLayout‘s children, setting their size_hint so that they’ll fit exactly in a grid cell (as per the rows and columns properties we set above). It then checks if they have a row or column property, setting it to 0 if not - I’ve chosen that my rows and columns should be zero-indexed, you could modify that if you like. After that, it sets their pos_hint such that they’re placed in the right place. I’ve deliberately let this work with floats, so for instance they could be in column 2.5 to be halfway between the integer columns, so the layout is extra flexible.

The final step is calling the original do_layout method of the FloatLayout. The magic is that all we did is set the child widgets size_hint and pos_hint so that the widgets align to a grid - the FloatLayout itself already knows how to actually set their positions and sizes based on this information. By making use of Kivy’s existing layout abilities, we’ve saved ourself a lot of work.

Finally, I also added a class to represent entries in the grid:

class GridEntry(EventDispatcher):
    row = NumericProperty(0)
    column = NumericProperty(0)

This is very simple, but it means you can do for example:

class GridLabel(Label, GridEntry):
    pass

The GridLabel is thereby a Label that already has row and column properties, so it will behave properly in our SparseGridLayout. We don’t strictly need to do this, we could add the row and column any other way, but this is neat and makes it totally clear what we’re using our widgets for.

That’s everything! With just a few simple modifications we’ve made a whole new Layout widget that can place its children in rows and columns of a grid. Maybe you’ll find that useful, but more generally I hope this demonstrates the general principles of thinking about Layouts and using Kivy’s existing mechanisms to do most of the work.

You can find all this code at my sparsegridlayout github repository, which also includes a simple demonstration App so you can test the new layout if you like.

Creating a Kivy layout: the SparseGridLayout

I thought for a change I’d try for a shorter post on a single quick subject, so I’m going to quickly explain a simple Kivy layout I created, the SparseGridLayout. The post is standalone, but would go well with ideas from my Kivy Crash Course, especially the recent videos trying to draw ideas together to make widgets or specifically focusing on layouts.

The point here is that Kivy has a built in GridLayout, but it doesn’t cover all use cases for widgets in a grid, which is sometimes confusing to users who’ve seen grid widgets in other places and expected a slightly different behaviour. The problem is that the GridLayout fills widgets in from the top. That means for instance if there are 3 columns, you can’t place a widget in the third row without first adding 6 widgets to fill the first two rows. That’s just inefficient and wasteful if all you wanted was a small number of widgets in a grid.

So, my SparseGridLayout is a very simple layout that has a number of rows or columns, and checks its children for a row and column property. It then resizes them automatically to be placed in the right grid cell. That means we don’t need any extra widgets, which is much more efficient if we want a grid with not many entries, hence sparse grid layout.

We can start with a FloatLayout base, then all we need to do is set our grid children’s size_hint and pos_hint properties appropriately for the grid and call the FloatLayout‘s normal layout method to actually place them in the grid positions/shapes for us.

We can start by making our layout class:

from kivy.uix.floatlayout import FloatLayout
from kivy.properties import NumericProperty, ReferenceListProperty

class SparseGridLayout(FloatLayout):
    rows = NumericProperty(1)
    columns = NumericProperty(1)
    shape = ReferenceListProperty(rows, columns)

That creates a basic class that doesn’t have any more actual behavior than the FloatLayout alone, but has a few new properties. It’ll hopefully all make sense if you’ve used Kivy a little or followed my crash course, though the ReferenceListProperty may be new - this takes multiple other properties and lets us access them as a list, so for instance referencing or setting shape[0] really updates the rows property, including calling all its associated events etc.. At the same time, the shape is also a real property, with its own events. Do experiment with this if the explanation is not clear.

Now, to make our layout actually rearrange its children to the grid, we need to override its do_layout method, which is what’s called whenever it or its children are updated.

def do_layout(self, *args):
    shape_hint = (1. / self.columns, 1. / self.rows)
    for child in self.children:
        child.size_hint = shape_hint
        if not hasattr(child, 'row'):
            child.row = 0
        if not hasattr(child, 'column'):
            child.column = 0

        child.pos_hint = {'x': shape_hint[0] * child.row,
                          'y': shape_hint[1] * child.column}
    super(SparseGridLayout, self).do_layout(*args)

This iterates over all the SparseGridLayout‘s children, setting their size_hint so that they’ll fit exactly in a grid cell (as per the rows and columns properties we set above). It then checks if they have a row or column property, setting it to 0 if not - I’ve chosen that my rows and columns should be zero-indexed, you could modify that if you like. After that, it sets their pos_hint such that they’re placed in the right place. I’ve deliberately let this work with floats, so for instance they could be in column 2.5 to be halfway between the integer columns, so the layout is extra flexible.

The final step is calling the original do_layout method of the FloatLayout. The magic is that all we did is set the child widgets size_hint and pos_hint so that the widgets align to a grid - the FloatLayout itself already knows how to actually set their positions and sizes based on this information. By making use of Kivy’s existing layout abilities, we’ve saved ourself a lot of work.

Finally, I also added a class to represent entries in the grid:

class GridEntry(EventDispatcher):
    row = NumericProperty(0)
    column = NumericProperty(0)

This is very simple, but it means you can do for example:

class GridLabel(Label, GridEntry):
    pass

The GridLabel is thereby a Label that already has row and column properties, so it will behave properly in our SparseGridLayout. We don’t strictly need to do this, we could add the row and column any other way, but this is neat and makes it totally clear what we’re using our widgets for.

That’s everything! With just a few simple modifications we’ve made a whole new Layout widget that can place its children in rows and columns of a grid. Maybe you’ll find that useful, but more generally I hope this demonstrates the general principles of thinking about Layouts and using Kivy’s existing mechanisms to do most of the work.

You can find all this code at my sparsegridlayout github repository, which also includes a simple demonstration App so you can test the new layout if you like.