【问题标题】:switch screenmanager inside layout在布局内切换屏幕管理器
【发布时间】:2016-12-26 23:10:37
【问题描述】:

我正在尝试使 BoxLayout 内的 ScreenManager 工作,因此我可以在屏幕的每个屏幕下方都有一个固定工具箱。我设法显示了第一个屏幕(感谢this question),但是,当我尝试切换到另一个屏幕时,应用程序崩溃了,说没有其他屏幕。

实际上,真的没有其他屏幕:屏幕管理的 init 内的两个打印都没有显示任何内容。我不知道为什么。

没有工具栏(当然,只有 ScreeManager(ment) 和代码中的必要调整)一切正常。

我尝试将_widget 添加到 ScreenManagement 并填充了 screen_names,但我无法在屏幕之间切换。

我错过了什么?

错误的最后部分:

screen = self.get_screen(value)
   File "C:\Python27\lib\site-packages\kivy\uix\screenmanager.py", line 944, in get_screen
     raise ScreenManagerException('No Screen with name "%s".' % name)
 ScreenManagerException: No Screen with name "init".

Windows 7、Python 2.7、Kivy 1.9.1

这是 ClassApp.py:

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

#just solving my weak GPU issue
from kivy import Config
Config.set('graphics', 'multisamples', '0')

kivy.require('1.9.1')

class Init(Screen):
    pass

class Menu(Screen):
    pass

class ScreenManagement(ScreenManager):

    def __init__(self,**kwargs):
        print('before super: ', self.screen_names)
        super(ScreenManagement,self).__init__(**kwargs)
        print('after super: ', self.screen_names)

    def switch_to_menu(self):
        self.current = 'menu'
        print('going to menu')

    def switch_to_init(self):
        self.current = 'init'
        print('going to init')

class ClassAllScreen(BoxLayout):
    sm = ScreenManagement()
    sm.transition = NoTransition()
    pass

class ClassApp(App):

    def build(self):
        self.root = ClassAllScreen()
        return self.root

if __name__ == '__main__':
    ClassApp().run()

这里是 Class.kv:

<Init>: #first Screen
    name: 'init'
    BoxLayout:
        orientation:'vertical'
        padding:20
        spacing:10
        Button:
            text:'uppest'
        GridLayout:
            spacing:10
            cols:2

            Button:
                text:'upper left'
            Button:
                text:'upper right'
            Button:
                text:'bottom left'
            Button:
                text:'bottom right'
        Button:
            text:'bottomest: go to menu'
            on_press:app.root.sm.switch_to_menu()       

<Menu>: #second Screen
    name: 'menu'

    BoxLayout:
        orientation:'vertical'
        padding:20
        spacing:10
        GridLayout:
            spacing:10
            cols:2

            Button:
                text:'upper left'
            Button:
                text:'upper right'
            Button:
                text:'bottom left'
            Button:
                text:'bottom right'
        Button:
            text:'bottomy'
        Button:
            text:'bottomest: go to init'
            on_press:app.root.sm.switch_to_init()

<ScreenManagement>: #including both the Screens in ScreenManager
    Menu:
    Init:

<ClassAllScreen>: #all the display with ScreenManager and "Toolbar"
    orientation:'vertical'
    ScreenManagement:
    BoxLayout:
        size_hint_y: None
        height: 60
        spacing: 5
        padding: 5,5,0,5

        canvas:
            Color:
                rgba: .1,.1,.1,1
            Rectangle:
                pos: self.pos
                size: self.size
        Button:
            text:'1'
            size_hint_x: None
            width: 60
        Button:
            text:'2'
            size_hint_x: None
            width: 60
        Button:
            text:'3'
            size_hint_x: None
            width: 60

