Kivy 1.9 released

Kivy 1.9 has just been released! This has been a long time in the making, for no very good reason, but now you can take advantage of all our many new features in the stable branch. You can find the full changelog at the official mailing list announcement.

This big release includes almost 2500 new commits (about 30% of the total in Kivy!) from nearly 100 different contributors, including both significant changes and many smaller fixes. I’ll showcase a few of the most interesting ones below; these are also listed in the changelog above, along with more information about the many other changes.

One of the most major internal changes is a shift to using SDL2 as our window and other backend provider on almost all platforms - only Android still uses the old pygame/SDL backend. This shouldn’t change the external user API at all, but directly makes available features that Pygame lacked such as proper support for high-DPI displays and the ability to retain an OpenGL context on resize (previously lacking in Windows and OS X), as well as resolving some old Pygame related bugs and hopefully making further low level customisation easier in the future. Although this doesn’t change at all how you interact with Kivy, it’s a big improvement behind the scenes. This also means that Pygame is now deprecated on platforms where SDL2 already works; we’ll continue to support it for a while and it’s unlikely to stop working even after that, but it’s no longer a focus.

Image of Kivy on a retina display with high DPI mode

Image of Kivy on a retina display without high DPI mode

These images show the difference in Kivy rendering on the same (OS X retina) screen, first with the new SDL2 high DPI mode enabled so that Kivy has full awareness of the true resolution, and second letting the operating system scale up a smaller rendered result - the latter is default for applications that do not declare DPI awareness, but Kivy will now always render properly as in the first image. The difference is dramatic, and we’re glad to be able to properly support these resolutions. This improvement is currently enabled only on OS X, but the equivalent Windows fix will be merged shortly and the behaviour should already be correct on Linux.

A different change that may be more directly useful in your applications is the new EffectWidget, which behaves as a normal RelativeLayout but also lets you add one or more shader effects to its rendered output. The API is designed to make it very easy to create simple effects even without knowing about GLSL, in a way that can easily be combined with existing applications.

Image of Kivy effectwidget

This above screenshot demonstrates the EffectWidget via one of the new Kivy examples; the kv code of the left and right is identical, except the right hand side includes colour mixing and pixelation effects. Since these are applied at a very low level they are very efficient (although not optimised for too many effects at once) and can be applied even to video or moving scenes such as in games.

Image of the Kivy SVG example, including the famous svg tiger

One feature that has been heavily requested by users is SVG support for Kivy, and preliminary support is included in 1.9! This is still experimental and currently supports only Python 2, but much of the work has been done and even complex SVG images are reproduced well. The above image shows one of the new SVG examples, including the famous tiger.

There are also some nice new features that can’t be captured so easily in a screenshot. One is the addition of a rebind option to Kivy properties. This resolves a problem that arose with code like

# In python
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
class MyButton(Button):
    some_ref = ObjectProperty(None, rebind=True)

# And in kv language
<MyButton>:
    text: self.some_ref.text if self.some_ref else ''

The problem here was that kv could only bind automatically to the first value of self.some_ref, so the text of the MyButton instance would never update, and it is difficult to improve this internally without dramatic slowdowns from checking if many objects have changed. The new rebind option makes it possible to enable this second level of binding in select places where appropriate; it won’t be necessary or useful to everyone, but it’s a convenient feature when really necessary.

Other new features include a new, faster video provider via Cython and ffmpeg, Window modes to detect and react to the presence of a software keyboard on Android, an internal rewiring of focus handling for widgets, and many many other bugfixes and smaller new features.

Thanks to all our contributors, and enjoy the new release!

Posted in Kivy, Python, release | Comments Off

Kivy in GSOC 2015

Kivy will be participating in the Google Summer of Code 2015 (GSOC), under the Python Software Foundation umbrella. Applications are welcomed not just for the Kivy framework itself but on all the projects managed by the Kivy organisation including Python-for-Android, Kivy-iOS, PyJNIus, PyOBJus, Plyer and Buildozer. As such, GSOC projects can range in focus and difficulty from those that should be accessible to intermediate Python users to low level work making use of Cython, or interacting with Java and Objective C on mobile platforms.

Our page of GSOC information and suggested projects is available here and includes ideas touching all of these areas. However, these are just guidelines and suggestions; if you have a different idea, we’re happy to discuss it. Prospective GSOC students should introduce themselves on the kivy-dev mailing list, and also say hello on our IRC channel, discussions there will be an important part of any application.

