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

Basic widgets – labels and buttons


In the last section, we used the Label class, which is one of the multiple widgets that Kivy provides. You can think of widgets as interface blocks that we use to set up a GUI. Kivy has a complete set of widgets – buttons, labels, checkboxes, dropdowns, and many more. You can find them all in the API of Kivy under the package kivy.uix (http://kivy.org/docs/api-kivy.html).

We are going to learn the basics of how to create our own personalized widget without affecting the default configuration of Kivy widgets. In order to do that, we will use inheritance to create the MyWidget class in the widgets.py file:

28.# File name: widgets.py
29. from kivy.app import App
30. from kivy.uix.widget import Widget
31. 
32. class MyWidget(Widget):
33.     pass
34. 
35. class WidgetsApp(App):
36.     def build(self):
37.         return MyWidget()
38. 
39. if __name__=="__main__":
40.     WidgetsApp().run()

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).

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.

Tip

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

In this code (widgets2.kv), we create (<MyButton@Button>:) and customize the MyButton class (lines 56 to 59) and instances (line 62 to 67). Note the differences in the manner we defined MyWidget and MyButton.

Note

Because we did not define the MyButton base class in widgets.py as we did with MyWidget (line 32 of widgets.py), we have to specify @Class in the Kivy language rule (line 56). In the MyWidget class case, we also needed to define its class from the Python side because we instantiated it directly (line 37 of widgets.py).

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.