Kivy: changing screen from python code

16,299

Solution 1

Here is a simple 'game' example based on your additional info. When a player enters the game screen, their health points are bleeding. When the pool reaches zero, they are sent back to menu screen.

main.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.properties import ObjectProperty, NumericProperty

import time
import threading


class ScreenOne(Screen):
    pass


class ScreenTwo(Screen):
    health_points = NumericProperty(100)

    def __init__(self, **kwargs):
        super(ScreenTwo, self).__init__(**kwargs)

    def on_health_points(self, instance, value):
        if value < 1:
            self.changeScreen()

    def on_enter(self, *args):
        thread = threading.Thread(target=self.bleed)
        thread.daemon = True
        thread.start()

    def bleed(self, *args):
        while self.health_points > 0:
            self.health_points -= 5
            time.sleep(0.1)

    def displayScreenThenLeave(self):
        self.changeScreen()

    def changeScreen(self):
        if self.manager.current == 'screen1':
            self.manager.current = 'screen2'
        else:
            self.manager.current = 'screen1'


class Manager(ScreenManager):

    screen_one = ObjectProperty(None)
    screen_two = ObjectProperty(None)


class ScreensApp(App):

    def build(self):
        m = Manager(transition=NoTransition())
        return m

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

screens.kv:

#:kivy 1.8.0

<ScreenOne>:

    BoxLayout:
        orientation: "vertical"
        size: root.size
        spacing: 20
        padding: 20

        Label:
            text: "Main Menu"
        Button:
            text: "Button 1"
            on_release:
                root.manager.current = "screen2"
                # reset health_points
                root.manager.ids.screen_two.health_points = 100

<ScreenTwo>:        

    BoxLayout:
        orientation: "vertical"
        size: root.size
        spacing: 20
        padding: 20

        Label:
            id: label
            text: "health points: " + str(root.health_points)

<Manager>:
    id: screen_manager

    screen_one: screen_one
    screen_two: screen_two

    ScreenOne:
        id: screen_one
        name: "screen1"
        manager: screen_manager

    ScreenTwo:
        id: screen_two
        name: "screen2"
        manager: screen_manager

Solution 2

Make these little changes

#import Clock to create a schedule
from kivy.clock import Clock

class ScreenTwo(Screen):

    def __init__(self,**kwargs):
        super(ScreenTwo, self).__init__(**kwargs)

    #this is event that is fired when the screen is displayed.
    def on_enter(self, *args):
        self.displayScreenThenLeave()

    def displayScreenThenLeave(self):
        #schedued after 3 seconds
        Clock.schedule_once(self.changeScreen, 3)

    def changeScreen(self, *args):
        #now switch to the screen 1
        self.parent.current = "screen1"

for more imformation go to these links Screen Manager, Clock

Share:
16,299
R. Duke
Author by

R. Duke

Updated on June 28, 2022

Comments

  • R. Duke
    R. Duke almost 2 years

    I'm putting together a Kivy app and am having some problems working out how to change screens at an arbitrarily chosen point within the python code.

    In the following example, I would like to know how to switch from Screen2 back to Screen1 by executing a function my main.py file.

    Here's my main.py:

    # -*- coding: utf-8 -*-
    
    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
    from kivy.properties import ObjectProperty
    from functools import partial
    
    import random
    import time
    
    class ScreenOne(Screen):
        pass
    
    class ScreenTwo(Screen):
    
        def __init__(self,**kwargs):
            super(ScreenTwo, self).__init__(**kwargs)
            self.displayScreenThenLeave()
    
        def displayScreenThenLeave(self):
            # 'time.sleep(3)' is a stand-in for "execute some code here"
            time.sleep(3)
            self.changeScreen()
    
        # I want this function to send the user back to ScreenOne.
        def changeScreen(self):
            pass
    
    class Manager(ScreenManager):
    
        screen_one = ObjectProperty(None)
        screen_two = ObjectProperty(None)
    
    class ScreensApp(App):
    
        def build(self):
            m = Manager(transition=NoTransition())
            return m
    
    if __name__ == "__main__":
        ScreensApp().run()
    

    And here's my screens.kv:

    #:kivy 1.8.0
    
    <ScreenOne>:
    
        BoxLayout:
            orientation: "vertical"
            size: root.size
            spacing: 20
            padding: 20
    
            Label:
                text: "Main Menu"
            Button:
                text: "Button 1"
                on_release: root.manager.current = "screen2"
    
    <ScreenTwo>:        
    
        BoxLayout:
            orientation: "vertical"
            size: root.size
            spacing: 20
            padding: 20
    
            Label:
                id: label
                text: "Welcome to Screen 2, please wait three seconds"
    
    <Manager>:
        id: screen_manager
    
        screen_one: screen_one
        screen_two: screen_two
    
        ScreenOne:
            id: screen_one
            name: "screen1"
            manager: screen_manager
    
        ScreenTwo:
            id: screen_two
            name: "screen2"
            manager: screen_manager
    

    As should be pretty evident, I'm a total beginner at Kivy, so I'd really appreciate it if you could show me exactly what I need to change, including the specific syntax that should be used.

    Thanks in advance for your time and wisdom.

  • R. Duke
    R. Duke over 8 years
    Thanks very much @kiok46 that's a great answer. Unfortunately, I still haven't been able to fix my problem. Appologies for not wording my question better. What I really need to know is how to change screen at an arbitrarily choosen point in the execution of the python code, not how to load a screen and then automatically leave it again it after waiting of for a certain number of seconds (though that is cool to know). The time.sleep(3) line was just meant as a stand in for #execute random code here. Sorry for not being clearer. Any chance you could help me out a bit more?
  • jligeza
    jligeza over 8 years
    @R.Duke Could you write what exactly are you trying to do, without unnecessary abstraction? What is screen one, and what is screen two? In which case do you need to change screen to #1, and when to screen #2?
  • R. Duke
    R. Duke over 8 years
    @zmarszczony Screen One is a menu screen, that at present just contains a single button sending you to Screen Two. Screen Two is a game screen. For the sake of giving a simple example, the "game" in Screen Two just consists of waiting for three seconds, but it could be any sort of game. What I need to know how to do is how to send the user from Screen Two back to Screen One when certain conditions are met, e.g. when their health equals zero.
  • R. Duke
    R. Duke over 8 years
    Awesome. Thanks very much.
  • Vishal Kumar Sahu
    Vishal Kumar Sahu over 3 years
    self.parent.current = "your_screen_name"