Embedding layouts
Layouts are subclasses of widgets. We have already been embedding widgets inside widgets since the beginning (line 43) and it won't matter if the widgets we are embedding are also layouts. In this section, we will work with a comprehensive example to explore the effect of the position properties discussed in the previous section. The example is not visually appealing, but it will be useful to illustrate some concepts and to provide some code that you can use to test different properties. The following is the Python code (layouts.py
) for the example:
92. # File name: layouts.py 93. from kivy.app import App 94. from kivy.uix.gridlayout import GridLayout 95. 96. class MyGridLayout(GridLayout): 97. pass 98. 99. class LayoutsApp(App): 100. def build(self): 101. return MyGridLayout() 102. 103. if __name__=="__main__": 104. LayoutsApp().run()
Nothing new in the preceding code – we just created MyGridLayout
. The final output is shown in the next screenshot, with some indications about the different layouts:
In this screenshot, six different Kivy layouts are embedded into a GridLayout
of two rows (line 107) in order to show the behavior of different widget properties. The code is straightforward, although extensive. Therefore, we are going to study the corresponding Kivy language code (layouts.kv
) in five fragments. The following is fragment 1:
105. # File name: layouts.kv (Fragment 1) 106. <MyGridLayout>: 107. rows: 2 108. FloatLayout: 109. Button: 110. text: 'F1' 111. size_hint: .3, .3 112. pos: 0, 0 113. RelativeLayout: 114. Button: 115. text: 'R1' 116. size_hint: .3, .3 117. pos: 0, 0
In this code, MyGridLayout
is defined by the number of rows with the rows
property (line 107). Then we add the first two layouts – FloatLayout
and RelativeLayout
with one Button
each. Both buttons have a defined property of pos: 0, 0
(lines 112 and 117) but note in the previous screenshot that the Button
F1 (line 109) is in the bottom-left corner of the whole window, whereas the Button
R1 (line 114) is in the bottom-left corner of RelativeLayout
. The reason is that the pos
coordinates in FloatLayout
are not relative to the position of the layout.
Note
Note that pos_hint
always uses relative coordinates, no matter the layout we are using. In other words, the previous example wouldn't have worked if we were using pos_hint
instead of pos
.
In fragment 2, one GridLayout
is added to MyGridLayout
:
118. # File name: layouts.kv (Fragment 2) 119. GridLayout: 120. cols: 2 121. spacing: 10 122. Button: 123. text: 'G1' 124. size_hint_x: None 125. width: 50 126. Button: 127. text: 'G2' 126. Button: 128. text: 'G3' 129. size_hint_x: None 130. width: 50
In this case, we use the cols
property to define two columns (line 120) and the spacing
property to separate the internal widgets by 10 pixels from each other (line 121). Also, note in the previous screenshot that the first column is thinner than the second. We achieved this by setting the size_hint_x
to None
and width
to 50
of the buttons G1 (line 122) and G3 (line 128).
In fragment 3, an
AnchorLayout
is added:
131. # File name: layouts.kv (Fragment 3) 132. AnchorLayout: 133. anchor_x: 'right' 135. anchor_y: 'top' 136. Button: 137. text: 'A1' 138. size_hint: .5, .5 139. Button: 140. text: 'A2' 141. size_hint: .2, .2
We have specified the anchor_x
property to right
and the anchor_y
property to top
(line 134 and 135) in order to arrange elements in the top-right corner of the window as shown in the previous screenshot with both buttons (lines 136 and 139). This layout is very useful to embed other layouts inside it, for example, top menu bars or side bars.
In fragment 4, a BoxLayout
is added:
142. # File name: layouts.kv (Fragment 4) 143. BoxLayout: 144. orientation: 'horizontal' 145. Button: 146. text: 'B1' 147. Button: 148. text: 'B2' 149. size_hint: 2, .3 150. pos_hint: {'y': .4} 151. Button: 152. text: 'B3'
The preceding code illustrates the use of BoxLayout
with the orientation
property set to horizontal
. Also, the lines 149 and 150 show how to use size_hint
and pos_hint
to move the button B2 further up.
Finally, fragment 5 adds a StackLayout
:
153. # File name: layouts.kv (Fragment 5) 154. StackLayout: 155. orientation: 'rl-tb' 156. padding: 10 157. Button: 158. text: 'S1' 159. size_hint: .6, .2 160. Button: 161. text: 'S2' 162. size_hint: .4, .4 163. Button: 164. text: 'S3' 165. size_hint: .3, .2 166. Button: 167. text: 'S4' 168. size_hint: .4, .3
In this case, we added four buttons of different sizes. It is important to pay attention to the previous screenshot on embedding layouts to understand the rules that we applied to organize the widgets with the orientation
property set to rl-tb
(right to left, top to bottom, line 155). Also note that the padding
property (line 156) adds 10 pixels of space between the widgets and the border of StackLayout
.