Kivy screenmanager:在超时后用信号切换屏幕

2024-07-04 08:54:12 发布

您现在位置:Python中文网/ 问答频道 /正文

目标是在一段时间内没有按下按钮、输入文本或其他任何内容时,移动到设置屏幕

事实上,功能就像某种屏幕保护程序

代码版本1

import signal
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen


class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass


class wiscApp(App):

    def setscreensaver(self, *args):
        print("switching to settings")
        # --> here I need to switch to the settings screen
        # but this doens't work, bnoth sm and setscreen are not known here
        sm.switch_to(setscreen)

    def resetscreensavertimeout(self):
        print("resetting screensaver timer")
        signal.alarm(10)  # just 5 seconds for debugging

    def build(self):
        sm = ScreenManager()
        setscreen = SettingsScreen(name='settings')
        sm.add_widget(MenuScreen(name='menu'))
        sm.add_widget(setscreen)
        signal.signal(signal.SIGALRM, self.setscreensaver)
        self.resetscreensavertimeout()
        return sm


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

和.kv

<MenuScreen>:
    BoxLayout:
        orientation: 'vertical'
        BoxLayout:
            Button:
                text: "resettimeout"
                on_press: app.resetscreensavertimeout()
            Button:
                text: "do other things"
        Button:
            text: 'settings'
            on_press: root.manager.current = 'settings'

<SettingsScreen>:
    BoxLayout:
        Button:
            text: "stop app"
            on_press: app.stop()
        Button:
            text: 'Back to menu'
            on_press: root.manager.current = 'menu'

在调用setscreensaver函数中的sm.switch_to(setscreen)之前,这一切都是完美的

我尝试了以下方法: 代码版本2

import signal
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen


class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass


class wiscApp(App):
    sm = ScreenManager()
    setscreen = SettingsScreen(name='settings')

    def setscreensaver(self, *args):
        print("switching to settings")
        # --> here I need to switch to the settings screen
        # but this doens't work, bnoth sm and setscreen are not known here
        self.sm.switch_to(self.setscreen)

    def resetscreensavertimeout(self):
        print("resetting screensaver timer")
        signal.alarm(10)  # just 5 seconds for debugging

    def build(self):
        self.sm.add_widget(MenuScreen(name='menu'))
        self.sm.add_widget(self.setscreen)
        signal.signal(signal.SIGALRM, self.setscreensaver)
        self.resetscreensavertimeout()
        return self.sm


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

但是设置屏幕是空白的! 在代码的第一个版本中,我理解它不起作用:sm和setscreen都是该函数中未定义的变量。 在第二个版本中,我不明白为什么设置屏幕是空白的

编辑 ***准则第3版***

import signal
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen


class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass


class wiscApp(App):
    def setscreensaver(self, *args):
        print("switching to settings")
        # --> here I need to switch to the settings screen
        # but this doens't work, bnoth sm and setscreen are not known here
        self.sm.switch_to(self.setscreen)

    def resetscreensavertimeout(self):
        print("resetting screensaver timer")
        signal.alarm(10)  # just 5 seconds for debugging

    def build(self):
        self.sm = ScreenManager()
        self.setscreen = SettingsScreen(name='settings')
        self.sm.add_widget(MenuScreen(name='menu'))
        self.sm.add_widget(self.setscreen)
        signal.signal(signal.SIGALRM, self.setscreensaver)
        self.resetscreensavertimeout()
        return self.sm


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

在这个版本3中,使用信号转换到设置屏幕可以正常工作,但是如果我单击菜单按钮,就会出现此错误(此错误不会出现在其他版本的代码中):

 kivy.uix.screenmanager.ScreenManagerException: No Screen with name "menu".

所以,我有几个问题

  1. 如何在每次按下按钮时重置计时器,文本为 输入任何内容,而不是为每个事件定义回调 (例如,在.kv代码中按app.resetscreensavertimeout())时)
  2. 如何在第一个版本中切换到设置屏幕 密码
  3. 为什么代码版本2中的设置屏幕为空
  4. 为什么在版本3中会出现错误
  5. 有没有其他(更好的)编码方法

非常感谢


Tags: tonameimportself版本signalsettings屏幕
1条回答
网友
1楼 · 发布于 2024-07-04 08:54:12

下面是代码的修改版本,它使用Clock.schedule_once()而不是signal

class wiscApp(App):
    def setscreensaver(self, *args):
        print("switching to settings")
        self.resetscreensavertimeout()
        self.sm.current = 'settings'

    def resetscreensavertimeout(self, *args):
        print("resetting screensaver timer")
        self.resetEvent.cancel()
        self.resetEvent = Clock.schedule_once(self.setscreensaver, 5)

    def build(self):
        self.sm = ScreenManager()
        self.setscreen = SettingsScreen(name='settings')
        self.sm.add_widget(MenuScreen(name='menu'))
        self.sm.add_widget(self.setscreen)
        self.resetEvent = Clock.schedule_once(self.setscreensaver, 5)
        Window.bind(on_touch_down=self.resetscreensavertimeout)
        Window.bind(on_key_down=self.resetscreensavertimeout)
        return self.sm

这还使用Window.bind()触发每当按下按钮或按键时的超时重置

相关问题 更多 >

    热门问题