Beyond that, check out the project page linked above, and good luck with your applications.

Posted in gsoc, Kivy, Python | Comments Off

Hy (lisp) and Kivy

I was recently reminded of the super cool Hy project. Hy is a lisp that compiles to python’s own abstract syntax tree, so it works perfectly with existing Python code (including with Cython etc.) but also exposes all the power of lisp.

For instance, here’s a simple Kivy application that simply displays a Label with the obligatory Hy pun, but written in Hy. I’ve included the normal Python code as comments so you can see exactly what the code is doing. If you’re new to Kivy and want to understand what the code actually does, check out my Kivy crash course:

(import [kivy.app [App]]
        [kivy.uix.label [Label]])
;; from kivy.app import App
;; from kivy.uix.label import Label


(defclass HyApp [App]
  [[build
    (fn [self]
      (apply Label [] {"text" "Hy world!"
                       "font_size" 100
                       "color" (, 0 1 0 1)}))]])

;; class HyApp(App):
;;     def build(self):
;;         return Label(text="Hy world!",
;;                      font_size=100,
;;                      color=(0, 1, 0, 1))

(.run (HyApp))

;; HyApp().run()

This works great, though only with python3 due to a small bug in Kivy - the kwargs of Label are eventually read in cython with a variable typed as str, which in python2 excludes the unicode Hy passes. Still, that’s not surprising even if it’s cool - part of the point of Hy is to interoperate perfectly with Python.

A tougher problem is how to use Kivy’s kv language with Hy. kv is a simple domain-specific language for declaring widget trees, making it easy to define event-driven interactions between the different properties of widgets. It’s really useful and we tend to recommend using it as much as possible, so it’d be great to have it work with Hy. I won’t explain the language here (you can see the Kivy doc or my own tutorials), but the key point is that much of it consists of interpreting normal python code, which I’d like to replace with Hy code.

It turns out making this work is actually really easy. Here’s the relevant part of lang.py in Kivy’s source, the file containing the code for the kv parser:

self.co_value = compile(value,
                        self.ctx.filename or '<string>',
                        mode)

value is the string of Python code whose output will set a property of a widget or be run when an event is registered. For instance, a line of kv code might be color: (1, 0, 0, some_function_of(self.alpha)), in which case value would be "(1, 0, 0, some_function_of(self.alpha))".

To make a line of Hy code work instead of Python, we can do an awful hack, replacing the above line with:

if value[-3:] == '#hy':
    from hy.importer import (ast_compile,
                             import_buffer_to_ast)
    from hy.compiler import hy_compile
    import ast
    ast_part = import_buffer_to_ast(value[:-3], '<stdin>')
    if mode == 'eval':
        ast_part = ast.Expression(ast_part.body[0].value)
    self.co_value = ast_compile(ast_part,
                                self.ctx.filename or '<string>',
                                mode)
else:
    self.co_value = compile(value,
                            self.ctx.filename or '<string>',
                            mode)

This new code checks if the line of Python ends with #hy, and if so runs the code through Hy’s own equivalent of compile (effectively parsing the Hy code to ast before doing the same thing as the normal Python code). I also have the extra muckiness of taking apart this ast if the compilation is in eval mode, because I couldn’t get Hy to return an ast.Expression in the first place. This is probably very easily and neatly fixed, but I’ve left it like this because a silly hack is good enough for a proof of concept. All credit for this part goes to the friendly Hy people on their irc channel, #hy on Freenode.

With this in place, we can write a new Python program, but this time use our Hy+kv language to define the widget tree. Here’s the new code on the Python (now Hy) side:

(import [kivy.app [App]]
        [kivy.lang [Builder]])

;; from kivy.app import App
;; from kivy.lang import Builder

(setv root (Builder.load_file "hy.kv"))

;; root = Builder.load_file("hy.kv")

(defclass HyApp [App]
  [[build
    (fn [self]
      root)]])

;; class HyApp(App):
;;     def build(self):
;;         return root

(.run (HyApp))

;; HyApp().run()

This obviously depends on our new kv file, "hy.kv", whose contents are as below. Kivy users will notice this file would normally be loaded automatically because the app name starts with Hy, but something about Hy seems to have broken this so I manually loaded it with the Builder.

