Book Image

Kivy - Interactive Applications and Games in Python

By : Roberto Ulloa
Book Image

Kivy - Interactive Applications and Games in Python

By: Roberto Ulloa

Overview of this book

Table of Contents (13 chapters)
Kivy – Interactive Applications and Games in Python Second Edition
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Layouts


No doubt, fixed coordinates are the most flexible way to organize elements in an n-dimensional space; however, it is very time consuming. Instead, Kivy provides a set of layouts that will facilitate the work of organizing widgets. A Layout is a Widget subclass that implements different strategies to organize embedded widgets. For example, one strategy could be organizing widgets in a grid (GridLayout).

Let's start with a simple FloatLayout example. It works in a very similar manner to the way we organize widgets directly inside of another Widget subclass, except that now we can use proportional coordinates ("percentages" of the total size of the window) rather than fixed coordinates (exact pixels).

That means that we won't need the calculations we did in the previous section with self and root. Here is the Python code of an example that resembles the previous one:

68. # File name: floatlayout.py
69. 
70. from kivy.app import App
71. from kivy.uix.floatlayout import FloatLayout
72. 
73. class FloatLayoutApp(App):
74.     def build(self):
75.         return FloatLayout()
76. 
77. if __name__=="__main__":
78.     FloatLayoutApp().run()

There is nothing really new in the preceding code (floatlayout.py), except the use of FloatLayout (line 75). The interesting parts are in the corresponding Kivy language (floatlayout.kv):

79. # File name: floatlayout.py
80. <Button>:
81.     color: .8,.9,0,1
82.     font_size: 32
83.     size_hint: .4, .3
84. 
85. <FloatLayout>:
86.     Button:
87.         text: 'Hello'
88.         pos_hint: {'x': 0, 'top': 1}
89.     Button:
90.         text: 'World!'
91.         pos_hint: {'right': 1, 'y': 0}

