Skip to content
Home » Kivy Part 29 – Styling the Widgets in the Slugrace Project

Kivy Part 29 – Styling the Widgets in the Slugrace Project

Spread the love

In the previous part we added some colors to our screens. However, except for the text color on the labels, we didn’t touch the widgets. Let’s add some styling to them too. By styles I mean colors and other properties that have a visual effect.

But before we delve into the topic, here’s some info for you.

*****

Book Info

I just published my Kivy book, GUI Programming with Python and Kivy. It’s pretty long (over 800 pages) and comprehensive. And, which also counts, easy to read. The book contains lots of illustrations.

This book covers all the basics that you need to know to start programming GUI applications with Python and Kivy. Throughout the book we are building a GUI application from scratch, a fully functional game using all kinds of tools that Kivy has to offer. It’s our Slugrace project, but covered in a much more in-depth manner.

Each part of the book starts with a theoretical introduction of a topic or idea that we then implement in the project. I assume you have no prior knowledge of the Kivy library, but you should have at least some basic knowledge of the Python programming language, including the object-oriented programming paradigm as this is what we will be using a lot in this book.

Kivy book

The book covers all the basic elements of Kivy that you have to know, like widgets, layouts, Kivy ids and properties, graphics, screens, animation, sound. Finally we’ll deploy the app to Windows. It is pretty comprehensive and after you finish it, I’m sure you’ll be able to create your own awesome GUI apps of any kind, not just games.

I hope you will have at least as much fun reading the book as I had writing it.

As far as this Kivy series is concerned, the following parts will contain the most important elements covered in the book. However, some elements will be presented in a simplified way here on my blog or omitted completely.

____________

If you are interested, you can purchase the book in four versions. Here are the links:

1) ebook – pdf version on my website – in full color

Here you can see the description of the book, sample graphics from the book and the full table of contents.

2) ebook – Kindle version on Amazon – in full color

3) paperback version on Amazon – in black and white

4) paperback version on Amazon – in full color

*****

And Now Let’s Move On…

As I have already mentioned multiple times, in the final version of the app all class rules that are shared by more than one screen will be moved to one file and referenced from there. This way we will be able to define their styles only in one place. For the time being, though, we’ll have to repeat the same code for each screen if we want the same styles.

The Buttons

Let’s start with the buttons. Generally, we want all buttons to look similar, for the sake of consistency.

Settings Screen

Have a look at the Ready Button in the Settings screen. Here is the final version of the screen:

button in final version

and here is our current version:

button now

As you can see, the colors of both the text and the background are different. Let’s make the button look like in the final version then. In the class rules, above the root widget, we’ll add a custom button class. The background color of the button is going to be a shade of red, so let’s name the class RedButton. Then let’s use an instance of this new button instead of the regular button that we now have. Here’s the code:

# File name: settings.kv

### LABELS ###
...

### BUTTONS ###
<RedButton@Button>:
    # The background color should be a shade of red.
    background_color: .8, 0, 0, 1

    # The text color should be a shade of yellow.
    color: 1, .8, .1, 1

    # The text should be in bold type, with font size 18.
    bold: True
    font_size: 18

    # The button should have a fixed size and be horizontally centered.
    size_hint: (None, None)    
    size: 200, 40
    pos_hint: {'center_x': 0.5}

### TEXT INPUTS ###
...

### CHECK BOXES ###
...

<SettingsScreen>:
    ...
       
    ### READY BUTTON ###
    
    # Let's use our custom button.
    RedButton:
        text: 'Ready'

Your Panda3D Magazine

Make Awesome Games and Other 3D Apps

with Panda3D and Blender using Python.

Cool stuff, easy to follow articles.

Get the magazine here (PDF).

Now the button should look like in the final version:

button styled

Styling the other buttons is easy. All you have to do is to copy the RedButton class rule with all the canvas instructions in it and add it to the other screens with buttons, so all the other screens to be precise. After that you have to replace all the instances of Button with RedButton. If any properties should differ from the ones set in the class rule, remember that you can overwrite them on the instance.