BoxLayout:
    orientation: "vertical"
    Label:
        id: label
        text: "What is your name?"
    TextInput:
        id: ti
        text: ""
    Button:
        text: (.format "Greet me as {}" ti.text) #hy
        on_press: (setv label.text (.format "Hy there {}" ti.text)) #hy

# as normal kv, except the final 2 rules would normally be:
# text: "Greet me as {}".format(ti.text)
# on_press: label.text = "Hy there {}".format(ti.text)

Running the code…it works perfectly! Here’s a picture after typing my name and clicking the button:

Image of Kivy program after running Hy code

For those not familiar with kv, one of its features is that it automatically detects property changes and updates dependent properties - in this case, the text of the button should change every time ti.text changes (i.e. every time a letter is typed in the TextInput). This works too with the new Hy interface, because the parser detects the dependency by searching the string for substrings like ti.text, and these have been unmodified by the move to Hy. Hy does support syntax that would break this relationship, but it’s quite convenient as it is.

So…there we go, Hy support in Kivy! The hack to make kv language work is pretty terrible, but it looks like a proper solution with this basis would work fine - we could subclass the kv parsing Builder to support a Hy loading option, removing the need for the #hy at the end of each Hy line.

Posted in android, hy, Kivy, kv, Python | Comments Off

Updating canvas instructions declared in Python

Continuing the theme of my last few posts, a common problem for new kivy users is creating canvas instructions that follow their parent widgets. For instance, here’s some code for a custom widget that tries to draw a red rectangle in its upper-right corner - this is fairly standard kivy code to draw directly on the widget canvas, and is documented here.

from kivy.uix.widget import Widget
from kivy.graphics import Rectangle, Color

class CornerRectangleWidget(Widget)
    def __init__(self, **kwargs):
        super(CornerRectangleWidget, self).__init__(**kwargs)

        with self.canvas:
            Color(1, 0, 0, 1)  # set the colour to red
            self.rect = Rectangle(pos=self.center,
                                  size=(self.width/2.,
                                        self.height/2.))

This looks like it will create a red rectangle, whose length is half the parent size in both directions, and whose position is the parent centre.

The surprise is that this is actually not what happens. Instead, the rectangle is always positioned at (50, 50) with size (50, 50), regardless of where the widget appears.

The reason for this is that these values really are based on the pos and size of the widget at the point where the canvas code was run; all widgets have a default position of (0, 0) and size of (100, 100), and this will not necessarily be updated (for instance by a parent layout class) until after their __init__ is run. However, the Rectangle properties receive only these initial values, and don’t know about the new position of the widget.

The solution is to simply hook into kivy’s event system to update the rectangle pos and size ourselves whenever the widget changes:

from kivy.uix.widget import Widget
from kivy.graphics import Rectangle, Color

class CornerRectangleWidget(Widget)
    def __init__(self, **kwargs):
        super(CornerRectangleWidget, self).__init__(**kwargs)

        with self.canvas:
            Color(1, 0, 0, 1)  # set the colour to red
            self.rect = Rectangle(pos=self.center,
                                  size=(self.width/2.,
                                        self.height/2.))

        self.bind(pos=self.update_rect,
                  size=self.update_rect)

    def update_rect(self, *args):
        self.rect.pos = self.pos
        self.rect.size = self.size

Now whenever the widget pos or size changes, our new method is called and the rectangle resized or repositioned as necessary. It will always track the widget’s upper right corner, so we get the visual effect we were originally looking for.

Of course, an even better solution (where possible) is to use kv language:

<CornerRectangleWidget@Widget>
    canvas:
        Color:
           rgba: 1, 0, 0, 1
        Rectangle:
           pos: self.center
           size: self.width / 2., self.height / 2.

This is shorter, simpler and clearer. We don’t need to manually set up the binding because kv automatically detects that we referred to properties of the parent widget and creates it automatically - something that isn’t really possible in python. This is one reason that we recommend using kv language wherever possible.

Posted in canvas instructions, Kivy, Python | Comments Off

Wrapping text in Kivy’s Label

Another Kivy question that I often see (particularly recently for some reason) is about using the Label widget - how to have text wrap automatically, or the opposite, how to have the label automatically grow to accommodate its text. I’ve covered this before in the 9th Kivy crash course video, but here’s a quick write up of the basics.

