A Complete Code Example Of Kivy A Working Screen Manager Reference Written In KV Language

Brad Fortner picture Brad Fortner · Sep 10, 2017 · Viewed 14k times · Source

I've been trying to build my kv language skills from Accessing id/widget of different class from a kivy file (.kv) using Kivy's clock? by working with the information found in Kivy Screen manager reference in kv language. Unfortunately the latter post does not contain a complete working code example so I can't understand how to make changes to the text elements in a on a specific screen in a multi-screen Kivy application.

After searching much of the day I can't find any simple concrete working examples of how to build a multi-screen app in kv language so here I am. I don't seem to be able to set up the proper references to the individual screens so I can change them.

In the simple example code below I have built a four screen application that switches automatically between four screens. There are 2 things I'd like to learn from this question;

  1. The kv language code that would set-up as much of the screenmanager as possible. ie. can lines 43 thru 47 be reduced or eliminated by the kv language?

  2. The actual python code (which I believe would go on line 56 of the app) that changes the text on the first screen to "Hi I'm The Fifth Screen" prior to it displayed the second time.

Code below. Thanks in advance. ....brad....

import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_string("""
<FirstScreen>:
    name: '_first_screen_'
    Label:
        id: first_screen
        text: "Hi I'm The First Screen"
<SecondScreen>:
    name: '_second_screen_'
    Label:
        id: second_screen
        text: "Hi I'm The Second Screen"
<ThirdScreen>:
    name: '_third_screen_'
    Label:
        id: third_screen
        text: "Hi I'm The Third Screen"
<FourthScreen>:
    name: '_fourth_screen_'
    Label:
        id: fourth_screen
        text: "Hi I'm The Fourth Screen"
""")

class FirstScreen(Screen):
    pass

class SecondScreen(Screen):
    pass

class ThirdScreen(Screen):
    pass

class FourthScreen(Screen):
    pass

sm = ScreenManager()
sm.add_widget(FirstScreen())
sm.add_widget(SecondScreen())
sm.add_widget(ThirdScreen())
sm.add_widget(FourthScreen())

class SwitchingScreenApp(App):

    def build(self):
        Clock.schedule_once(self.screen_switch_one, 2)
        Clock.schedule_once(self.screen_switch_two, 4)
        Clock.schedule_once(self.screen_switch_three, 6)
        Clock.schedule_once(self.screen_switch_four, 8)
        # Want to place the code here that changes the first_screen text to "Hi I'm The Fifth Screen"
        Clock.schedule_once(self.screen_switch_one, 10)
        return sm

    def screen_switch_one(a,b):
        sm.current = '_first_screen_'
    def screen_switch_two(a,b):
        sm.current = '_second_screen_'
    def screen_switch_three(a,b):
        sm.current = '_third_screen_'
    def screen_switch_four(a,b):
        sm.current = '_fourth_screen_'

SwitchingScreenApp().run()

Answer

ikolim picture ikolim · Sep 11, 2017

Firstly, I would suggest splitting your codes into Python and kv file, because as your program grows, it will be easier to maintain the UIs/widgets and the Python code. Please refer to the example (app_with_kv.py, switchingscreen.kv, output) for details.

Question: 1

The kv language code that would set-up as much of the screenmanager as possible. ie. can lines 43 thru 47 be reduced or eliminated by the kv language?

sm = ScreenManager()
sm.add_widget(FirstScreen())
sm.add_widget(SecondScreen())
sm.add_widget(ThirdScreen())
sm.add_widget(FourthScreen())

Answer

Step 1

Add a class MyScreenManager into your Python code.

class MyScreenManager(ScreenManager):
    pass
...
    def build(self):
        sm = MyScreenManager()

Step2

Addd the following kv rule either inline or in a separate kv file. This is equivalent to using the statement, sm.add_widget() four times.

<MyScreenManager>:
    FirstScreen:
    SecondScreen:
    ThirdScreen:
    FourthScreen:

Question: 2

The actual python code (which I believe would go on line 56 of the app) that changes the text on the first screen to "Hi I'm The Fifth Screen" prior to it displayed the second time.

Answer

You have to place the following code in any of the 3 switching screen methods excluding the first switching screen method, screen_switch_one()

self.ids.first_screen.ids.first_screen_label.text = "Hi I'm The Fifth Screen"

Example

app_with_kv.py

from kivy.app import App
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen


class FirstScreen(Screen):
    pass


class SecondScreen(Screen):
    pass


class ThirdScreen(Screen):
    pass


class FourthScreen(Screen):
    pass


class MyScreenManager(ScreenManager):

    def __init__(self, **kwargs):
        super(MyScreenManager, self).__init__(**kwargs)
        Clock.schedule_once(self.screen_switch_one, 2)

    def screen_switch_one(self, dt):
        self.current = '_first_screen_'
        Clock.schedule_once(self.screen_switch_two, 2)

    def screen_switch_two(self, dt):
        self.current = '_second_screen_'
        self.ids.first_screen.ids.first_screen_label.text = "Hi I'm The Fifth Screen"
        Clock.schedule_once(self.screen_switch_three, 2)

    def screen_switch_three(self, dt):
        self.current = '_third_screen_'
        Clock.schedule_once(self.screen_switch_four, 2)

    def screen_switch_four(self, dt):
        self.current = '_fourth_screen_'
        Clock.schedule_once(self.screen_switch_one, 2)


class SwitchingScreenApp(App):

    def build(self):
        return MyScreenManager()


if __name__ == "__main__":
    SwitchingScreenApp().run()

switchingscreen.kv

#:kivy 1.10.0

<MyScreenManager>:
    FirstScreen:
        id: first_screen
    SecondScreen:
    ThirdScreen:
    FourthScreen:

<FirstScreen>:
    name: '_first_screen_'
    Label:
        id: first_screen_label
        text: "Hi I'm The First Screen"

<SecondScreen>:
    name: '_second_screen_'
    Label:
        id: second_screen_label
        text: "Hi I'm The Second Screen"

<ThirdScreen>:
    name: '_third_screen_'
    Label:
        id: third_screen_label
        text: "Hi I'm The Third Screen"

<FourthScreen>:
    name: '_fourth_screen_'
    Label:
        id: fourth_screen_label
        text: "Hi I'm The Fourth Screen"

Output

enter image description here