Skip to content
Home » Kivy Part 21 – Slugrace – Bets Screen GUI

Kivy Part 21 – Slugrace – Bets Screen GUI

Spread the love

In the previous part of the series we created the Race screen. I also mentioned that the Bets and Results screens will be injected into the Race screen in the final version of the program, but for now let’s create them as independent apps so that we can easily test them. So, in this part let’s focus on the Bets screen and in the next part we’ll create the Results screen.

When we were starting with some initial code in part 17, we left the bets.py and bets.kv files empty. So now we have to start from scratch.

First let’s have a look at the final version of the Bets screen:

Bets screen

So, what do we have here:

1) The Title Label – it reads Bets

2) The Player Bets – they are pretty complex

3) The Go Button – this is just a simple widget

So, the layout I think would take care of such a hierarchy well is a vertical BoxLayout.

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…

The root Widget of the Bets Screen

Let’s define the BetsScreen class in the Python file then. It should inherit from BoxLayout. Here’s the Python file:

# File name: bets.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class BetsScreen(BoxLayout):
    pass

class BetsApp(App):
    def build(self):
        return BetsScreen()

if __name__ == '__main__':
    BetsApp().run()

As you can see, the code is pretty much the same as in the previous Python files, for example when we were creating the Race screen. Naturally, the names of the root widget class and the name of the app are different.

Now that we have the BetsScreen class defined, let’s use it as the root widget in the kv file. In its basic form the kv file looks like this:

# File name: bets.kv

<BetsScreen>:
    orientation: 'vertical'

    ### TITLE LABEL ###

    ### PLAYER BETS ###

    ### GO BUTTON ###

And now we can have a look at each area one by one. Or maybe rather let’s handle the first and last areas right away, because they are very simple and straightforward, and then let’s discuss the Player Bets area in more detail.

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

The Title Label and Go Button Areas

For the Title Label we’ll use the BoldLabel that we defined before. It inherits from RegularLabel, which itself inherits from Label. We need to add the appropriate class rules above the root widget. As mentioned before, all class rules that are shared by more than one screen will eventually be moved to a separate file, but for now let’s just add them to the bets.kv file.

So, the kv file at this point looks like this:

# File name: bets.kv

### CLASS RULES ###

<RegularLabel@Label>:
    text_size: self.size
    halign: 'left'
    valign: 'center'

<BoldLabel@RegularLabel>:    
    bold: True

<BetsScreen>:
    orientation: 'vertical'
    padding: 10
    spacing: 10

    ### TITLE LABEL ###
    BoldLabel:
        text: "Bets"
        size_hint: (1, None)
        height: 30

    ### PLAYER BETS ###

    # just a placeholder for now
    Label:
        text: 'PLAYER BETS'

    ### GO BUTTON ###

    # Let's make the button look the same as in the Settings screen. 
    # Only the text should be different.
    Button:
        text: 'Go'
        size_hint: (None, None)        
        size: 200, 40
        pos_hint: {'center_x': 0.5}

As you can see, I added some padding and spacing to the root widget. If you now run the app, you’ll get this:

The Title Label and Go Button Areas

The Player Bets Area

And now let’s handle the middle part of the screen, the Player Bets area. Here’s the picture again:

The Player Bets Area - final

Here you can see two players only, because that’s what we set in the Settings screen, but there may be up to four players. Now, each player occupies one row. It contains some labels, a text input, a slider and four radio buttons with labels. For this area I’m going to use a vertical BoxLayout for the four rows (as you can see, some of them may be invisible, which we’ll take care of a bit later) and for each row I’ll use a horizontal BoxLayout. The code is pretty long, but there’s nothing new.

We have to add some class rules. As for the radio buttons we’ll add the PlayerSlugButton class. There will be a separate group set for each player because we want to be able to select one slug for each player. If we put all the radio buttons in one group, it would be only possible to select one slug for all the players altogether.

Python Jumpstart Course

Learn the basics of Python, including OOP.

with lots of exercises, easy to follow

The course is available on Udemy.

One more thing is the BetInput class. It will be used for the players’ bet amounts and will inherit from NumInput, which inherits from TextInput. We defined NumInput in the settings.kv file, so let’s just copy the class rule here and add the BetInput class. The BetInput will differ by width and the y-position.

As you can see in the picture above, there is a label with the dollar sign on it. We could use the DollarLabel class defined in the settings.kv screen, but there it inherits from Regular80x30Label class, in which the width and height properties are set to 80 and 30 respectively. We could overwrite these two properties, but I decided to take a simpler approach and just use a RegularLabel with the text property set to ‘$’.

Here’s the whole bet.kv file:

# File name: bets.kv

### CLASS RULES ###

<RegularLabel@Label>:
    text_size: self.size
    halign: 'left'
    valign: 'center'

<BoldLabel@RegularLabel>:    
    bold: True

# PlayerSlugButton inherits from CheckBox.
<PlayerSlugButton@CheckBox>:
    size_hint: (.5, 1)

# NumInput inherits from TextInput
<NumInput@TextInput>:
    multiline: False
    size_hint: None, None
    height: 30
    width: 250

