In the previous parts we saw how widgets on their own and widgets in layouts are positioned and scaled. Before we move on, let’s recapitulate briefly on what we already covered about scaling and positioning.
But before we delve into the topic, here’s some info for you.
*****
Table of Contents
Book Info
I just published my Kivy book, GUI Programming with Python and Kivy. It’s pretty long (over 800 pages) and comprehensive. And, which also counts, easy to read. The book contains lots of illustrations.
This book covers all the basics that you need to know to start programming GUI applications with Python and Kivy. Throughout the book we are building a GUI application from scratch, a fully functional game using all kinds of tools that Kivy has to offer. It’s our Slugrace project, but covered in a much more in-depth manner.
Each part of the book starts with a theoretical introduction of a topic or idea that we then implement in the project. I assume you have no prior knowledge of the Kivy library, but you should have at least some basic knowledge of the Python programming language, including the object-oriented programming paradigm as this is what we will be using a lot in this book.
The book covers all the basic elements of Kivy that you have to know, like widgets, layouts, Kivy ids and properties, graphics, screens, animation, sound. Finally we’ll deploy the app to Windows. It is pretty comprehensive and after you finish it, I’m sure you’ll be able to create your own awesome GUI apps of any kind, not just games.
I hope you will have at least as much fun reading the book as I had writing it.
As far as this Kivy series is concerned, the following parts will contain the most important elements covered in the book. However, some elements will be presented in a simplified way here on my blog or omitted completely.
____________
If you are interested, you can purchase the book in four versions. Here are the links:
1) ebook – pdf version on my website – in full color
Here you can see the description of the book, sample graphics from the book and the full table of contents.
2) ebook – Kindle version on Amazon – in full color
3) paperback version on Amazon – in black and white
4) paperback version on Amazon – in full color
*****
And Now Let’s Move On…
So, if you want to scale a widget which is not inside a layout, you use the properties size, width and height. If you want to position such a widget, you should use the pos property. All these properties use fixed numbers of pixels.
Now, if you want to scale a widget inside a layout, you should use one of the following properties: size_hint, size_hint_x or size_hint_y. They are used with proportions rather than fixed numbers of pixels, so the value you assign to them should be between 0 and 1. If you want to position a widget inside a layout, you use the pos_hint property, to which you assign a dictionary with one or more of the following properties: x, center_x, right (for horizontal positioning), y, center_y, top (for vertical positioning). The values are proportions again, so they should be in a range from 0 to 1. One more thing we discussed in the previous part is that the proportions may also be outside the range from 0 to 1 if you want the widget or part of it to be outside the visible program window.
Fine, you already know how to scale and position widgets, both on their own and inside layouts. But there are still some more options to explore. Let’s have a look at them now.
Using the x, center_x, right, y, center_y and top Properties In Layouts
You can use these properties with fixed numbers of pixels in layouts, but then you shouldn’t use the same properties in pos_hint. Here’s an example:
# File name: helloworld.kv
<CustomButton@Button>:
size_hint: .2, .1
<FloatLayout>:
CustomButton:
text: 'Button 1'
x: 0
y: 0
CustomButton:
text: 'Button 2'
x: 200
y: 200
If you run this program now, you will get the following window:
Now the left borders of the two buttons (x) and their bottom borders (y) will be always the same, even if you resize the window.
Using the x, center_x, right, y, center_y and top Properties Outside Layouts
Some time ago we were using the x, y, right and top properties on the root object (it was in the part about custom widgets). Here’s the code again:
Python file:
# File name: main.py
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.widget import Widget
class MyCustomButton(Button):
pass
class MyCustomWidget(Widget):
pass
class HelloWorldApp(App):
def build(self):
return MyCustomWidget()
if __name__ == '__main__':
HelloWorldApp().run()
kv file:
# File name: helloworld.kv
<MyCustomButton>:
size: 120, 40
color: .7, .6, .4, 1
<MyCustomWidget>:
TextInput:
hint_text: 'Type Something'
pos: root.x + 20, root.top - self.height - 20
size: 300, 40
MyCustomButton:
text: 'Press Me'
pos: root.x + 20, root.y + 20
MyCustomButton:
text: 'Press Me Too'
pos: root.right - self.width - 20, root.y + 20
Here the properties refer to the root object, which is the MyCustomWidet object. If you run this program again, you will see the following:
Try resizing the window and watch carefully how the elements behave. And now let’s rewrite the kv code as follows:
<MyCustomButton>:
size: 120, 40
color: .7, .6, .4, 1
<MyCustomWidget>:
TextInput:
hint_text: 'Type Something'
x: 20
y: 400
size: 300, 40
MyCustomButton:
text: 'Press Me'
center_x: 60
center_y: 20
MyCustomButton:
text: 'Press Me Too'
right: 300
top: 20
If you now run the app, it will look like this:
Using the pos Property Inside Layouts
The pos property is usually used for widgets, not for layouts. However you can use it for a layout if you need fixed numbers of pixels. Then, however, you must remember to not use pos_hint or otherwise it will override pos.
Here’s a simple example.
Python code:
import kivy
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
class HelloWorldApp(App):
def build(self):
return FloatLayout()
if __name__ == '__main__':
HelloWorldApp().run()
kv code:
# File name: helloworld.kv
<CustomButton@Button>:
size_hint: .2, .1
<FloatLayout>:
CustomButton:
text: 'Button 1'
pos: 20, 50
CustomButton:
text: 'Button 2'
pos: 500, 500
And here’s the program window:
If you resize the window, the positions of the buttons won’t change.
Using the size, width and height Properties Inside Layouts for Scaling
You can also use the size, width and height properties for scaling in layouts. You must remember, however, to set size_hint, size_hint_x or size_hint_y (for size, width and height respectively) to None. In case of size_hint you should actually set it to (None, None). Otherwise it won’t take effect.
Here’s an example. The Python file is just like before and here’s the kv file:
# File name: helloworld.kv
<FloatLayout>:
Button:
text: 'Button 1'
pos: 20, 50
size: 200, 20
Button:
text: 'Button 2'
pos: 500, 500
size_hint: None, None
size: 200, 20
If you now run the application, this is what you will get:
As you can see, although we set size to the same value for both buttons, 200 pixels wide and 20 pixels high, it only works with Button 2. This is because we didn’t set the first button’s size_hint property to (None, None). Let’s fix it:
# File name: helloworld.kv
<FloatLayout>:
Button:
text: 'Button 1'
pos: 20, 50
size_hint: None, None
size: 200, 20
Button:
text: 'Button 2'
pos: 500, 500
size_hint: None, None
size: 200, 20
Now it will work as expected for both buttons:
And now watch what will happen if we change just one line of code:
# File name: helloworld.kv
<FloatLayout>:
Button:
text: 'Button 1'
pos: 20, 50
# Here's the difference.
size_hint_x: None
size: 200, 20
Button:
text: 'Button 2'
pos: 500, 500
size_hint: None, None
size: 200, 20
Now, for the first button, we only set the size_hint_x property to None, not size_hint. This will cause the size property to take effect only partially, in horizontal direction:
So now you know all you need about positioning and scaling widgets, both inside and outside layouts. I’m using the plural form, layouts, here, although the only layout we’ve been using so far is FloatLayout. In the next part we’ll have a look at the other layouts that we’ll be making use of in our application.