Skip to content

Beginner Challenge 2

Estimated time of completion: 2 to 6 hours (depending on your experience) 🕐

Welcome to your second challenge!

In this challenge you are going to create this screen. Are you ready?

You will learn how to position widgets like Button and Label on the screen and change their size, color, and font and much more.

What do I need before starting?

  • You need to have Kivy installed on your computer. If you don't have it installed, follow the instructions on the installation page.
  • We also recommend you to read the first challenge, Beginner Challenge 1.

Tip

Do not forget making yourself questions and trying things out! "What will happen if I change this?", "What will happen if I change that?". Not only will you learn more, but you will also have fun! Experiment and discover!

You don't need to know everything to start. You will learn as you go.

You don't need to memorize everything. You can always look up the documentation. You will naturally remember things as you use them.

Creating a layout - BoxLayout

Create it

  • Create a new file called main.py or whatever_you_want.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
    Button:
        text: "Button 2"
    Button:
        text: "Button 3"
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()
Tip

You can always copy the code by clicking on the copy button on the top right corner of the code block. Copy to Clipboard

Check it out

  • Run the app by typing python main.py in your terminal. You should see a window with three buttons.
$ python main.py

What did we do?

We created a Kivy app that displays three buttons. But how does it work? Let's break it down.

Recap, step by step

Step 1: import Kivy classes and load the Kivy language code

Note

What these classes (App, Builder) do was explained in the first challenge, Beginner Challenge 1.

main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
    Button:
        text: "Button 2"
    Button:
        text: "Button 3"
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Step 2: create a BoxLayout

A BoxLayout is a layout widget that arranges its children in a horizontal or vertical row. We set its orientation property to "vertical". This means that the buttons will be arranged vertically. The height of each button inside the vertical BoxLayout will be the same, because the BoxLayout takes the entire available space and divides it equally among its children.

main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
    Button:
        text: "Button 2"
    Button:
        text: "Button 3"
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()
Question

What happens if you change the orientation property to "horizontal"? Try it out!

Note

If you do not specify the orientation property, the default value is "horizontal". We encourage you to remove the orientation property (remove the line) and see what happens.

Step 3: create three buttons

We created three buttons inside the BoxLayout. Each button has a different text.

main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
    Button:
        text: "Button 2"
    Button:
        text: "Button 3"
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()
Experimentation
  • Why don't you try 5 buttons instead of 3?
  • Change their text to something else.
  • Change the orientation property to "horizontal" or "vertical". Draw your conclusions.

Step 4: run the app

Note

In the future, we'll modify the build method from MainApp class to return a ScreenManager instead of kv. This will allow us to have multiple screens in our app.

main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
    Button:
        text: "Button 2"
    Button:
        text: "Button 3"
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Changing the relative size of widgets

Continue it

  • Modify main.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
        size_hint: 0.25, 1
    Button:
        text: "Button 2"
        size_hint: 0.5, 1
    Button:
        text: "Button 3"
        size_hint: 0.75, 1
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Check it out

  • Run the app by typing python main.py in your terminal. You should see a window with three buttons.
$ python main.py

What did we do?

We changed the relative size of the buttons. The size_hint property is a tuple that contains two values: the size_hint_x, which is "how much % of the parent width I should have" and the size_hint_y, which is "how much % of the parent height I should have".

The values are between 0 and 1 (0 and 100% of the available space). The first button has a width of 25%, the second button has a width of 50%, and the third button has a width of 75%. The height of each button is 100% of the available height.

Note

BoxLayout is the parent widget of the buttons. The BoxLayout takes the entire available space. The buttons are children of the BoxLayout.

Three vertically stacked buttons: 25%, 50%, and 75% width

Because this is a vertical BoxLayout, the height of each button is the same. We have three buttons, so the height of each button is 1/3 of the available space. If you make the window smaller, the buttons will shrink. If you make the window bigger, the buttons will grow.

Question

What happens if you change the size_hint property of a Button to (0.25, 0.25)?

Question

What happens if you change the size_hint property of the BoxLayout to (1, 0.5)?

Question

What happens if you change the size_hint property of the BoxLayout to (0.5, 1)?

You should try to answer these questions before reading the next section. Change the code and run the app to see the results and explain them.

Note

The size_hint property is very useful when you want to create a responsive app. It allows you to create an app that looks good on different screen sizes. Also, remember that the size_hint property is relative to the parent widget. If the parent widget has 100 pixels of width and 80 pixels of height, and the child widget has a size_hint of (0.5, 0.5), the child widget will have 50 pixels of width and 40 pixels of height.