In floatlayout.kv, we use two new properties – size_hint (line 83) and pos_hint (lines 88 and 91) .They are similar to size and pos but receive proportional coordinates with values ranging from 0 to 1; (0, 0) is the bottom-left corner and (1, 1) is the top-right corner. For example, the size_hint property on line 83 sets the width to 40 percent of the window width and the height to 30 percent of the current window height. Something similar happens to the pos_hint property (lines 88 and 91 but the notation is different – a Python dictionary where the keys (for example, 'x' or 'top') indicate which part of the widget is referenced. For example, 'x' is the left border.

Note that we use the top key instead of the y one on line 88 and the right key instead of the x one on line 91. The top and right keys respectively reference the top and right edges of Button. In this case, we could have also used x and y for both axes; for example, we could have written pos_hint: {'x': .85, 'y': 0} as line 91. However, the right and top keys avoid us some calculations, making the code clearer.

The next screenshot shows the result, and the available keys for the pos_hint dictionary:

The available pos_hint keys (x, center_x, right, y, center_y, and top) are useful to align the edges or for centering. For example, pos_hint: {'center_x':.5, 'center_y':.5} would align a widget in the middle no matter the size of the window.

We could have used the top and right properties with the fixed positioning of widgets2.kv (line 64 and 67), but note that pos doesn't accept Python dictionaries ({'x':0,'y':0}), just pairs of values exclusively corresponding to (x, y). Therefore, instead of using the pos property, we should use the x, center_x, right, y, center_y, and top properties directly (not dictionary keys). For example, instead of pos: root.x, root.top - self.height (line 64), we should have used:

x: 0
top: root.height

Note

The properties x, center_x, right, y, center_y, and top always specify fixed coordinates (pixels), and not proportional ones. If we want to use proportional coordinates, we have to be inside a Layout (or an App) and use the pos_hint property.

We can also force a Layout to use fixed values, but there can be conflicts if we are not careful with the properties. If we use any Layout; pos_hint and size_hint take priority. If we want to use fixed positioning properties (pos, x, center_x, right, y, center_y, top), we have to ensure that we are not using the pos_hint property. Second, if we want to use the size, height, or width properties, then we need to set a None value to the size_hint axis we want to use with absolute values. For example, size_hint: (None, .10) allows us to use height property, but it keeps the width of 10 percent for the window's size.

The following table summarizes what we have seen about the positioning and sizing properties. The first and second columns indicate the name of the property and its respective value. The third and fourth column indicate whether it is available for layouts and for widgets.

Property

Value

For layouts

For widgets

size_hint

A pair w, h: w, and h express a proportion (from 0 to 1 or None).

Yes

No

size_hint_x

size_hint_y

A proportion from 0 to 1 or None, indicating width (size_hint_x) or height (size_hint_y).

Yes

No

pos_hint

Dictionary with one x-axis key (x, center_x, or right) and one y-axis key (y, center_y, or top). The values are proportions from 0 to 1.

Yes

No

size

A pair w, h: w and h indicating fixed width and height in pixels.

Yes, but set size_hint: (None, None)

Yes

width

Fixed number of pixels.

Yes, but set size_hint_x: None

Yes

height

Fixed number of pixels.

Yes, but set size_hint_y: None

Yes

pos

A pair x, y indicating a fixed coordinate (x, y) in pixels.

Yes, but don't use pos_hint

Yes

x, right or center_x

Fixed number of pixels.

Yes, but don't use x, right or center_x in pos_hint

Yes

y, top or center_y

Fixed number of pixels.

Yes, but don't use y, top or center_y in pos_hint

Yes

We have to be careful because some of the properties behave differently depending on the layout we are using. Kivy currently has eight different layouts, which are described in the following table. The left-hand side column shows the name of the Kivy layout class. The right-hand side column describes briefly how they work.

Layout

Details

FloatLayout

Organizes the widgets with proportional coordinates by the size_hint and pos_hint properties. The values are numbers between 0 and 1, indicating a proportion to the window size.

RelativeLayout

Operates in the same way that FloatLayout does, but the positioning properties (pos, x, center_x, right, y, center_y, top) are relative to the Layout size and not the window size.

GridLayout

Organizes widgets in a grid. You have to specify at least one of two properties – cols (for columns) or rows (for rows).

BoxLayout

Organizes widgets in one row or one column depending on whether the value of the orientation property is horizontal or vertical.

StackLayout

Similar to BoxLayout, but it goes to the next row or column when it runs out of space. There is more flexibility to set the orientation. For example, rl-bt organizes the widgets in right-to-left, bottom-to-top order. Any combination of lr (left to right), rl (right to left), tb (top to bottom), and bt (bottom to top) is allowed.

ScatterLayout

Works in a similar manner to RelativeLayout but allows multitouch gesturing for rotating, scaling, and translating. It is slightly different in its implementation, so we will review it later on.

PageLayout

Stacks widgets on top of each other, creating a multipage effect that allows flipping of pages using side borders. Very often, we will use another layout to organize elements inside each of the pages, which are simply widgets.

The Kivy API (http://kivy.org/docs/api-kivy.html) offers a detailed explanation and good examples of each of the layouts. The behavioral difference of the properties depends on the layout, and it is sometimes unexpected. Here are some hints that will help us in the GUI building process:

  • size_hint, size_hint_x, and size_hint_y work on all the layouts (except PageLayout), but the behavior might be different. For example, GridLayout will try to take an average of the x hints and y hints on the same row or column respectively.

  • You should use values from 0 to 1 with size_hint, size_hint_x, and size_hint_y. However, you can use values higher than 1. Depending on the layout, Kivy makes the widget bigger than the container or tries to recalculate a proportion based on the sum of the hints on the same axis.

  • pos_hint only works for FloatLayout, RelativeLayout, and BoxLayout. In BoxLayout, only the axis-x keys (x, center_x, right) work in the vertical orientation and vice-versa for the horizontal orientation. An analogous rule applies for the fixed positioning properties (pos, x, center_x, right, y, center_y, and top).

  • size_hint, size_hint_x, and size_hint_y can always be set as None in favor of size, width, and height.

There are more properties and particularities of each layout, but with the ones covered, we will be able to build almost any GUI. In general, the recommendation is to use the layout as it is and, instead of forcing it with the properties we are using, it is better to have more layouts and combine them to reach our goals. The next section will teach us how to embed layouts and will offer more comprehensive examples.