Hey guys, in the previous part of the Kivy series we were talking about switching between screens. Today we’ll be talking about managing screens. But before we move on, here’s some info for you.
Table of Contents
Book Info
Managing Screens
In the preceding parts of the series we added two screen managers that switch between screens. Now the general flow of our application is as it should be, but still there are some warnings and errors visible in the terminal. This is because we have to clean the code up a bit.
Redundant App Launching Code
First of all, now the application is always launched in one place, in the main.py file. But we still have the code in the particular screens that we used before to run them as individual apps. Here’s an example from the Settings screen:
# File name: settings.py
import kivy
from kivy.app import App
...
class SettingsApp(App):
def build(self):
return SettingsScreen()
if __name__ == '__main__':
SettingsApp().run()
Let’s remove the code we don’t need anymore. Now the settings.py file should look like this:
# File name: settings.py
import kivy
from kivy.uix.boxlayout import BoxLayout
from kivy.config import Config
from kivy.properties import StringProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
# Configuration
Config.set('graphics', 'width', '1200')
Config.set('graphics', 'height', '675')
Config.set('graphics', 'resizable', '1')
Builder.load_file('widgets.kv')
class PlayerCount(BoxLayout):
count_text = StringProperty('')
class PlayerSettings(BoxLayout):
label_text = StringProperty('')
class SettingsScreen(Screen):
pass
Now we should remove the corresponding parts in the race.py, bets.py, results.py and gameover.py files, so first the import of the App class, then the class that inherits from App and the code that runs the program. It’s very easy, just do it yourself.
kv Files loaded Multiple Times
As you remember, we used the load_file method in the Builder class to load the widgets.kv file in each of the screens, so multiple times. Here’s how we did it:
Builder.load_file('widgets.kv')
As I mentioned before, a kv file should be loaded only once. We’ll load the file only in the main.py file:
# File name: main.py
...
# Configuration
...
# kv files
Builder.load_file('settings.kv')
Builder.load_file('race.kv')
Builder.load_file('gameover.kv')
# We will load the widgets.kv file only once, right here.
Builder.load_file('widgets.kv')
class SlugraceScreenManager(ScreenManager):
...
Now we’ll remove the code from the other Python files that loads the widgets.kv file, so in settings.py, race.py, bets.py, results.py and gameover.py. Just make sure you don’t forget any of these locations.
Also, in all the Python files except race.py, you can remove the code that imports the Builder class because it was only used with the widgets.kv file in mind. But don’t remove the import from the race.py file because it’s used there to load the Bets and Results screens.
Now the widgets.kv file is loaded only once, in the main.py file, and all screens have access to the widgets defined in it. If you run the app now, it’ll work like before.
Configuration Code
Now that we put the configuration code in the main.py file, we don’t need it in the other locations. So, again, go through the screens one by one and remove the code that imports the Config class, which looks like so:
from kivy.config import Config
And then remove the following lines of code in each screen:
# Configuration
Config.set('graphics', 'width', '1200')
Config.set('graphics', 'height', '675')
Config.set('graphics', 'resizable', '1')
Just make sure you don’t remove it from the main.py file as well by accident. Now our Python files are simplified and the app is configured in one place only.
Error Loading Texture
If you now run the app, it will work like before, but in the terminal you will see the following error, repeated multiple times:
[ERROR ] [Image ] Error reading file assets/slugs/.png
You can see the error although the images are displayed correctly. So, what’s the problem? The problem is that the program tries to load the image in the class rule. We have the following code in the race.kv file:
# File name: race.kv
#:import race race
...
<SlugImage>:
...
# the body image
Image:
source: 'assets/slugs/' + root.body_image + '.png'
# the left eye image
Image:
...
source: 'assets/slugs/' + root.eye_image + '.png'
...
# the right eye image
Image:
...
source: 'assets/slugs/' + root.eye_image + '.png'
...
<RaceScreen>:
...
So the program tries to resolve the source string by concatenating the first part of the path with root.body_image or root.eye_image and the string ‘.png’. But these two properties were set to empty strings in the Python file:
# File name: race.py
...
class SlugImage(RelativeLayout):
body_image = StringProperty('')
eye_image = StringProperty('')
...
Then the source is set correctly for each slug in each SlugImage widget further in the kv code, where the body_image and eye_image properties are set, but we still have the error in the terminal. So, as it works, we could just ignore the errors, but it’s not good to have errors, so let’s fix it.
In the kv file we’ll set the source to the concatenated string only if the body_image and eye_image properties are not empty strings. If they are, the source will be set to None. Here’s the code:
# File name: race.kv
#:import race race
...
<SlugImage>:
...
# the body image
Image:
source: 'assets/slugs/' + root.body_image + '.png' if root.body_image else None
# the left eye image
Image:
...
source: 'assets/slugs/' + root.eye_image + '.png' if root.eye_image else None
...
# the right eye image
Image:
...
source: 'assets/slugs/' + root.eye_image + '.png' if root.eye_image else None
...
<RaceScreen>:
...
If you run the program now and navigate to the Race screen (by pressing the Ready button), it will work and look like before and the errors will be gone too.
In the next part of the series we’ll be talking about transitions. This is what you see when a screen manager switches from one screen to another.