How can I create a button with the same appearance as the buttons in Android and iOS?

You'll learn how to create a custom style in this challenge, and you will even create a button with the same appearance as the buttons in Android and iOS.

Kivy default style is not the same as Google Material, but we have a complete extension library called KivyMD that already has implemented Google Material style. But we'll learn how to create a custom style manually, and you can decide to use KivyMD library or not.

Remember that any app you can imagine, you can create with Kivy.

Creating a button function

Continue it

  • Modify main.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
        size_hint: 0.25, 1
        on_press: print("Button 1 pressed")
    Button:
        text: "Button 2"
        size_hint: 0.5, 1
        on_release: print("Button 2 released")
    Button:
        text: "Button 3"
        size_hint: 0.75, 1
        on_press: print("Button 3 pressed")
        on_release: print("Button 3 released")
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Check it out

  • Run the app by typing python main.py in your terminal. You should see a window with three buttons. Click on the three buttons and you should see the text Button 1 pressed, Button 2 released, and Button 3 pressed and Button 3 released in the terminal.
$ python main.py

Button 1 pressed
Button 2 released
Button 3 pressed
Button 3 released

What did we do?

We created a function for each button. The on_press event is fired when the button is pressed, and the on_release event is fired when the button is released. You can create a function for each event, i.e., you can run any kind of code when the button is pressed. We simply printed a specific message to terminal when the button is pressed or released.

Note

The on_press and on_release are called events. When these events are fired, the function is executed (if you put any). You can create your own events and functions, we'll see in next section.

You can also use the on_press and on_release events to change the appearance of a button (or other widget). For example, you can change the color of a button when it is pressed, show a popup, or navigate to another screen. Actually you can do anything you want.

Question

What is the difference between on_press and on_release?

Question

Can you execute multiple functions when the button is pressed?

Creating a custom button style

Continue it

  • Modify main.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: ''
        size_hint: 0.25, 1
    Button:
        text: "Button 2"
        color: 0, 0, 0, 1
        background_color: .5, 1, 1, 1
        background_normal: ''
        size_hint: 0.5, 1
    Button:
        text: "Button 3"
        color: 0, 0, 0, 1
        background_color: 1, 1, .5, 1
        background_normal: ''
        size_hint: 0.75, 1
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Check it out

  • Run the app by typing python main.py in your terminal. You should see a window with three buttons.
$ python main.py

Three vertically stacked buttons of varying widths: pink, cyan, and yellow.

What did we do?

We created a custom style for the buttons. We changed the color of the text and the background color of the buttons. We also removed the default background image of the buttons.

color

  • The color property is used to change the color of the text. The color is a tuple of four values: red, green, blue, and alpha, also known as RGBA. Each value can be between 0 and 1. Let's see how it works.
main.py
 9
10
11
12
13
14
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: ''
        size_hint: 0.25, 1
  • This button has a black text color because the color property is (0, 0, 0, 1), i.e., it has no red, green, or blue, and it is fully opaque. If you are used to work with values between 0 and 255, you can divide each value by 255. For example, (51/255, 0, 0, 1) is the same as (0.2, 0, 0, 1).
main.py
 9
10
11
12
13
14
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: ''
        size_hint: 0.25, 1

background_color

  • The background_color property is used to change the background color of the button, also in RGBA format. This button has a pink background color because the background_color property is (1, 0.5, 1, 1).

Difference between color and background_color on a Button

background_normal

  • The background_normal property is used to remove the default background image of the button. The default background image is a gray image. If you want to use an image as the background of the button, you can use the background_normal property to set the image path. For example, background_normal: 'path_to_image.png'.
main.py
 9
10
11
12
13
14
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: ''
        size_hint: 0.25, 1

Let's better understand the background_normal property. The background_normal property is used to set the background image of the button when the button is not pressed, i.e., the normal state of the button. Yes, it means instead of a color, you can use an image as the background of the button. For example, let's put this image.png in our button:

Image example to be used on a Kivy Button

main.py
 9
10
11
12
13
14
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: 'image.png'
        size_hint: 0.25, 1

Tinting an image in a Button with pink

What? Why the image is pink? The image is pink because the background_color acts as a multiplier of the image. Each pixel of the image is multiplied by the background_color. Every white pixel of the image, (1,1,1,1), multiplied by the background_color, (1, 0.5, 1, 1), will be (1, 0.5, 1, 1).

