Kivy - Interactive Applications and Games in Python - Second Edition - Sample Chapter
Kivy - Interactive Applications and Games in Python - Second Edition - Sample Chapter
ee
Sa
pl
Preface
Mobile devices have transformed the way applications are perceived. They
have increased in interaction types; the user now expects gestures, multi-touches,
animations, responsiveness, virtual keyboards, and magic-pens. Moreover,
compatibility has become a must if you want to avoid the barriers imposed by
major operating systems. Kivy is an open source Python solution that covers these
market needs with an easy-to-learn and rapid development approach. Kivy continues
to grow fast and two versions have been released since the first publication of this
book in September 2013. Thanks to an enthusiastic community, Kivy is making its way
in an extremely competitive territory in which it stands out for offering both a crossplatform and efficient alternative to native development and HTML5.
This book introduces you to the Kivy world, covering a large variety of important
topics related to interactive applications and games development. The components
presented in this book were selected according to their usefulness for developing
state-of-art applications and also for serving as an example of broader Kivy
functionalities. Following this approach, the book covers a big part of the
Kivy library.
This book provides you with examples to understand their use and how to
integrate the three projects that come with this book. The first one, the comic
creator, exemplifies how to build a user interface (Chapter 1, GUI Basics Building
an Interface), how to draw vector shapes in the screen (Chapter 2, Graphics the
Canvas), how to bind user interactions with pieces codes (Chapter 3, Widget Events
Binding Actions), and other components related to improving the user experience
(Chapter 4, Improving the User Experience). The second project, Invaders Revenge, is an
interactive game that introduces you to the use of animations, scheduling of tasks,
keyboard events, and multi-touch control (Chapter 5, Invaders Revenge an Interactive
Multi-touch Game). The third project, Kivy Player, teaches how we can control video
streams with a modern design and responsive interactions to maximize the use of the
screen (Chapter 6, Kivy Player a TED Video Streamer).
Preface
Occasionally, this book explains some technical but important Kivy concepts that are
related to the Kivy class structure and implementation, or the order and strategies to
draw on the screen. These explanations give the reader some insights into the Kivy
internals that will help them solve potential problems when they develop their own
projects. Even though they are not necessary for the comprehension of the main
topics of this book, they will become important lessons when the reader faces new
situations implementing their own applications.
This book grabs the reader's attention by stating interesting programming scenarios.
The sections are generally short and straightforward, making the learning process
constant. These short sections will also serve as a reference when the reader finishes
the book. However, serving as a reference doesn't prevent the text from achieving the
main goal, which is teaching bigger projects that connect the small topics. At the end
of this book, the reader will feel comfortable to start their own project.
[1]
This book requires some knowledge of Python, and very basic terminal skills, but
also it requires some understanding of Object-Oriented Programming (OOP)
concepts. In particular, it is assumed that you understand the concept of inheritance
and the difference between instances and classes. Refer to the following table to
review some of these concepts:
Concept
OOP
Inheritance
Instance
Class
URL
http://en.wikipedia.org/wiki/Object-oriented_
programming
http://en.wikipedia.org/wiki/Inheritance_(objectoriented_programming)
http://en.wikipedia.org/wiki/Instance_(computer_
science)
http://en.wikipedia.org/wiki/Class_(computer_
science)
Before we start, you will need to install Kivy. The installation process for all different
platforms is documented and regularly updated on the Kivy website: http://kivy.
org/docs/installation/installation.html.
All code in this book has been tested with Kivy 1.9.0 and both
Python 2.7 and Python 3.4 (but 3.3 should work fine as well).
Note that packaging support for mobile is not yet complete
for Python 3.3+. For now, if we want to create mobile apps for
Android or iOS, we should use Python 2.7. If you want to know
your Python version, you can execute python -V in a terminal
to check your installed Python version.
In this chapter, we start by creating user interfaces using one of Kivy's most fun
and powerful components the Kivy language (.kv). The Kivy Language separates
logic from presentation in order to keep an easy and intuitive code; it also links
components at an interface level. In future chapters, you will also learn how to build
and modify interfaces dynamically using pure Python code and Kivy as a library.
[2]
Chapter 1
Here is a list of all the skills that you are about to learn:
This chapter covers all the basics for building a Graphical User Interface (GUI)
in Kivy. First, we will learn techniques to run an application and how to use and
integrate widgets. After that, we will introduce the main project of the book, the
Comic Creator, and program the main structure of the GUI that we will continue
using in the following two chapters. At the end of this chapter, you will be able to
build a GUI starting from a pencil and paper sketch, and also learn some techniques
to make the GUI responsive to the size of the window.
[3]
In order to run the code, you open a terminal (line of commands or console)
and specify the following command in Windows or Linux: python hello.py
--size=150x100 (--size is a parameter to specify the screen size).
On a Mac, you must type in kivy instead of python after installing Kivy.app in /
Applications. Lines 2 and 3 verify that we have the appropriate version of Kivy
installed on our computer.
We omit the call to kivy.require in most of the examples in the book, but you will
find it in the code that you download online (https://www.packtpub.com/), and its
use is strongly encouraged in real-life projects. The program uses two classes from
the Kivy library (lines 5 and 6) App and Label. The class App is the starting point of
any Kivy application. Consider App as the empty window where we will add other
Kivy components.
[4]
Chapter 1
We use the App class through inheritance; the App class becomes the base class of the
HelloApp subclass or child class (line 8). In practice, this means that the HelloApp
class has all the variables and methods of App, plus whatever we define in the body
(lines 9 and 10) of the HelloApp class. Most importantly, App is the starting point of
any Kivy application. We can see that line 13 creates an instance of HelloApp and
runs it.
Now the HelloApp class's body just overrides one of the existing App class's methods,
the build(self) method. This method has to return the window content. In our
case, a Label that holds the text Hello World! (line 10). A Label is a widget that
allows you to display some text on the screen.
A widget is a Kivy GUI component. Widgets are the minimal graphical
units that we put together in order to create user interfaces.
The following screenshot shows the resulting screen after executing the
hello.py code:
So, is Kivy just another library for Python? Well, yes. But as part of the library, Kivy
offers its own language in order to separate the logic from the presentation and to
link elements of the interface. Moreover, remember that this library will allow you to
port your applications to many platforms.
Let's start to explore the Kivy language. We will separate the previous Python code
into two files, one for the presentation (interface), and another for the logic. The first
file includes the Python lines:
14.
15.
16.
17.
18.
[5]
The hello2.py code is very similar to hello.py. The difference is that the method
build(self) doesn't have the Hello World! message. Instead, the message has been
moved to the text property in the Kivy language file (hello2.kv).
A property is an attribute that can be used to change the content,
appearance, or behavior of a widget.
The following is the code (rules) of hello2.kv, which shows how we modify the
Label content with the text property (line 27):
24. # File name: hello2.kv
25. #:kivy 1.9.0
26. <Label>:
27.
text: 'Hello World!'
You might wonder how Python or Kivy knows that these two files (hello2.py and
hello2.kv) are related. This tends to be confusing at the beginning. The key is in the
name of the subclass of App, which in this case is HelloApp.
The beginning part of the App class's subclass name must coincide
with the name of the Kivy file. For example, if the definition of the
class is class FooApp(App), then the name of the file has to be
foo.kv and in the same directory of the main file (the one that
executes the run() method of App).
Once that consideration is included, this example can be run in the same way we
ran the previous one. We just need to be sure we are calling the main file python
hello2.py -size=150x100.
This is our first contact with the Kivy language, so we should have an in-depth
look at it. Line 25 (hello2.kv) tells Python the minimal version of Kivy that should
be used. It does the same thing as the previous lines 2 and 3 do in hello.py. The
instructions that start with #: in the header of a Kivy language are called directives.
We will also be omitting the version directive throughout the rest of this book, but
remember to include it in your own projects.
[6]
Chapter 1
The <Label>: rule (line 26) indicates that we are going to modify the Label class.
The Kivy language is expressed as a sequence of rules. A rule is a piece
of code that defines the content, behavior, and appearance of a Kivy
widget class. A rule always starts with a widget class name in angle
brackets followed by a colon, like this, <Widget Class>:
Inside the rule, we set the text property with 'Hello World!' (line 27). The code
in this section will generate the same output screen as before. In general, everything
in Kivy can be done using pure Python and importing the necessary classes from
the Kivy library, as we did in the first example (hello.py). However, there are
many advantages of using the Kivy language and therefore this book explains all
the presentation programming in the Kivy language, unless we need to add
dynamic components, in which case using Kivy as a traditional Python library is
more appropriate.
If you are an experienced programmer, you might have worried that modifying
the Label class affects all the instances we could potentially create from Label,
and therefore they will all contain the same Hello World text. That is true, and
we are going to study a better approach to doing this in the following section.
[7]
In line 32, we inherit from the base class Widget and create the subclass MyWidget.
It is a general practice to create your own Widget for your applications instead of
using the Kivy classes directly, because we want to avoid applying our changes to
all future instances of the widget Kivy class. In the case of our previous example
(hello2.kv), modifying the Label class (line 26) would affect all of its future
instances. In line 37, we instantiated MyWidget instead of Label directly (as we did
in hello2.py), so we can now distinguish between our widget (MyWidget) and the
Kivy widget (Widget). The rest of the code is analogous to what we covered before.
The following is the corresponding Kivy language code (widgets.kv):
41. # File name: widgets.kv
42. <MyWidget>:
43.
Button:
44.
text: 'Hello'
45.
font_size: 32
46.
color: .8,.9,0,1
47.
pos: 0, 100
48.
size: 100, 50
49.
Button:
50.
text: 'World!'
51.
font_size: 32
52.
color: .8,.9,0,1
53.
pos: 100,0
54.
size: 100, 50
Note that now we are using buttons instead of labels. Most of the basic widgets
in Kivy work in similar ways. In fact, Button is just a subclass of Label that
incorporates more properties such as background color.
Compare the notation of line 26 (<Label>:) in hello2.kv with line 43 (Button:) of
the preceding code (widgets.kv). We used the rule class notation (<Class>:) for the
Label (and MyWidget) class, but a different notation (Instance:) for Button. In this
way, we defined that MyWidget has two instances of Button (line 43 and 49).
[8]
Chapter 1
Finally, we set the properties of the Button instances. The font_size property sets
the size of the text. The color property sets the text color and is specified in RGBA
format (red, green, blue, and alpha/transparency). The properties size and pos set
the size and position of the widget and consist of a pair of fixed coordinates (x for
horizontal and y for vertical), the exact pixels on the window.
Note that the coordinate (0, 0) is located at the bottom-left corner,
the Cartesian origin. Many other languages (including CSS) use
the top-left corner as the (0, 0) coordinate, so take note!
The following screenshot shows the output of widgets.py and widgets.kv with
some helpful annotations:
A couple of things can be improved in the previous code (widgets.kv). First, there
are some repeated properties for both buttons: pos, color, and font_size. Instead
of that, let's create our own Button as we did with MyWidget so it will be easy to
keep the buttons' design consistent. Second, the fixed position is quite annoying
because the widgets don't adjust when the screen is resized. Let's make it responsive
to the screen size in the widgets2.kv file:
55. # File name: widgets2.kv
56. <MyButton@Button>:
57.
color: .8,.9,0,1
58.
font_size: 32
59.
size: 100, 50
60.
61. <MyWidget>:
62.
MyButton:
63.
text: 'Hello'
64.
pos: root.x, root.top - self.height
65.
MyButton:
66.
text: 'World!'
67.
pos: root.right - self.width, root.y
[9]
In this example, each Button class's position is responsive in the sense that they are
always in the corners of the screen, no matter what the window size is. In order to
achieve that, we need to use two internal variables self and root. You might be
familiar with the variable self. As you have probably guessed, it is just a reference
to the Widget itself. For example, self.height (line 64) has a value of 50 because
that is the height of that particular MyButton class. The variable root is a reference
to the Widget class at the top of the hierarchy. For example, the root.x (line 64) has
a value of 0 because that is the position in X-axis of the MyWidget instance created on
line 37 of widgets.py.
MyWidget uses all of the window's space by default; therefore, the origin is (0, 0).
The x and y and width and height are also widget properties, which we can
use to disjoint pos and size respectively.
Fixed coordinates are still a laborious way to organize widgets and elements in the
window. Let's move on to something smarter layouts.
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).
[ 10 ]
Chapter 1
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.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
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.
[ 11 ]
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
[ 12 ]
Chapter 1
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
Yes
No
size_
hint_x
A proportion from 0 to 1 or
None, indicating width (size_
hint_x) or height (size_
hint_y).
Yes
No
Yes
No
size
Yes
width
Yes
height
Yes
size_
hint_y
pos_hint
[ 13 ]
Property
Value
For layouts
For
widgets
pos
Yes
x, right or
center_x
Yes
y, top or
center_y
Yes
Details
FloatLayout
RelativeLayout
GridLayout
BoxLayout
StackLayout
[ 14 ]
Chapter 1
Layout
Details
ScatterLayout
PageLayout
will try to take an average of the x hints and y hints on the same row or
column respectively.
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.
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.
[ 15 ]
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:
Embedding layouts
[ 16 ]
Chapter 1
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 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.
[ 17 ]
size_hint_x: None
width: 50
Button:
text: 'G2'
Button:
text: 'G3'
size_hint_x: None
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:
[ 18 ]
Chapter 1
148.
149.
150.
151.
152.
text: 'B2'
size_hint: 2, .3
pos_hint: {'y': .4}
Button:
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.
[ 19 ]
The following example illustrates its use, taking advantage of the example from the
previous section. The Python code (pagelayout.py) is presented here:
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
There is nothing new in this code except the use of the PageLayout class. For the
Kivy language code (pagelayout.kv), we will study the properties of PageLayout.
We have simply modified the layouts.kv studied in the previous section by
changing the header of the file (lines 105 to 107), now called pagelayout.kv:
184. # File name: pagelayout.kv
185. <Layout>:
186.
canvas:
187.
Color:
188.
rgba: 1, 1, 1, 1
189.
Rectangle:
190.
pos: self.pos
191.
size: self.size
192.
193. <MyPageLayout>:
194.
page: 3
195.
border: 120
196.
swipe_threshold: .4
197.
FloatLay...
All the layouts inherit from a base class called Layout. In line 185, we are modifying
this base class in the same way we did earlier with the Button class (line 80).
[ 20 ]
Chapter 1
By default, layouts don't have a background color, which is not convenient when
PageLayout stacks them on top of each other, because we can see the elements of the
layouts on the bottom. Lines 186 to 191 will draw a white (line 187 and 188) rectangle
of the size (line 190) and position (line 191) of the Layout. In order to do this, we
need to use the canvas, which allows us to draw shapes directly on the screen. This
topic will be explained in-depth in the next chapter (Chapter 2, Graphics - The Canvas).
You can see the result in the following screenshot:
If you run the code on your computer, you will notice that it will take you to the
page corresponding to AnchorLayout in the example of the previous section. The
reason is that we set the page property to value 3 (line 194). Counting from 0, this
property tells Kivy which page to display first. The border property tells Kivy
how wide the side borders are (for sliding to the previous or the next screen).
Finally, swipe_threshold tells the percentage of the screen that we have to slide
over, in order to change the page. The next section will use some of the layouts and
properties learned so far to display a more professional screen.
[ 21 ]
We can distinguish several areas in the sketch. First, we need a drawing space
(top-right) for our comics. We need a tool box (top-left) with some drawing tools to
draw our figures and also some general options (second from bottom to top) clear
the screen, remove the last element, group elements, change color, and use the
gestures mode. Finally, it would be useful to have a status bar (center-bottom) to
provide some information to the user number of figures and last action performed.
According to what we have learned in this chapter, there are multiple solutions to
organize this screen. We will use the following:
AnchorLayout for the tool box area in the top-left corner. Inside it will be a
GridLayout of two columns for the drawing tools.
AnchorLayout for the drawing space in the top-right corner. Inside it will be a
RelativeLayout to have a relative space to draw in.
AnchorLayout for the general options and status bar area at the bottom. Inside
it will be a BoxLayout with vertical orientation to organize the general options
on top of the status bar:
general options.
BoxLayout with horizontal orientation for the labels of the status bar.
[ 22 ]
Chapter 1
We are going to use that structure by creating different files for each area
comiccreator.py, comiccreator.kv, toolbox.kv, generaltools.kv,
drawingspace.kv, and statusbar.kv. Let's start with comiccreator.py:
198.
199.
200.
201.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
Note that we are explicitly loading some of the files with the Builder.load_file
instruction (lines 203 to 206). There is no need to explicitly load comiccreator.
kv because Kivy automatically loads it by extracting the first part of the
ComicCreatorApp name. For ComicCreator, we choose AnchorLayout. It is not the
only option, but it gives clarity to the code, because the second level is also composed
of AnchorLayout instances.
Even though using a simple widget would have been clear, it is not possible, because
the Widget class doesn't honor the size_hint and pos_hint properties that are
necessary in the AnchorLayout internals.
Remember that only layouts honor the size_hint and
pos_hint properties.
[ 23 ]
[ 24 ]
Chapter 1
This code follows the previously presented structure for the Comic Creator. There are
basically three AnchorLayout instances in the first level (lines 219, 226, and 233) and
a BoxLayout that organizes the general options and the status bar (line 236).
We set the width of the ToolBox to 100 pixels and the height of the GeneralOptions
and StatusBar to 48 and 24 pixels respectively (lines 241 and 245). This brings with
it an interesting problem the drawing space should use the remaining width and
height of the screen (no matter the screen size). In order to achieve this, we will take
advantage of the Kivy id (lines 223, 239, and 243), which allows us to refer to other
components inside the Kivy language. On lines 231 and 232, we subtract tool_box.
width from root.width (line 231) and general_options.height and status_bar.
height from root.height (line 232).
A Kivy id allows us to create internal variables in order to access
properties of other widgets inside the Kivy language rules.
For now, let's continue exploring the Kivy language in the toolbox.kv:
245. # File name: toolbox.kv
246. <ToolButton@ToggleButton>:
247.
size_hint: None, None
248.
size: 48,48
249.
group: 'tool'
250.
251. <ToolBox@GridLayout>:
252.
cols: 2
253.
padding: 2
254.
ToolButton:
255.
text: 'O'
256.
ToolButton:
257.
text: '/'
258.
ToolButton:
259.
text: '?'
[ 25 ]
We created a ToolButton class that defines the size of the drawing tools and also
introduces a new Kivy widget ToggleButton. The difference with the normal
Button is that it stays pressed until we click on it again. The following is an example
of the tool box with a ToolButton activated:
[ 26 ]
Chapter 1
Here is an example of how inheritance can help us separate our components. We are
using ToggleButton instances (lines 269 and 273), and they are not affected by the
previous ToolButton implementation. Also, we didn't associate them to any group,
so they are independent of each other and will just keep a mode or state. The code
only defines the GeneralOptions class following our initial structure. The following
is the resulting screenshot:
The difference is that it organizes labels and not buttons. The following is
the screenshot:
[ 27 ]
In the following chapters, we are going to add the respective functionality to this
interface that, for now, consists of placeholder widgets. However, it is exciting what
we got with just a few lines of code. Our GUI is ready to go and we will be working
on its logic from now on.
[ 28 ]
Chapter 1
Summary
This chapter covered all the basics and introduced some not-so-basic concepts of
Kivy. We covered how to configure classes, instances, and templates. Here is a list of
Kivy elements we have learned to use in this chapter:
There are many more elements from the Kivy language that we can use, but with this
chapter, we have understood the general idea of how to organize elements. With the
help of the Kivy API, we should be able to display most of the elements available
for GUI design. There is, however, a very important element we need to study
separately the canvas, which allows us to draw vector shapes inside widgets, such
as the white rectangle we draw as background in the PageLayout example. It is a
very important topic to master in Kivy, and the entire next chapter, Graphics - The
Canvas, will be dedicated to it.
[ 29 ]
www.PacktPub.com
Stay Connected: