things i want to remember, things i want to share

Développeur Python et adepte Linux depuis 2005, Core développeur Kivy, passionné par beaucoup trop de choses.
Profil Github gpg signature bitcoin address

Entries tagged “sizing”

Position/Size of widgets in kivy.

written by tshirtman, on 1/16/14 12:55 AM.

I see it’s a common struggle for people to understand how to manage size and positions of the widgets in kivy.

There is not much to it, really, just a few principles to understand, but they are better explained by example, i believe.

dumb positionning

Let’s create a root widget, and put two buttons in it.

root = Widget()
b1 = Button()
b2 = Button()

What will happen when i return root to be used as my root widget? As a root widget, it will have all the space for itself, the two buttons, however, will only use their default size, which is (100, 100), and will use their default position, which is (0, 0), the bottom-left corner of the screen.

We can change b1 and b2 positions to absolute values, let’s change line 2 and 3 to:

b1 = Button(pos=(100, 100))
b2 = Button(pos=(200, 200))

something a little smarter

Now, that doesn’t make for a very flexible UI, if you ask me, it would be better to use the parent size to decide where to place the buttons, no?

b1 = Button(pos=(root.x, root.height / 2))
b2 = Button(pos=(root.width - 100, root.height / 2))

No, that’s not much smarter, it’s still quite dumb actually, it doesn’t even work, why? because we just instanciated root, it’s not even the root widget yet, it doesn’t have its final size, so our widgets will use the default value of (100, 100), for their calculations, no - no.

Let’s fix this with bindings.

b1 = Button()
root.bind(size=reposition_b1, pos=reposition_b1)
b2 = Button()
root.bind(size=reposition_b2, pos=reposition_b2)

Where these two functions will be along the lines of:

def reposition_b1(root, *args):
    b1.pos = root.x, root.height / 2 - b1.height / 2

Also, widget have nice alias properties for things like height / 2, x + width, x + width / 2, here is a quick table:

right = x + width
top = y + height
center_x = x + width / 2
center_y = y + height / 2
center = (center_x, center_y)

and actually, pos is just an alias property for (x, y). Alias Properties works both ways, so we can use them to set our positions in a simpler way.

def reposition_b1(root, *args):
    b1.x = root.x
    b1.center_y = root.center_y

A lot of work for not so much, right? That’s because we are not using the right tools!

Let’s jump on a layout, specifically FloatLayout.

FloatLayout to the rescue

Layouts are here to make our life easier when constructing an UI.

FloatLayout is very flexible, it lets you set rules for positions, or do things in the absolute way.

root = FloatLayout()
b1 = Button(pos_hint={'x': 0, 'center_y': .5})
b2 = Button(pos_hint={'right': 1, 'center_y': .5})

pos_hint will make the values relative to the size/position of the parent. So here, for b1 x will be the x of the parent, and center_y will be at the middle between y and top.

Now, if you run this, you may get a surprise, because FloatLayout also made b1 and b2 sizes relative to root.size, and the default value being (1, 1), they both have the same size as the root widget, sometime you want to keep that relative, maybe with a different value, sometime you want to have them keep the value passed in size (or default size value), if so, you can pass (None, None) to size_hint.

b1 = Button(pos_hint={'x': 0, 'center_y': .5}, size_hint=(None, None))


I’ll probably do other posts on the subject, because there is much more to it, but the basic principles are here. I anyway really encourage you to look at this section of the documentation, which go further with the various kind of layouts you have access to.


#FIXME 3G absurd ad_sense alterway aléatoire android animation anonymity atheism bach backlog bash bitcoins blog blogging boldness book books boulot bricolage bépo C canvas captcha captures carte SD censure christianity chroot CI CLI cli cloudwatt code colors comfort zone command line community company life conferences contest copwatch copwatchnord-idf core-devs cours ct705 culture deb debian debug deformation dehors dessin dev distribute distribution docker débutant déploiement développement ebooks eeepad eeepc effect ego empty en escher event firefly flappy bird flask fosdem foss fr fun game garden gdb geek culture git github goals graphics grrr gödel hack hackathon hacked hacking health hooks i3 images IMAP inspirational install isync java jenkins jeu jeu video jinja2 jni keyboard keynav kivy kv lame learning lib libre life linux lol macosx magnet mail mailing-list mails maths mbsync meetings memory leak mesh meta mint mirroir MIT module motivational mouse museomix mutt nexus7 no-mouse notmuch nottoomuch offlineimap onycroit opencourseware osc packaging paris passphrase password patch pentacatyl people perte de données ping pip planning plugin positioning pr procrastination programmation progress project projet property proudhon proxy psf publisher/consumer pull-down pygame pyjnius pypi python pythonar qtile raid rapsberry pi reading recorder references release religion responsive review reviews réseau réseaux sociaux résurection salon screenshots script self service shows shutil shyness sizing solib sortie sousous!!! spam spritz stash status systeme système templating terminal texture texture coordinates Thomas Paine thread thème tiling time time management. tip tips tools transformer tutorial tv twitter typematrix typing ubuntu ubuntu-fr ultimate-smash-friends unity update upload images useless usf utils value VDM video vie/mort vim virtualenv visite widget windows wm wmii work workflow workflow. zine études