Race Screen

There’s one thing about the buttons in the Race screen, and in particular about the third one. If you look at the final version of the screen, you can see that it’s much shorter:

race screen buttons
race

This means that we have to overwrite not only the pos_hint property on that button, but also the size property. The size of the button should be 70 x 40 px.

Here’s the kv code of the Race screen:

# File name: race.kv

### CLASS RULES ###

<RegularLabel@Label>:
    ...

<BoldLabel@RegularLabel>:    
    ...

# the RedButton class rule
<RedButton@Button>:
    background_color: .8, 0, 0, 1
    color: 1, .8, .1, 1
    bold: True
    font_size: 18
    size_hint: (None, None)    
    size: 200, 40
    pos_hint: {'center_x': 0.5}

<RaceScreen>:
    ...

        # Buttons
        BoxLayout:
            orientation: 'vertical'   
            spacing: 3 
            size_hint: .7, 1               
            
            # We're replacing the three Buttons with RedButtons.
            # We have to overwrite the pos_hint property.
            RedButton:
                text: 'End Game'  
                pos_hint: {'right': 1}

            RedButton:
                text: 'Instructions'   
                pos_hint: {'right': 1}
            
            # Here we have to overwrite the size property too.
            RedButton: 
                text: 'Sound'
                pos_hint: {'right': 1}
                size: 70, 40
                                  
    ### THE TRACK ###
    ...

Now the Race screen should look like this:

race screen

Bets Screen

Next, let’s have a look at the Bets screen. Here’s the code:

# File name: bets.kv

### CLASS RULES ###

<RegularLabel@Label>:
    ...

<BoldLabel@RegularLabel>:    
    ...

# The RedButton class rule.
<RedButton@Button>:
    background_color: .8, 0, 0, 1
    color: 1, .8, .1, 1
    bold: True
    font_size: 18
    size_hint: (None, None)    
    size: 200, 40
    pos_hint: {'center_x': 0.5}

...

<BetsScreen>:
    ...

    ### GO BUTTON ###    

    # We're replacing Button with RedButton.
    RedButton:
        text: 'Go'

And here’s the screen:

bets screen

Python Jumpstart Course

Learn the basics of Python, including OOP.

with lots of exercises, easy to follow

The course is available on Udemy.

Results Screen

And here’s the code of the Results screen:

# File name: results.kv

### CLASS RULES ###

<RegularLabel@Label>:
    ...

<BoldLabel@RegularLabel>:    
    ...

# The RedButton class rule.
<RedButton@Button>:
    background_color: .8, 0, 0, 1
    color: 1, .8, .1, 1
    bold: True
    font_size: 18
    size_hint: (None, None)    
    size: 200, 40
    pos_hint: {'center_x': 0.5}

<ResultsScreen>: 
    ...
                
    ### NEXT RACE BUTTON ###    
    # We're replacing Button with RedButton.
    RedButton:
        text: 'Next Race'

If you run the code, you will see the following:

results screen

Game Over Screen

And finally the Game Over screen. Here’s the kv code:

# File name: gameover.kv

### CLASS RULES ###

<RegularLabel@Label>:
    ...

<BoldLabel@RegularLabel>:    
    ...

# The RedButton class rule.
<RedButton@Button>:
    background_color: .8, 0, 0, 1
    color: 1, .8, .1, 1
    bold: True
    font_size: 18
    size_hint: (None, None)    
    size: 200, 40
    pos_hint: {'center_x': 0.5}

<GameoverScreen>: 
    ...
    
    # The buttons
    BoxLayout: 
        spacing: 50            
        pos_hint: {'center_x': .5, 'center_y': .5} 
        size_hint: None, None
        size: 450, 200    

        # We're replacing Button with RedButton, but 
        # we have to overwrite the pos_hint property.      
        RedButton:
            text: 'Play Again'
            pos_hint: {'x': 0, 'center_y': .5}
        RedButton:
            text: 'Quit'
            pos_hint: {'right': 1, 'center_y': .5} 

This screen now looks like so:

game over screen

The Check Boxes

And now let’s have a look at the other widgets that we definitely have to handle, the check boxes, or rather the radio buttons, because it’s how the check boxes are used in our project. Now the radio buttons are hardly visible. In the final version the circles that you can check are filled, so let’s do it now.

Blender Jumpstart Course

Learn the basics of 3D modeling in Blender.

step-by-step, easy to follow, visually rich

The course is available on Udemy and on Skillshare.

Settings Screen

There are radio buttons in two screens, the Settings screen and the Bets screen. Let’s start with the former. You will find two classes defined in the class rules section in the settings.kv file, PlayerRadioButton and ConditionRadioButton. If you run the app and resize the window slightly, you will see that there’s a little circle in the middle where you can click to check the radio button:

settings screen

When unchecked, the circle is hardly visible. Let’s replace it with a filled circle that you can see without difficulty.

Let’s start with the PlayerRadioButton class. To draw a filled circle we have to use the Color instruction and the Ellipse class. So, we need to add some canvas instructions. First let’s set the color to black (0, 0, 0, 1). The ellipse should be a circle. It should sit in the very center of the widget, but when you specify the position of an ellipse, you actually specify the position of its bottom-left corner, not the center. But knowing that the radius of the circle is 20, it’s easy to calculate the coordinates of its center. We must remember to set the size property as well. It’s also easy to calculate.

If we have done everything correctly so far, we should now see filled circles, which we can’t check, though. Actually, we can check them, but we won’t see the blue dot that appears when a radio button is checked. This is because the blue dot is drawn before the circle. But this can be easily fixed. We can change the order in which things are drawn. Assuming we used the canvas instruction, we just have to use one of the other canvas instructions instead. Apart from canvas there are the canvas.before and canvas.after instructions.

Now it should work as expected. Here’s the settings.kv file:

# File name: settings.kv

### LABELS ###
...

### BUTTONS ###
...

### TEXT INPUTS ###
...

### CHECK BOXES ###
<PlayerRadioButton@CheckBox>:
    # We want to draw something, so we need canvas instructions.
    # The black circle should be drawn first, so we should
    # use the canvas.before set of instructions.
    canvas.before:
        # At first let's set the color for the context.
        Color:
            rgba: 0,0,0,1
        
        # Then let's draw the ellipse. If the radius is 10, the bottom-left 
        # corner of the ellipse is 10 px to the left and 10 px in the
        # downward direction from the center of the radio button. The size
        # is twice the radius in both directions.
        Ellipse:
            pos:self.center_x - 10, self.center_y - 10
            size:[20,20]

    group: 'players'  
    size_hint: (.5, 1)

<ConditionRadioButton@CheckBox>:
    # the same canvas instructions as with the PlayerRadioButton
    canvas.before:
        Color:
            rgba: 0,0,0,1
        Ellipse:
            pos:self.center_x - 10, self.center_y - 10
            size:[20,20]

    group: 'conditions'
    size_hint_x: .05

<SettingsScreen>:
    ...

If you now run the app, the radio buttons will be filled and you will see the blue dot when you check one of them:

styled check boxes

Bets Screen

And here’s the bets.kv file:

# File name: bets.kv

### CLASS RULES ###

...

<PlayerSlugButton@CheckBox>:
    # the same canvas instructions as with the PlayerRadioButton
    # in the Settings screen
    canvas.before:
        Color:
            rgba: 0,0,0,1
        Ellipse:
            pos:self.center_x - 10, self.center_y - 10
            size:[20,20]

    size_hint: (.5, 1)

...

<BetsScreen>:
    ...

And this is what it looks like if you run the app now:

bets screen

Spread the love

Leave a Reply