# BetInput inherits from NumInput
<BetInput@NumInput>:    
    width: 120 
    pos_hint: {'center_y': .5}

<BetsScreen>:
    orientation: 'vertical'
    padding: 10
    spacing: 10

    ### TITLE LABEL ###
    BoldLabel:
        text: "Bets"
        size_hint: (1, None)
        height: 30

    ### PLAYER BETS ###

    BoxLayout:
        orientation: 'vertical'

        # player 1            
        BoxLayout:          
            spacing: 10
            
            RegularLabel:
                text: 'Player 1'
            
            RegularLabel:                    
                text: 'bets'
                size_hint: (.4, 1)
            
            BoxLayout: 
                spacing: 5                                   
                RegularLabel: 
                    text: '$'
                    # In the RegularLabel class the horizontal alignment is set to 'left',
                    # but can be easily overwritten here. 
                    halign: 'right'               
                BetInput: 
                    # just an arbitrary number for now  
                    text: '1000'    
                                
            Slider:
                # The min and max values will be for now set to 1 and 1000 respectively.
                min: 1
                max: 1000

                # value will be set to 1000 for now.                                   
                value: 1000

                # The slider should increment and decrement by 1.
                step: 1                    
            
            RegularLabel:
                text: 'on'
                size_hint: (.3, 1)
            
            BoxLayout:  
                PlayerSlugButton:
                    group: 'player1'                                              
                
                RegularLabel:
                    text: 'Speedster'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player1'
                
                RegularLabel:
                    text: 'Trusty'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player1'
                
                RegularLabel:
                    text: 'Iffy'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player1'

                RegularLabel:
                    text: 'Slowpoke'
                    
        # player 2 
        BoxLayout:          
            spacing: 10
            
            RegularLabel:
                text: 'Player 2'
            
            RegularLabel:                    
                text: 'bets'
                size_hint: (.4, 1)
            
            BoxLayout: 
                spacing: 5                                   
                RegularLabel: 
                    text: '$'
                    halign: 'right'               
                BetInput: 
                    text: '1000'    
                                
            Slider:
                min: 1
                max: 1000                             
                value: 1000
                step: 1                    
            
            RegularLabel:
                text: 'on'
                size_hint: (.3, 1)
            
            BoxLayout:  
                PlayerSlugButton:
                    group: 'player2'                                              
                
                RegularLabel:
                    text: 'Speedster'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player2'
                
                RegularLabel:
                    text: 'Trusty'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player2'
                
                RegularLabel:
                    text: 'Iffy'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player2'
                    
                RegularLabel:
                    text: 'Slowpoke'      

        # player 3 
        BoxLayout:          
            spacing: 10
            
            RegularLabel:
                text: 'Player 3'
            
            RegularLabel:                    
                text: 'bets'
                size_hint: (.4, 1)
            
            BoxLayout: 
                spacing: 5                                   
                RegularLabel: 
                    text: '$'
                    halign: 'right'               
                BetInput: 
                    text: '1000'    
                                
            Slider:
                min: 1
                max: 1000                           
                value: 1000
                step: 1                    
            
            RegularLabel:
                text: 'on'
                size_hint: (.3, 1)
            
            BoxLayout:  
                PlayerSlugButton:
                    group: 'player3'                                              
                
                RegularLabel:
                    text: 'Speedster'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player3'
                
                RegularLabel:
                    text: 'Trusty'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player3'
                
                RegularLabel:
                    text: 'Iffy'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player3'
                    
                RegularLabel:
                    text: 'Slowpoke'

        # player 4 
        BoxLayout:          
            spacing: 10
            
            RegularLabel:
                text: 'Player 4'
            
            RegularLabel:                    
                text: 'bets'
                size_hint: (.4, 1)
            
            BoxLayout: 
                spacing: 5                                   
                RegularLabel: 
                    text: '$'
                    halign: 'right'               
                BetInput: 
                    text: '1000'    
                                
            Slider:
                min: 1
                max: 1000                               
                value: 1000
                step: 1                    
            
            RegularLabel:
                text: 'on'
                size_hint: (.3, 1)
            
            BoxLayout:  
                PlayerSlugButton:
                    group: 'player4'                                              
                
                RegularLabel:
                    text: 'Speedster'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player4'
                
                RegularLabel:
                    text: 'Trusty'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player4'
                
                RegularLabel:
                    text: 'Iffy'
            
            BoxLayout:
                PlayerSlugButton:
                    group: 'player4'
                    
                RegularLabel:
                    text: 'Slowpoke'

    ### GO BUTTON ###    
    Button:
        text: 'Go'
        size_hint: (None, None)        
        size: 200, 40
        pos_hint: {'center_x': 0.5}

And this is what you will get if you now run the bets.py file and then resize the window:

Bets screen

This is more or less what we were aiming at, at least as far as the visual representation is concerned. Naturally, here we can see all four players, because their visibility will be taken care of later in the series. In the next part we’ll create the Results screen, which will replace the Bets screen after each race finishes. As I said before, in the final version both the Bets screen and the Results screen will be shown inside the Race screen which we already created.

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.


Spread the love

Leave a Reply