If you just want to use the image as the background of the button, you can set the background_color to (1, 1, 1, 1), then every pixel of the image will be the same as the image.

main.py
 9
10
11
12
13
14
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 1, 1, 1
        background_normal: 'image.png'
        size_hint: 0.25, 1

Using an image on a Kivy Button, normal state

Question

What happens if you change the background_color property to (0, 0, 0, 1)?

background_down

What if you want to have a different image when the button is pressed? You can use the background_down property. The background_down property is used to set the background image of the button when the button is pressed. For this example, I'm going to remove the "Button 1" text, it's not needed. Let's use this dog image as the background of the button when it is pressed:

Dog example to be used on a Kivy Button

main.py
 9
10
11
12
13
14
15
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 1, 1, 1
        background_normal: 'image.png'
        background_down: 'image_down.png'
        size_hint: 0.25, 1

How to color the BoxLayout

Continue it

  • Modify main.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    canvas.before:
        Color:
            rgba: .25, 0, 0, 1
        Rectangle:
            size: self.size
            pos: self.pos
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: ''
        size_hint: 0.25, 1
    Button:
        text: "Button 2"
        color: 0, 0, 0, 1
        background_color: .5, 1, 1, 1
        background_normal: ''
        size_hint: 0.5, 1
    Button:
        text: "Button 3"
        color: 0, 0, 0, 1
        background_color: 1, 1, .5, 1
        background_normal: ''
        size_hint: 0.75, 1
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Check it out

  • Run the app by typing python main.py in your terminal. You should see a window with three buttons.
$ python main.py

Colored Box Layout

What did we do?

We colored the BoxLayout widget. The canvas.before property is used to draw graphics before the widget's content. We used the Color and Rectangle canvas instructions to draw a red rectangle behind the BoxLayout widget.

The Color instruction sets the color of drawing, and the Rectangle instruction tells the shape. The size property of the Rectangle instruction is set to self.size (self in this case is the BoxLayout itself), and the pos property is set to self.pos. This means that the rectangle will have the same size and position as the BoxLayout widget.

Right now we are not going to explain the canvas.before property in detail. We are going to explain it better in the next lessons. In the future you learn how to use it to draw rectangles, circles, lines, images and complex shapes.

Note

Remember you don't have to understand everything at once. When you start learning how to drive a car, you don't need to know how the engine works. You just need to know how to drive it. The same is true for Kivy. You don't need to know everything to start. You will learn as you go.

When you want to paint a BoxLayout with a specific color, just type this:

canvas.before:
    Color:
        rgba: YOUR_COLOR
    Rectangle:
        size: self.size
        pos: self.pos

That's it for now.

Padding and spacing

Continue it

  • Modify main.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from kivy.app import App
from kivy.lang import Builder


kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    padding: dp(50)
    spacing: dp(20)
    canvas.before:
        Color:
            rgba: .25, 0, 0, 1
        Rectangle:
            size: self.size
            pos: self.pos
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: ''
        size_hint: 0.25, 1
    Button:
        text: "Button 2"
        color: 0, 0, 0, 1
        background_color: .5, 1, 1, 1
        background_normal: ''
        size_hint: 0.5, 1
    Button:
        text: "Button 3"
        color: 0, 0, 0, 1
        background_color: 1, 1, .5, 1
        background_normal: ''
        size_hint: 0.75, 1
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Check it out

  • Run the app by typing python main.py in your terminal. You should see this:

BoxLayout with padding and spacing

What is padding?

Padding is the space between the border of the widget, in this case the BoxLayout and its content. The padding is a tuple of four values: left, top, right, and bottom.

But in this case, we used the padding property to set the same padding for all sides. The padding is set to dp(50), which means 50 density-independent pixels. Here in this image, we painted the padding of the BoxLayout widget in gray:

BoxLayout padding in gray

The values are in pixels, but we recommend always using the dp function to convert the size from pixels to density-independent pixels. You can use any unit you want, but we recommend using dp for the best results. It provides consistency for the real-world size of your UI across different devices. You can read more here.

Note

There are three ways of declaring the padding. A tuple of four values, a tuple of two values, or a single value.

Single value padding:

  • padding: dp(50) - sets the same padding for all sides.

Two values padding:

  • padding: (dp(50), dp(20)) - sets the padding for left/right and top/bottom sides, in this order.

Four values padding:

  • padding: (dp(20), dp(30), dp(40), dp(50)) - sets the padding for left, top, right, and bottom sides, in this order.

