简体   繁体   中英

How to switch screens in Kivy Python file from outside of a screen instance

I am trying to write a function in a Kivy app that will handle turning the backlight of the device screen on and off. Since I want this function to run independent of whatever screen the user is on, I would like to call the transition to the "Screen Saver" screen from outside of a Screen instance. The goal is to have a timer that starts counting upon entering the app that will schedule a function that turns of the screen brightness as well as transitions the screen to a screensaver screen which consists only of a button (so that when you touch the display to wake it up, it does not trigger any of the buttons of the app). When you hit the button of the screensaver screen, it will turn on the display brightness and return the home (or return to the last screen used, but that is the next hurdle).

Below is a stripped-down version of my code:

os_example.py:

import subprocess
import kivy
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
from kivy.uix.screenmanager import FadeTransition


# ---- Backlight Setup -----------

backlight_command = "sudo rpi-backlight -b 50"
process = subprocess.Popen(backlight_command.split())

# --------------------------------
 

class HubHome(Screen):
    pass


class Lighting(Screen):
    pass


class Climate(Screen):
    pass


class ScreenSaver(Screen):
    pass


class WindowManager(ScreenManager):
    
    def __init__(self, **kwargs):
        super(WindowManager, self).__init__(**kwargs)

    def switch_to_screensaver(self):
        self.current = "screensaver"



def dimScreen():
    backlight_command = "sudo rpi-backlight -b 20 --duration 0.3"
    process = subprocess.Popen(backlight_command.split())
    print("dimmed")


def sleepScreen(*args):
    backlight_command = "sudo rpi-backlight -b 0"
    process = subprocess.Popen(backlight_command.split())
    App.get_running_app().root.ids.manager.transition = FadeTransition(duration = .3)
    App.get_running_app().root.ids.manager.current = "screensaver"


def brightnessUp():
    backlight_command = "sudo rpi-backlight -b 50"
    process = subprocess.Popen(backlight_command.split())


def on_motion(self, etype, motionevent, **kwargs):
    brightnessUp()
    Clock.unschedule(sleepScreen)
    Clock.schedule_once(sleepScreen, 5)


Window.bind(on_motion=on_motion)

kv = Builder.load_file("so_example.kv")


class HubApp(App):
    def build(self):
        return kv
    

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

so_example.kv:

#: import SlideTransition kivy.uix.screenmanager.SlideTransition

WindowManager:
    HubHome:
    Lighting:
    Climate:
    ScreenSaver:
        id: screensaver

<Button>:
    font_size: 28
    
<Title@Label>:
    font_size: 36
    height: 100
    size_hint_y: None


<HubHome>:
    name: "hubhome"
    
    GridLayout:
        cols: 1
    
        Title:
            text: "Hub Home"
    
        GridLayout:
            cols: 2
            
            Button:
                text: "Lighting"
                on_release:
                    root.manager.transition.direction = "right"
                    app.root.current = "lighting"

            Button
                text: "Climate"
                on_release:
                    root.manager.transition.direction = "left"
                    app.root.current = "climate"


<Lighting>:
    name: "lighting"
    
    GridLayout:
        cols: 1
    
        Title:
            text: "Lighting"
        
        Button:
            text: "Back"
            on_release:
                app.root.current = "hubhome"
                root.manager.transition.direction = "left"  


<Climate>:
    name: "climate"
    
    GridLayout:
        cols: 1
    
        Title:
            text: "Climate"
        
        Button:
            text: "Back"
            on_release:
                app.root.current = "hubhome"
                root.manager.transition.direction = "right" 
            
            
<ScreenSaver>:
    name: "screensaver"
    
    Button:
        background_color: (0,0,0, 1)
        on_press:
            app.root.transition = SlideTransition(direction = "up")
            root.manager.transition.direction = "up"
            app.root.current = "hubhome"

I have tried instantiating a screen manager in the Python code, like so:

wm = WindowManager()
wm.add_widget(HubHome())
wm.add_widget(Climate())
wm.add_widget(Lighting())
wm.add_widget(ScreenSaver(name='screensaver'))

and then trying to call the following code in the "sleepScreen" function, but to no success.

wm.current = 'screensaver'

As well, this line of code keeps throwing an error:

App.get_running_app().root.ids.manager.current = "screensaver"

Error:

AttributeError: 'super' object has no attribute '__getattr__'

It seems pretty straightforward to transition screens from within a Screen instance, but I'm having a really hard time performing it outside of a Screen instance. Please let me know if you have any suggestions- thank you!

The root Widget of your App is the ScreenManager ( WindowManager ), so your sleepScreen() method can access the WindowManager just by referencing the App root property. The sleepScreen() method can be:

def sleepScreen(*args):
    backlight_command = "sudo rpi-backlight -b 0"
    process = subprocess.Popen(backlight_command.split())
    App.get_running_app().root.transition = FadeTransition(duration=.3)
    App.get_running_app().root.current = "screensaver"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM