【问题标题】:Kivy - Kv - ScreenManager - changing the current screenKivy - Kv - ScreenManager - 改变当前屏幕
【发布时间】:2018-05-25 20:18:50
【问题描述】:

我正在尝试在kivy(kv)中做一个非常简单的例子如下:

#:import Toolbar kivymd.toolbar.Toolbar

BoxLayout:
    orientation: 'vertical'
    Toolbar:
        id: toolbar
        title: 'My Toolbar'
        md_bg_color: app.theme_cls.primary_color
        background_palette: 'Primary'
        background_hue: '500'
        left_action_items: [['arrow-left', app.root.ids.scr_mngr.current = 'screen1' ]]
        right_action_items: [['arrow-right', app.root.ids.scr_mngr.current = 'screen2' ]]
    ScreenManager:
        id: scr_mngr
        Screen:
            name: 'screen1'
            Toolbar:
                title: "Screen 1"
        Screen:
            name: 'screen2'
            Toolbar:
                title: "Screen 2"

这将失败,因为 left_action_items 和 right_action_items 都需要一个对列表:[name_of_icon, expression]。另一方面,当您处理按钮时,该语句将是合法的,例如,如果我们执行以下操作:

on_release:
    app.root.ids.scr_mngr.current = 'screen1'

另一方面,left_action_item 的正确方法是:

left_action_items: [['arrow-left', lambda x: app.root.ids.scr_mngr.current = 'screen1' ]]

但是这是不合法的,因为你不能在 python 下的 lambda 中执行这样的赋值。

left_action_items 改变屏幕的正确方法是什么?

【问题讨论】:

    标签: python kivy screen


    【解决方案1】:

    这是我发现点击 MDToolbar 图标更改屏幕的最简单方法:

    ma​​in.py

    from kivymd.app import MDApp
    from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
    from kivy.lang import Builder
    
    Builder.load_file("telas.kv")
    
    
    class Tela1(Screen):
        pass
    
    
    class Tela2(Screen):
        pass
    
    
    class MainApp(MDApp):
        def build(self):
            self.sm = ScreenManager(transition=NoTransition())
            self.sm.add_widget(Tela1(name="tela1"))
            self.sm.add_widget(Tela2(name="tela2"))
            return self.sm
    
        def change_screen(self, tela):
            self.sm.current = tela
    
    if __name__ == "__main__":
        MainApp().run()
    

    telas.kv

    <Tela1>:
        BoxLayout:
            orientation: "vertical"
            MDToolbar:
                title: "My App"
            MDRoundFlatButton:
                text: "Go to Tela 2"
                on_release: app.root.current = "tela2"
            MDLabel:
                text: "Tela 1"
    
    <Tela2>:
        BoxLayout:
            orientation: "vertical"
            MDToolbar:
                title: "Tela 2"
                left_action_items: [["arrow-left",  lambda x: app.change_screen("tela1")]]
            MDLabel:
                text: "Tela 2"
    

    【讨论】:

      【解决方案2】:

      你可以把你的根类变成一个 python 类,并在那里有一个 change_screen 方法。还将您的屏幕管理器设置为根类中的 ObjectProperty。
      然后在 kv 中使用 partial 以便能够将参数传递给方法。
      试试这样:

      from kivy.app import App
      from kivy.lang import Builder
      from kivy.properties import ObjectProperty
      from kivy.uix.boxlayout import BoxLayout
      from kivymd.theming import ThemeManager
      
      class MyLayout(BoxLayout):
      
          scr_mngr = ObjectProperty(None)
      
          def change_screen(self, screen, *args):
              self.scr_mngr.current = screen
      
      
      KV = """
      #:import Toolbar kivymd.toolbar.Toolbar
      #:import partial functools.partial
      
      MyLayout:
          scr_mngr: scr_mngr
          orientation: 'vertical'
          Toolbar:
              id: toolbar
              title: 'My Toolbar'
              left_action_items: [['arrow-left', partial(root.change_screen, 'screen1') ]]
              right_action_items: [['arrow-right', partial(root.change_screen, 'screen2') ]]
          ScreenManager:
              id: scr_mngr
              Screen:
                  name: 'screen1'
                  Toolbar:
                      title: "Screen 1"
              Screen:
                  name: 'screen2'
                  Toolbar:
                      title: "Screen 2"
      """
      
      
      class MyApp(App):
          theme_cls = ThemeManager()
      
          def build(self):
              return Builder.load_string(KV)
      
      
      MyApp().run()
      

      【讨论】:

      • 它有效。遗憾的是,ScreenManager 没有提供执行以下操作的可能性: set_screen('screen1')
      【解决方案3】:

      有多种选择,你可以做

      left_action_items: [('arrow-left', (app.root.ids.scr_mngr, 'current', 'screen1'))]
      

      然后再做:

      for icon, expr in self.left_action_items:
          setattr(*expr)
      

      如果你真的想要一个可执行的表达式,你可以这样做:

      left_action_items: [('arrow-left', lambda: setattr(app.root.ids.scr_mngr, 'current' 'screen1'))]
      

      【讨论】:

        【解决方案4】:

        还有一种方法。我使用的:

        left_action_items: [['arrow-left', lambda x: root.manager.change_screen("main_screen")]]

        屏幕管理器内部函数change_screen()的实现:

        def change_screen(self, screen):
            # the same as in .kv: app.root.current = screen
            self.current = screen
        

        【讨论】:

          猜你喜欢
          • 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
          相关资源
          最近更新 更多