What is spacing?

Spacing is the space between the widgets inside the BoxLayout. The spacing is set to dp(20), which means 20 density-independent pixels. Here in this image, we painted the spacing of the BoxLayout for you to see it better:

BoxLayout spacing in gray

How to set the absolute size of any widget

Continue it

  • Modify main.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from kivy.app import App
from kivy.lang import Builder


kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    padding: dp(50)
    spacing: dp(20)
    canvas.before:
        Color:
            rgba: .25, 0, 0, 1
        Rectangle:
            size: self.size
            pos: self.pos
    Button:
        text: "Button 1"
        color: 0, 0, 0, 1
        background_color: 1, 0.5, 1, 1
        background_normal: ''
        size_hint: None, None
        size: dp(100), dp(50)
    Button:
        text: "Button 2"
        color: 0, 0, 0, 1
        background_color: .5, 1, 1, 1
        background_normal: ''
        size_hint: None, None
        size: dp(200), dp(100)
    Button:
        text: "Button 3"
        color: 0, 0, 0, 1
        background_color: 1, 1, .5, 1
        background_normal: ''
        size_hint: None, None
        size: dp(300), dp(150)
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Check it out

  • Run the app by typing python main.py in your terminal. You should see a window with three buttons.
$ python main.py

BoxLayout with absolute size buttons

What did we do?

We set the absolute size of the buttons. The size_hint property is set to None, None, which means that the size of the button is not relative to the parent widget. The size property is set to dp(100), dp(50), dp(200), dp(100), and dp(300), dp(150). This means that the first button has a width of 100 pixels and a height of 50 pixels, the second button has a width of 200 pixels and a height of 100 pixels, and the third button has a width of 300 pixels and a height of 150 pixels.

Labels

Labels are widgets that display text. But the text is not the Label itself. The Label is a widget that contains the text. The easy way to understand this is to think of a piece of paper with text written on it. The piece of paper is the Label, and the text is the text of the Label.

You must make sure you understand this concept. A page of a book is not its text. The page can be yellow, the text can be green. The page can be small, the text can be big. The page may have pictures or lines drawn to it.

You can show a text using any type of font and it can be aligned to left/right, it can be bold, italic, underlined, etc. You can even display animations in the label. Let's see how it works.

Continue it

  • Create a tutorial_labels.py file and paste the following code:
tutorial_labels.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    orientation: "vertical"
    Label:
        text: "Normal Text"
    Label:
        text: "Green Text"
        color: 0,1,0,1
    Label:
        text: "Big Green Text"
        color: 0,1,0,1
        font_size: dp(42)
    Label:
        text: "A very long text that does not fit in the screen"
        font_size: dp(42)
    Label:
        text: "Text with [b]bold[/b], [i]italic[/i], [u]underline[/u], [s]strikethrough[/s] and [color=ff0000]red[/color] text that fit on the screen"
        font_size: dp(35)
        markup: True
        text_size: root.width, None