The first thing to realise is how the Label works by default, it takes the text and draws it to a texture - in practical terms that’s an image of the characters. Everything you might want to do with the Label revolves around what this texture is really doing. By default, it does not wrap the text (unless you put in linebreak characters manually), it just makes one long image on a single row. This image is is placed right in the middle of the label, centered in both directions, which is fine for short text snippets but will overhang the Label on both sides if the text is too long.

This also leads to some other annoying behaviour - as well as the text not wrapping, you might have observed that the halign and valign properties seem to do nothing by default. This is because they orient things not inside the widget, but inside the texture…which is the exact size it needs to contain the text so alignments change nothing.

To solve all these problems, you can manually set the size of the texture with text_size, a tuple of width and height, e.g.

Label:
    text_size: self.size

This reverses the default behaviour - instead of the texture growing to fit the text, the text will be wrapped to fit the texture! If there is space to spare, it is aligned within the texture according to the halign and valign properties.

The Label also has another useful property, the texture_size, which holds the actual size of the texture. You can use that do bind behaviour to the size of the text. For instance, a common requirement is to create a Label that grows as long as it needs to contain its text, but which wraps it to a certain width. We can combine both of the above ideas to accomplish this:

Label:
    size_hint_y: None
    text_size: self.width, None
    height: self.texture_size[1]

If you (for instance) place this label in a ScrollView, it will be Scrollable over exactly the right distance to fit in all the text.

Posted in Kivy, label, Python | Comments Off

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!

Posted in contest, Kivy, Python | Comments Off

Kivy Programming Contest 2014

Kivy is organizing its second application development contest!. This is a great chance for users both new and experienced to show off their skills and compete for prizes. Entries will be judged on a range of criteria accessible to both new and experienced programmers, so don’t be afraid to dive in!

poster_1

A big big thanks to the Python Software Foundation for being our first and lovely sponsor :)

Posted in Coding, Kivy, Planet Python | Comments Off

2048, in Python / Kivy

If you don’t know the 2048 puzzle yet, you should. But be careful, it’s time consuming. I won’t go on the whole clone history of the game, but will just say that if you want to play it on the Web, play to the Gabriel Cirulli 2048. The author said it wont make an official iOS/Android app, so… let’s give Kivy a try :)

device-2014-03-15-114048

Only 2 hours of coding where needed for the first published version of the game. Then i learned on the Google Play Game services APIs for integrating a leaderboard and achievements. And after a couple of hours during the night, what i can say is: Be patient! Even if you follow the documentation carefully, you need to wait few hours before your app_id works on their server, even in test mode. There never warn us about it.

When the setup is done and it start working, it is easy to login:

PythonActivity = autoclass('org.renpy.android.PythonActivity')
    GameHelper = autoclass('com.google.example.games.basegameutils.GameHelper')

    gh_instance = GameHelper(PythonActivity.mActivity, GameHelper.CLIENT_ALL)
    gh_instance_listener = GameHelperListener()
    gh_instance.setup(gh_instance_listener)
    gh_instance.onStart(PythonActivity.mActivity)
    android.activity.unbind(on_activity_result=_on_activity_result)
    android.activity.bind(on_activity_result=_on_activity_result)

That’s how you can unlock achievement:

# uid is the Google UID for the achievement you want
if gh_instance.isSignedIn():
    Games.Achievements.unlock(gh_instance.getApiClient(), uid)

And put the user score on the leaderboard:

# uid is the Google UID for the leaderboard you've created.
# You can have multiple leaderboard.
if gh_instance.isSignedIn():
    Games.Leaderboards.submitScore(gh_instance.getApiClient(), uid, score)

There is a little more code around that, but globally, using the new Play Games services APIs is now easy. I hope this little piece of code will help peoples to integrate it into their app. Somebody need to start a Python library for managing Google Play API and Game Center for iOS.

Have a look at the source code for an example of the integration with the Play Games services APIs :)


Get it on Google Play

Posted in Coding, Kivy, Planet Python | Comments Off

Prepare for the Kivy contest #2

Developers, developers… rejoice!

kivy contest

The kivy project is organizing a second contest!

From the 15th of April, when the theme will be revealed, to the 15th of May, the final deadline, all the interested candidates will compete to produce the nicest application possible, once month to make the difference, and collect prices :).

Prizes will be announced before the beginning of the contest, the python software foundation kindly offered to sponsor the contest, if you are or know somebody interested in sponsoring the contest, please contact us at contest@kivy.org.

Comments Off

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!

Posted in Kivy, Python | Comments Off