Skip to content
Home » Kivy Part 49 – Events in Kivy

Kivy Part 49 – Events in Kivy

Spread the love

Hey guys, in the previous part of the series we created the Game class, or rather renamed the SlugraceScreenManager class that we had defined long before. This is the class most of our game logic will go into. Part of the logic is that if we do something, like press a button or check a radio button, something should happen. This is what events are for. Yes, in this part we’re going to talk about events in Kivy. But before we start, here’s some info for you.

Book Info

I published a 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.

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…

We’ve been using events a lot since the beginning of this series. In this part we’ll try to systematize what we know about the basic usage of events in Kivy. Let’s take a break from the Slugrace project and use the test files (test.py and test.kv) for a while to practice events.

Overriding Existing Event Methods

Let’s rewrite our test files. Here’s the Python code:

# File name: test.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.config import Config
from kivy.properties import NumericProperty
from kivy.uix.button import Button

# Configuration
Config.set('graphics', 'width', '1200')
Config.set('graphics', 'height', '675') 
Config.set('graphics', 'resizable', '1')

class CustomButton(Button): 
    counter = NumericProperty(1)

class TestLayout(BoxLayout): 
    pass

class TestApp(App):
    def build(self):
        return TestLayout()

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

And here’s the kv file:

# File name: test.kv

<CustomButton>:
    font_size: 50   
    size_hint_x: .5
    text: str(self.counter) 

<TestLayout>:
    CustomButton:    
    CustomButton:

If you run the app, you will see the two buttons next to each other:

Overriding Existing Event Methods

The Button class has two methods which you already know, on_press and on_release. You can redefine them, so override their functionality. You can do it in two ways, either for the whole class (then they will be redefined for all instances of the class) or just for a single instance.

If you want the on_press event to do something on one instance only, you can easily do it in kv code. Let’s define a simple functionality that increases the counter value for the second button when it’s pressed. All you have to do is define the on_press event on just that button:

# File name: test.kv

<CustomButton>:
    font_size: 50   
    size_hint_x: .5
    text: str(self.counter) 

<TestLayout>:
    CustomButton:    
    CustomButton:
        on_press: self.counter += 1

Now if you run the program and click on the second button, the counter value will change. But it won’t change if you press the first button:

Overriding Existing Event Methods

You can also define an event on each instance individually so that it works in a different way. Have a look at this:

# File name: test.kv

<CustomButton>:
    font_size: 50   
    size_hint_x: .5
    text: str(self.counter) 

<TestLayout>:
    CustomButton:
        on_press: self.counter -= 1
    
    CustomButton:
        on_press: self.counter += 1

Now the counter will be increased on the second button, but decreased on the first one:

Overriding Existing Event Methods

If you want the event to work the same for all instances, a better solution that defining it on each instance and thus making the code repetitive, is to define it in the class rule or in Python code. Suppose we want the counter value to be increased on any instance of the button when pressed. Here’s how we can do it in kv:

# File name: test.kv

<CustomButton>:
    font_size: 50   
    size_hint_x: .5
    text: str(self.counter) 
    on_press: self.counter += 1

<TestLayout>:
    CustomButton:    
    CustomButton:

Now if you run the app and press both buttons several times, you will see something like this:

Overriding Existing Event Methods

Alternatively, you could remove the code from the kv file and put it in the Python file:

# File name: test.py

...

class CustomButton(Button): 
    counter = NumericProperty(1)  

    def on_press(self):
        self.counter += 1

class TestLayout(BoxLayout): 
    ...

You can also put the code in both Python code and kv code. For example, if we want the counter value to be increased for each button, but additionally we want the font size to be increased only on the second button, we can put the shared behavior in the Python file (or in the class rule in kv) and the individual behavior on the particular instance in kv. Here’s how we can do it. First, the Python code:

# File name: test.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.config import Config
from kivy.properties import NumericProperty
from kivy.uix.button import Button

# Configuration
Config.set('graphics', 'width', '1200')
Config.set('graphics', 'height', '675') 
Config.set('graphics', 'resizable', '1')

class CustomButton(Button): 
    counter = NumericProperty(1)  

    # This will work for each button.
    def on_press(self):
        self.counter += 1

class TestLayout(BoxLayout): 
    pass

class TestApp(App):
    def build(self):
        return TestLayout()

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

And here’s the kv file:

# File name: test.kv

<CustomButton>:
    font_size: 50   
    size_hint_x: .5
    text: str(self.counter) 

<TestLayout>:
    CustomButton:
    
    CustomButton:
        # This will work only on this button.
        on_press: self.font_size += 10

If you now run the program and press the two buttons several times, you will see the following:

Overriding Existing Event Methods

Here we’ve been working on the Button’s on_press event only, but naturally you can override any other event method on any other widget like that.

Triggering Methods

In the previous example we just changed the button’s counter and font_size properties by passing some simple Python code directly in kv. But sometimes we need something more complex to happen each time an event is triggered. If this is the case, we can define a method in the Python file and call it from the kv file.

Here we’re defining a method in the CustomButton class:

# File name: test.py

...

class CustomButton(Button): 
    counter = NumericProperty(1)  

    def reset_counter(self):
        self.counter += 1

        if self.counter > 5:
            self.counter = 1

class TestLayout(BoxLayout): 
    ...

And here we’re calling it from the kv file when the second button is pressed:

# File name: test.kv

<CustomButton>:
    font_size: 50   
    size_hint_x: .5
    text: str(self.counter) 

<TestLayout>:
    CustomButton:
    
    CustomButton:
        # This will work only on this button.
        on_press: self.reset_counter()

If you now run the app, the counter will be reset back to 1 each time its value exceeds 5.

***

There’s much more to propreties than that. You can find more examples in my book. Also in my book I’m explaining how to bind and unbind events using the bind and unbind methods. I’m not going to discuss these two methods in this series, but we might occasionally be using them in the future. If so, I’ll explain what the code does and how it works when necessary.


Spread the love

Leave a Reply