"""
)


class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Check it out

  • Run the app by typing tutorial_labels.py in your terminal (or pressing F5 on VS Code). You should see a window with five labels.
$ python tutorial_labels.py

BoxLayout with 5 labels, different sizes and styles

What did we do?

  • We created five labels. The first label is a normal label, and the second label has a green color.
main.py
1
2
3
4
5
    Label:
        text: "Normal Text"
    Label:
        text: "Green Text"
        color: 0,1,0,1

Comparing a Label with black and gray background

Note

On the image above we changed the background color of the label, just to make it clear that the label is a widget. The label is not the letters of Normal Text. The label is a widget that contains the text Normal Text.

Question

If you changed the size_hint_x of the label, what would happen? Would the text Normal Text become smaller, bigger, or would it be the same size?

Question

Is it possible make the text Normal Text bigger than the label?

Note

The color property is a tuple of four values: red, green, blue, and alpha. Each value can be between 0 and 1. The alpha value is the transparency of the color. If the alpha value is 1, the color is fully opaque, and if the alpha value is 0, the color is fully transparent.

For example, (0, 1, 0, 1) is a green color, and (0, 1, 0, 0.5) is a green color with 50% transparency.

Question

What happens if you change color to (0, 1, 0, 0)?

What happens if you change color to (1, 1, 1, 1)?

  • The third label has a big green font. The font_size property is used to change the size of the font. The dp function is used to convert the size from pixels to density-independent pixels. You can use any unit you want, but we recommend using dp for the best results. It provides consistency for the real-world size of your UI across different devices. You can read more here.
main.py
1
2
3
4
    Label:
        text: "Big Green Text"
        color: 0,1,0,1
        font_size: dp(42)
Question

What happens if you change the font size to dp(100)? And dp(10)?

  • The fourth label has a bigger font size, but the text is too long to fit in the screen. Let's see how we can fix this on the fifth label.
main.py
1
2
3
    Label:
        text: "A very long text that does not fit in the screen"
        font_size: dp(42)
  • The fifth label has a bigger font size, and the text would be too long to fit in the screen, but we used the text_size property to tell Kivy that the text can have a maximum width of the root widget.
main.py
1
2
3
4
5
    Label:
        text: "Text with [b]bold[/b], [i]italic[/i], [u]underline[/u], [s]strikethrough[/s] and [color=ff0000]red[/color] text that fit on the screen"
        font_size: dp(35)
        markup: True
        text_size: root.width, None

We also used the markup property to tell Kivy that we want to use the Text Markup to format the text. The Text Markup Language allows you to change the font size, color, and style of the text.

main.py
1
2
3
4
5
    Label:
        text: "Text with [b]bold[/b], [i]italic[/i], [u]underline[/u], [s]strikethrough[/s] and [color=ff0000]red[/color] text that fit on the screen"
        font_size: dp(35)
        markup: True
        text_size: root.width, None

We limited the text_size to the width of the root widget, and we set the height to None. This means that the height of the text will be as big as it needs to be.

If you do not know who is the root widget, think on a tree. The root is where the tree starts. In this case, the root is the BoxLayout widget. The BoxLayout widget is the parent of the Label widget and the root widget of the Label widget.

For example:

main.py
1
2
3
4
5
6
7
|---BoxLayout
|   |---Label
|   |---Label
|   |---GridLayout
|       |---Button
|       |---Button
|       |---Button

In a structure like this, the BoxLayout widget is the root widget of the Label, GridLayout and the Button. Yes! The BoxLayout widget is the root widget of every widget in the tree. Because everything started from the BoxLayout widget.

  • But the GridLayout widget is the parent of the Button widget
  • And the BoxLayout widget is the parent of the GridLayout widget and the Label widgets.
Question

What is the difference between the root widget and the parent widget?

Note

There is a label property called halign that allows you to align the text to the left, right, or center. The default value is left. But, suppose we want to align the text to the center, it would be like this:

main.py
1
2
3
4
5
6
Label:
    text: "Text with [b]bold[/b], [i]italic[/i], [u]underline[/u], [s]strikethrough[/s] and [color=ff0000]red[/color] text that fit on the screen"
    font_size: dp(35)
    markup: True
    text_size: root.width, None
    halign: "center"

Example of Label using different markup tags

Getting ready for the challenge

Now that you have learned how to position widgets like Button and Label on the screen and change their size, color, and font, you are ready for the challenge. We are going to give you the last piece of information you need to complete the challenge: the canvas.before property.

canvas.before

The canvas.before property is used to draw graphics before the widget's content. You can use it to draw rectangles, circles, lines, etc. You can also use it to draw images, but we are going to teach more this in the next challenges. Right now, we are going to use it to draw a rectangle behind widgets like BoxLayout and Label, so you can change the background color of these widgets to see them better.

Let's see how it works.

Continue it

  • Modify main.py and paste the following code:
main.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from kivy.app import App
from kivy.lang import Builder

kv = Builder.load_string(
"""
BoxLayout:
    canvas.before:
        Color:
            rgba: .5, 0, 0, 1
        Rectangle:
            size: self.size
            pos: self.pos
"""
)

a: list(int) = 5
class MainApp(App):
    def build(self):
        return kv


MainApp().run()

Conclusion

Congratulations for reaching this point of the challenge, but you have not completed your second challenge yet!

You have learned how to position widgets like Button and Label on the screen and change their size, color, and font. But you must create the screen that we showed at the beginning of this challenge using only what you have learned so far. Yes, there are multiple ways to create the screen, but in this challenge, you must use only what you have learned so far.

We encourage you to experiment with the code and try to create the screen by yourself. Don't simply copy and paste the code. Copy, paste, and change the code. Make yourself questions and try to answer them. Then run the app and see the results. Compare the results with your expectations.

If you do not do this, you will not learn as much as you could and you won't have as much fun as you should.

This is how actual learning works.