【问题讨论】:

    标签: python python-2.7 kivy kivy-language


    【解决方案1】:

    首先,您需要将屏幕添加到屏幕管理器。
    为此,您可以在 ScreenManager 类中执行类似的操作。

    def __init__(self,**kwargs):
        super(ScreenManagement,self).__init__(**kwargs)
        self.add_widget(Init(name="init"))
        self.add_widget(Menu(name="menu"))
    

    现在两个屏幕将有一个经理,即ScreenManagement
    因此,在您的 kv 代码中,您可以像这样调用管理器:

    Button:
        text:'bottomest: go to menu'
        on_press:root.manager.switch_to_menu()  
    

    如果你不想做方法,你也可以这样做:

    Button:
        text:'bottomest: go to menu'
        on_press:root.manager.current = 'menu'
    

    您的代码也有问题,您将屏幕管理器添加到boxlayout,并尝试返回boxlayout。你不能这样做。您一次只能显示一个屏幕。所以我猜你想要第三个屏幕。您应该做的是在您的构建方法中重新启动屏幕管理器,并且只向其中添加屏幕。
    我写了一个例子。我不知道你是否想要这样的东西。

    import kivy
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.lang import Builder
    
    
    Builder.load_string("""
    
    <Init>:
        name: 'init'
        BoxLayout:
            orientation:'vertical'
            Button:
                text:'go to menu'
                on_press:root.manager.current = "menu"
    
    
    <Menu>:
        name: 'menu'
    
        BoxLayout:
            orientation:'vertical'
            Button:
                text:'go to init'
                on_press:root.manager.current = "init"
    
    
    <ClassAllScreen>:
        BoxLayout:
            orientation:'vertical'
            Button:
                text:'go to init'
                on_press:root.manager.current = "init"
            Button:
                text:'go to menu'
                on_press:root.manager.current = "menu"
    
    """)
    
    
    class Init(Screen):
        pass
    
    class Menu(Screen):
        pass
    
    class ClassAllScreen(Screen):
        pass
    
    
    class ClassApp(App):
    
        def build(self):
            sm = ScreenManager()
            sm.add_widget(ClassAllScreen(name="main"))
            sm.add_widget(Init(name="init"))
            sm.add_widget(Menu(name="menu"))
            return sm
    
    
    if __name__ == '__main__':
        ClassApp().run()
    

    【讨论】:

    • 感谢您的回答。但是,虽然打印显示我有一个名为“菜单”的屏幕,但仍然会出现错误:“ScreenManagerException:没有名称为“菜单”的屏幕。”
    • @HenriqueGarcia 立即尝试。回答 udatet。忘记设置名称self.add_widget(Init(name="init"))
    • 没有出现错误,但屏幕没有切换。 self.current 从“init”变为“menu”,但 GUI 保持不变。为什么我需要将名称传递给 Screen 构造函数?已经在kv文件中设置了......
    • @HenriqueGarcia 我刚刚在您的代码中看到了问题。查看更新的答案,尝试运行最后一个示例。
    • 感谢您的帮助!它正在工作。我刚刚发布了一个 anwser 来澄清一切。 :D
    【解决方案2】:

    在@EL3PHANTEN 和this 的大力帮助下,我修复了我的代码,我想我知道我的错误在哪里。

    我不能在 kv 文件中使用app.root.sm.current='whateverScreenName'。我无法解释原因,但我想这与 ScreenManagement 的启动时刻有关。正如我从一开始就认为的那样,python 部分非常简单。

    再次感谢您的帮助,@EL3PHANTEN :)

    结果如下:

    ScreenManager inside a BoxLayout to have a Toolbar

    这里是工作的固定 python 代码:

    import kivy
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
    from kivy.clock import Clock
    
    #just solving my weak GPU issue
    from kivy import Config
    Config.set('graphics', 'multisamples', '0')
    
    kivy.require('1.9.1')
    
    class ScreenManagement(ScreenManager):
        pass
    
    class Init(Screen):
        pass
    
    class Menu(Screen):
        pass
    
    
    class ClassAllScreen(BoxLayout):
        pass
    
    class ClassApp(App):
    
        def build(self):
            self.root = ClassAllScreen()
            return self.root
    
    if __name__ == '__main__':
        ClassApp().run()
    

    还有Class.kv:

    #: import NoTransition kivy.uix.screenmanager.NoTransition
    <Init>:
        name: 'init'
        BoxLayout:
            orientation:'vertical'
            padding:20
            spacing:10
            Button:
                text:'uppest'
            GridLayout:
                spacing:10
                cols:2
    
                Button:
                    text:'upper left'
                Button:
                    text:'upper right'
                Button:
                    text:'bottom left'
                Button:
                    text:'bottom right'
            Button:
                text:'bottomest: go to menu'
                on_press: root.manager.current = 'menu'
    
    <Menu>:
        name: 'menu'     
        BoxLayout:
            orientation:'vertical'
            padding:20
            spacing:10
            GridLayout:
                spacing:10
                cols:2
    
                Button:
                    text:'upper left'
                Button:
                    text:'upper right'
                Button:
                    text:'bottom left'
                Button:
                    text:'bottom right'
            Button:
                text:'bottomy'
            Button:
                text:'bottomest: go to init'
                on_press: root.manager.current = 'init'
    
    <ScreenManagement>:
        transition: NoTransition()
        Init:
        Menu:
    
    <ClassAllScreen>:
        orientation:'vertical'
        ScreenManagement:
        BoxLayout:
            size_hint_y: None
            height: 60
            spacing: 5
            padding: 5,5,0,5
    
            canvas:
                Color:
                    rgba: .1,.1,.1,1
                Rectangle:
                    pos: self.pos
                    size: self.size
            Button:
                text:'1'
                size_hint_x: None
                width: 60
            Button:
                text:'2'
                size_hint_x: None
                width: 60
            Button:
                text:'3'
                size_hint_x: None
                width: 60
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多