-
Book Overview & Buying
-
Table Of Contents
Kivy: Interactive Applications in Python
By :
In the previous section, we were already using the Label class, which is one of the widgets that Kivy provides. Widgets are the little interface blocks that we use to set up the GUI. Kivy has a complete set of widgets including buttons, labels, checkboxes, dropdowns, and so on. You can find them all in the Kivy API
kivy.uix (http://kivy.org/docs/api-kivy.html) under the package kivy.uix.
It's a good practice to create your own Widget for your applications instead of using the Kivy classes directly as we did in hello2.kv (line 26). The following code shows how to do that through inheritance:
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 of the preceding code (widgets.py), we inherit from the base class Widget and create the subclass MyWidget, and, in line 37, we instantiated MyWidget instead of modifying the Kivy Label class directly as we did in hello2.py. 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. pos: 0, 100 46. size: 100, 50 47. color: .8,.9,0,1 48. font_size: 32 49. Button: 50. text: 'World!' 51. pos: 100,0 52. size: 100, 50 53. color: .8,.9,0,1 54. font_size: 32
Notice that now we are using buttons instead of labels. Most of the basic widgets in Kivy work in a very similar manner. In fact, Button is just a subclass of Label that includes more properties such as background color.
Compare the notation of line 26 (<Label>:) of hello2.kv with the line 43 (Button:) of the preceding code (widgets.kv). We used the class notation (<Class>:) for the Label (and for MyWidget) but another notation (Instance:) for Button. We just defined that MyWidget has two instances of Button (on line 43 and 49), and then we set the properties of those instances (the color is in RGBA format that stands for red, green, blue, and alpha/transparency).
The size and pos properties consist of fixed values, that is, the exact pixels on the window.
Notice that the coordinate (0, 0) is at the bottom-left corner, that is, the Cartesian origin. Many other languages (including CSS) use the top-left corner as the (0, 0) coordinate, so be careful with this.
The following screenshot shows the output of the widgets.py and widgets.kv code files with some helpful annotations (on white color):

Creating our own widget
A couple of things could be improved in the previous code (widgets.kv). The first thing is that there are many repeated properties for the buttons such as pos, color and font_size. Instead of that, let's create our own Button as we did with MyWidget. The second is that the fixed position is quite annoying because the widgets don't adjust when the screen is resized because the position is fixed. Let's make the widgets more responsive:
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 widgets2.kv we created (<MyButton@Button>:) and customized the MyButton class (as shown in lines 56 to 59) and instances (as shown in the lines 62 to 67).
Please note the difference between the way we defined MyWidget and MyButton. We need to specify @Class only if we didn't define the base class in the Python side as we did with MyWidget (line 32 of widgets.py). On the other hand, we had to define MyWidget in the Python side because we instantiated it directly (line 37 of widgets.py).
In this example, each Button's position is responsive in the sense that they will always be displayed in the corners of the screen, no matter what the window size is. In order to achieve that, we need to use the self and root variables. 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. The root variable 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 the X-axis of the MyWidget instance created on in line 37 of widgets.py. Since, the
MyWidget instance is the only one in the WidgetsApp, it uses all the space by default; therefore, the origin is (0, 0). The x, y, width, and height are also the widgets properties.
Still, fixed coordinates are an inefficient way of organizing widgets and elements in the window. Let's move on to something smarter: layouts.
Change the font size
Change margin width
Change background colour