【问题标题】:A Complete Code Example Of Kivy A Working Screen Manager Reference Written In KV LanguageKivy 的完整代码示例 用 KV 语言编写的工作屏幕管理器参考
【发布时间】:2017-09-10 19:30:17
【问题描述】:

我一直在尝试通过使用Kivy Screen manager reference in kv language 中的信息从Accessing id/widget of different class from a kivy file (.kv) using Kivy's clock? 建立我的kv 语言技能。不幸的是,后一篇文章不包含完整的工作代码示例,因此我无法理解如何在多屏幕 Kivy 应用程序的特定屏幕上更改文本元素。

在搜索了一天的大部分时间后,我找不到任何关于如何用 kv 语言构建多屏应用程序的简单具体工作示例,所以我在这里。我似乎无法设置对各个屏幕的正确引用,因此我可以更改它们。

在下面的简单示例代码中,我构建了一个在四个屏幕之间自动切换的四屏应用程序。我想从这个问题中学到两点;

  1. 尽可能多地设置屏幕管理器的 kv 语言代码。 IE。 kv 语言可以减少或消除第 43 到 47 行吗?

  2. 实际的 python 代码(我相信它会在应用程序的第 56 行)在第二次显示之前将第一个屏幕上的文本更改为“嗨,我是第五个屏幕”。

代码如下。提前致谢。 ....布拉德....

import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_string("""
<FirstScreen>:
    name: '_first_screen_'
    Label:
        id: first_screen
        text: "Hi I'm The First Screen"
<SecondScreen>:
    name: '_second_screen_'
    Label:
        id: second_screen
        text: "Hi I'm The Second Screen"
<ThirdScreen>:
    name: '_third_screen_'
    Label:
        id: third_screen
        text: "Hi I'm The Third Screen"
<FourthScreen>:
    name: '_fourth_screen_'
    Label:
        id: fourth_screen
        text: "Hi I'm The Fourth Screen"
""")

class FirstScreen(Screen):
    pass

class SecondScreen(Screen):
    pass

class ThirdScreen(Screen):
    pass

class FourthScreen(Screen):
    pass

sm = ScreenManager()
sm.add_widget(FirstScreen())
sm.add_widget(SecondScreen())
sm.add_widget(ThirdScreen())
sm.add_widget(FourthScreen())

class SwitchingScreenApp(App):

    def build(self):
        Clock.schedule_once(self.screen_switch_one, 2)
        Clock.schedule_once(self.screen_switch_two, 4)
        Clock.schedule_once(self.screen_switch_three, 6)
        Clock.schedule_once(self.screen_switch_four, 8)
        # Want to place the code here that changes the first_screen text to "Hi I'm The Fifth Screen"
        Clock.schedule_once(self.screen_switch_one, 10)
        return sm

    def screen_switch_one(a,b):
        sm.current = '_first_screen_'
    def screen_switch_two(a,b):
        sm.current = '_second_screen_'
    def screen_switch_three(a,b):
        sm.current = '_third_screen_'
    def screen_switch_four(a,b):
        sm.current = '_fourth_screen_'

SwitchingScreenApp().run()

【问题讨论】:

    标签: user-interface kivy kivy-language


    【解决方案1】:

    首先,我建议将您的代码拆分为 Python 和 kv 文件,因为随着程序的增长,维护 UI/小部件和 Python 代码会更容易。详情请参考示例(app_with_kv.py、switchingscreen.kv、输出)。

    问题:1

    尽可能多地设置屏幕管理器的 kv 语言代码。 IE。 kv 语言可以减少或消除第 43 到 47 行吗?

    sm = ScreenManager()
    sm.add_widget(FirstScreen())
    sm.add_widget(SecondScreen())
    sm.add_widget(ThirdScreen())
    sm.add_widget(FourthScreen())
    

    回答

    步骤 1

    将 MyScreenManager 类添加到您的 Python 代码中。

    class MyScreenManager(ScreenManager):
        pass
    ...
        def build(self):
            sm = MyScreenManager()
    

    第二步

    内联或在单独的 kv 文件中添加以下 kv 规则。这相当于使用语句 sm.add_widget() 四次。

    <MyScreenManager>:
        FirstScreen:
        SecondScreen:
        ThirdScreen:
        FourthScreen:
    

    问题:2

    实际的 python 代码(我相信它会在应用程序的第 56 行)在第二次显示之前将第一个屏幕上的文本更改为“嗨,我是第五个屏幕”。

    回答

    除了第一个切换屏幕方法 screen_switch_one() 之外,您必须将以下代码放置在 3 个切换屏幕方法中的任何一个中

    self.ids.first_screen.ids.first_screen_label.text = "Hi I'm The Fifth Screen"
    

    示例

    app_with_kv.py

    ​​>
    from kivy.app import App
    from kivy.clock import Clock
    from kivy.uix.screenmanager import ScreenManager, Screen
    
    
    class FirstScreen(Screen):
        pass
    
    
    class SecondScreen(Screen):
        pass
    
    
    class ThirdScreen(Screen):
        pass
    
    
    class FourthScreen(Screen):
        pass
    
    
    class MyScreenManager(ScreenManager):
    
        def __init__(self, **kwargs):
            super(MyScreenManager, self).__init__(**kwargs)
            Clock.schedule_once(self.screen_switch_one, 2)
    
        def screen_switch_one(self, dt):
            self.current = '_first_screen_'
            Clock.schedule_once(self.screen_switch_two, 2)
    
        def screen_switch_two(self, dt):
            self.current = '_second_screen_'
            self.ids.first_screen.ids.first_screen_label.text = "Hi I'm The Fifth Screen"
            Clock.schedule_once(self.screen_switch_three, 2)
    
        def screen_switch_three(self, dt):
            self.current = '_third_screen_'
            Clock.schedule_once(self.screen_switch_four, 2)
    
        def screen_switch_four(self, dt):
            self.current = '_fourth_screen_'
            Clock.schedule_once(self.screen_switch_one, 2)
    
    
    class SwitchingScreenApp(App):
    
        def build(self):
            return MyScreenManager()
    
    
    if __name__ == "__main__":
        SwitchingScreenApp().run()
    

    switchingscreen.kv

    #:kivy 1.10.0
    
    <MyScreenManager>:
        FirstScreen:
            id: first_screen
        SecondScreen:
        ThirdScreen:
        FourthScreen:
    
    <FirstScreen>:
        name: '_first_screen_'
        Label:
            id: first_screen_label
            text: "Hi I'm The First Screen"
    
    <SecondScreen>:
        name: '_second_screen_'
        Label:
            id: second_screen_label
            text: "Hi I'm The Second Screen"
    
    <ThirdScreen>:
        name: '_third_screen_'
        Label:
            id: third_screen_label
            text: "Hi I'm The Third Screen"
    
    <FourthScreen>:
        name: '_fourth_screen_'
        Label:
            id: fourth_screen_label
            text: "Hi I'm The Fourth Screen"
    

    输出

    【讨论】:

      【解决方案2】:
      1. 是的,您可以通过创建 root_widget 并在 app 类的 build 方法中返回该根小部件并在 kv 文件中创建屏幕来消除该代码(我希望代码能更好地解释它)

      2. 要更改 kv 文件中标签的 python 文本,您应该使用 kivy properties 并使用 manager.get_screen('screenname').widget 命令访问另一个屏幕的小部件

      这里是 main.py 文件

          import kivy
          kivy.require('1.10.0')
          from kivy.app import App
          from kivy.lang import Builder
          from kivy.clock import Clock
          from kivy.uix.screenmanager import ScreenManager, Screen
          from kivy.properties import ObjectProperty
      
          class MenuScreen(Screen):
              pass
          class FirstScreen(Screen):
              #create property in python
              first_screen = ObjectProperty()
              def starttimer(self):
                  self.timer = Clock.schedule_once(self.screen_switch_two, 2)
              def screen_switch_two(self, dt):
                  self.manager.current = 'second_screen'
          class SecondScreen(Screen):
              def starttimer(self):
                  self.timer = Clock.schedule_once(self.screen_switch_three, 4)
              def screen_switch_three(self, dt):
                  self.manager.current = 'third_screen'
          class ThirdScreen(Screen):
              def starttimer(self):
                  self.timer = Clock.schedule_once(self.screen_switch_four, 6)
              def screen_switch_four(self, dt):
                  self.manager.current = 'fourth_screen'
          class FourthScreen(Screen):
              def starttimer(self):
                  self.timer = Clock.schedule_once(self.screen_switch_one, 8)
              def screen_switch_one(self, dt):
                  #change the text of the label in the first_screen
                  self.manager.get_screen('first_screen').first_screen.text = "Hi I'm The Fifth Screen"
                  self.manager.current = 'first_screen'
      
          root_widget = Builder.load_string("""
          #here the screens will be created
          ScreenManager:
              MenuScreen:
              FirstScreen:
              SecondScreen:
              ThirdScreen:
              FourthScreen:
          #the menu screen is created that the method on_enter in the first screen is called and the loop through the screens can begin
          <MenuScreen>:
              Button:
                  text: 'start'
                  on_press: app.root.current = 'first_screen'
          <FirstScreen>:
              #link/bind the property in the kv file 
              first_screen: first_screen
              name: 'first_screen'
              on_enter: root.starttimer()
              Label:
                  id: first_screen
                  text: "Hi I'm The First Screen"
          <SecondScreen>:
              name: 'second_screen'
              on_enter: root.starttimer()
              Label:
                  id: second_screen
                  text: "Hi I'm The Second Screen"
          <ThirdScreen>:
              name: 'third_screen'
              on_enter: root.starttimer()
              Label:
                  id: third_screen
                  text: "Hi I'm The Third Screen"
          <FourthScreen>:
              name: 'fourth_screen'
              on_enter: root.starttimer()
              Label:
                  id: fourth_screen
                  text: "Hi I'm The Fourth Screen"
          """)
      
          class SwitchingScreenApp(App):
      
              def build(self):
                  return root_widget
      
          if __name__ == '__main__':
              SwitchingScreenApp().run()
      

      为了更好地构建代码,我将 kv 和 python 代码分开在 2 个文件中:

      ma​​in.py

      import kivy
      kivy.require('1.10.0')
      from kivy.app import App
      from kivy.lang import Builder
      from kivy.clock import Clock
      from kivy.uix.screenmanager import ScreenManager, Screen
      from kivy.properties import ObjectProperty
      
      class MenuScreen(Screen):
          pass
      class FirstScreen(Screen):
          first_screen = ObjectProperty()
          def starttimer(self):
              self.timer = Clock.schedule_once(self.screen_switch_two, 2)
          def screen_switch_two(self, dt):
              self.manager.current = 'second_screen'
      class SecondScreen(Screen):
          def starttimer(self):
              self.timer = Clock.schedule_once(self.screen_switch_three, 4)
          def screen_switch_three(self, dt):
              self.manager.current = 'third_screen'
      class ThirdScreen(Screen):
          def starttimer(self):
              self.timer = Clock.schedule_once(self.screen_switch_four, 6)
          def screen_switch_four(self, dt):
              self.manager.current = 'fourth_screen'
      class FourthScreen(Screen):
          def starttimer(self):
              self.timer = Clock.schedule_once(self.screen_switch_one, 8)
          def screen_switch_one(self, dt):
              self.manager.get_screen('first_screen').first_screen.text = "Hi I'm The Fifth Screen"
              self.manager.current = 'first_screen'
      
      class SwitchingScreenApp(App):
      
          def build(self):
              return Builder.load_file('screen.kv')
      
      if __name__ == '__main__':
          SwitchingScreenApp().run()
      

      和 screen.kv 文件

      ScreenManager:
          MenuScreen:
          FirstScreen:
          SecondScreen:
          ThirdScreen:
          FourthScreen:
      <MenuScreen>:
          Button:
              text: 'start'
              on_press: app.root.current = 'first_screen'
      <FirstScreen>:
          first_screen: first_screen
          name: 'first_screen'
          on_enter: root.starttimer()
          Label:
              id: first_screen
              text: "Hi I'm The First Screen"
      <SecondScreen>:
          name: 'second_screen'
          on_enter: root.starttimer()
          Label:
              id: second_screen
              text: "Hi I'm The Second Screen"
      <ThirdScreen>:
          name: 'third_screen'
          on_enter: root.starttimer()
          Label:
              id: third_screen
              text: "Hi I'm The Third Screen"
      <FourthScreen>:
          name: 'fourth_screen'
          on_enter: root.starttimer()
          Label:
              id: fourth_screen
              text: "Hi I'm The Fourth Screen"
      

      希望代码可以帮助到你。

      【讨论】:

      • 谢谢耀西。您已经很好地回答了关于 kv 语言的问题 1。 :)(请参阅我发布的代码。)回答问题 2 所采用的方法适用于本示例,但最终我将采用我在这里寻求的内容并将其构建到更大的应用程序中。我更喜欢在构建代码中(一个地方)在屏幕之间放置尽可能多的交互,这样代码变得更容易管理。也就是说,我想学习如何在每个屏幕上引用单个元素,以便更新它们。这就是为什么在重新发布的代码中,我仍然想在构建期间更改第一个屏幕上的文本。
      【解决方案3】:

      from kivy.app import App
      from kivy.lang import Builder
      from kivy.uix.screenmanager import ScreenManager, Screen
      from kivy.uix.boxlayout import BoxLayout
      
      class screenone(Screen):
          pass
      class screentwo(Screen):
          pass
      
      
      
      class mainApp(App):
          def build(self):
              screen_manager=ScreenManager()
              screen_manager.add_widget(screenone(name='screen_one'))
              screen_manager.add_widget(screentwo(name='screen_two'))
              return screen_manager
      
      
      if __name__=='__main__':
          mainApp().run()
      
      
      
      <main.kv>
      
      <screenone>:
          BoxLayout:
              Button:
                  text:"go to next screen"
                  on_press:root.manager.current='screen_two'
      <screentwo>:
          BoxLayout:
              Button:
                  text:"go back to first screen"
                  on_press:root.manager.current='screen_one'
      

      【讨论】:

      • 请考虑编辑您的答案。不要在 cmets 中添加其他信息,而是在答案本身中添加。来自review
      【解决方案4】:

      就像我所有帖子中的情况一样,我喜欢发布完整的工作代码,以便立即有用。根据 YOSHI 的回答,我重新编写了他的 kv 语言代码,以便它尽可能多地设置屏幕管理器并遵循我的原始代码。这回答了问题 1。

      但是,我仍然想知道在下面代码的第 55 行第二次显示之前,我可以将屏幕 1 上的文本更改为“Hi I'm The Fifth Screen”的代码。这将帮助我了解如何更好地导航绑定以更新各个屏幕上的元素。

      非常感谢您对此提供任何帮助(使用完整的工作代码)。更新了下面的工作代码;....布拉德....

      import kivy
      kivy.require('1.10.0')
      from kivy.app import App
      from kivy.lang import Builder
      from kivy.clock import Clock
      from kivy.uix.screenmanager import Screen
      
      class FirstScreen(Screen):
          pass
      
      class SecondScreen(Screen):
          pass
      
      class ThirdScreen(Screen):
          pass
      
      class FourthScreen(Screen):
          pass
      
      root_widget = Builder.load_string("""
      ScreenManager:
          FirstScreen:
          SecondScreen:
          ThirdScreen:
          FourthScreen:
      <FirstScreen>:
          first_screen: first_screen
          name: '_first_screen_'
          Label:
              id: first_screen
              text: "Hi I'm The First Screen"
      <SecondScreen>:
          name: '_second_screen_'
          Label:
              id: second_screen
              text: "Hi I'm The Second Screen"
      <ThirdScreen>:
          name: '_third_screen_'
          Label:
              id: third_screen
              text: "Hi I'm The Third Screen"
      <FourthScreen>:
          name: '_fourth_screen_'
          Label:
              id: fourth_screen
              text: "Hi I'm The Fourth Screen"
      """)
      
      class SwitchingScreenApp(App):
          def build(self):
              Clock.schedule_once(self.screen_switch_one, 2)
              Clock.schedule_once(self.screen_switch_two, 4)
              Clock.schedule_once(self.screen_switch_three, 6)
              Clock.schedule_once(self.screen_switch_four, 8)
              # Want to place the code here that changes the first_screen text to "Hi I'm The Fifth Screen"
              Clock.schedule_once(self.screen_switch_one, 10)
              return root_widget
      
          def screen_switch_one(a, b):
              root_widget.current = '_first_screen_'
      
          def screen_switch_two(a, b):
              root_widget.current = '_second_screen_'
      
          def screen_switch_three(a, b):
              root_widget.current = '_third_screen_'
      
          def screen_switch_four(a, b):
              root_widget.current = '_fourth_screen_'
      
      if __name__ == '__main__':
          SwitchingScreenApp().run()
      

      【讨论】:

        【解决方案5】:

        您只需在第 55 行添加这一行。

        root_widget.get_screen('_first_screen_').first_screen.text = "Hi I'm The Fifth Screen"
        

        首先你必须绑定标签(更多信息here)然后你可以使用上面的代码访问标签文本

        所以这里是完整的代码:

        ma​​in.py

        import kivy
        kivy.require('1.10.0')
        from kivy.app import App
        from kivy.lang import Builder
        from kivy.clock import Clock
        from kivy.uix.screenmanager import Screen
        
        class FirstScreen(Screen):
            pass
        
        class SecondScreen(Screen):
            pass
        
        class ThirdScreen(Screen):
            pass
        
        class FourthScreen(Screen):
            pass
        
        root_widget = Builder.load_string("""
        ScreenManager:
            FirstScreen:
            SecondScreen:
            ThirdScreen:
            FourthScreen:
        <FirstScreen>:
            first_screen: first_screen
            name: '_first_screen_'
            Label:
                id: first_screen
                text: "Hi I'm The First Screen"
        <SecondScreen>:
            name: '_second_screen_'
            Label:
                id: second_screen
                text: "Hi I'm The Second Screen"
        <ThirdScreen>:
            name: '_third_screen_'
            Label:
                id: third_screen
                text: "Hi I'm The Third Screen"
        <FourthScreen>:
            name: '_fourth_screen_'
            Label:
                id: fourth_screen
                text: "Hi I'm The Fourth Screen"
        """)
        
        class SwitchingScreenApp(App):
            def build(self):
                Clock.schedule_once(self.screen_switch_one, 2)
                Clock.schedule_once(self.screen_switch_two, 4)
                Clock.schedule_once(self.screen_switch_three, 6)
                Clock.schedule_once(self.screen_switch_four, 8)
                root_widget.get_screen('_first_screen_').first_screen.text = "Hi I'm The Fifth Screen"
                Clock.schedule_once(self.screen_switch_one, 10)
                return root_widget
        
            def screen_switch_one(a, b):
                root_widget.current = '_first_screen_'
        
            def screen_switch_two(a, b):
                root_widget.current = '_second_screen_'
        
            def screen_switch_three(a, b):
                root_widget.current = '_third_screen_'
        
            def screen_switch_four(a, b):
                root_widget.current = '_fourth_screen_'
        
        if __name__ == '__main__':
            SwitchingScreenApp().run()
        

        希望代码可以帮助到你。

        【讨论】:

        • 您发布的完整代码需要更正。 :( 第 55 行文本需要一个事件调度程序才能运行。在我将发布的最终代码的情况下,我将使用 Kivy 的时钟。当作为时钟事件调度时,它工作得非常好。再次感谢您在这方面的时间....布拉德....
        • 你能编辑代码吗,因为对我来说代码工作正常
        • Yoshi - 当这个版本(上面)运行时,仔细看看屏幕。显示的第一个屏幕实际上显示“嗨,我是第五个屏幕”。这可能是因为第一个屏幕文本在实际时钟调用开始运行之前更新。请注意,在我发布 Kivy 时钟的最终版本中,文本是否会更改 9 秒作为事件,并且在 10 秒时屏幕会重新显示更改后的文本。
        【解决方案6】:

        为了在每个帖子中保持简单而完整的工作代码的信条,我已经根据 Yoshi 在他的第二个代码帖子中提供的信息完成了代码。因此,最初发布的问题的最终和工作代码如下;

        import kivy
        kivy.require('1.10.0')
        from kivy.app import App
        from kivy.lang import Builder
        from kivy.clock import Clock
        from kivy.uix.screenmanager import Screen
        
        class FirstScreen(Screen):
            pass
        
        class SecondScreen(Screen):
            pass
        
        class ThirdScreen(Screen):
            pass
        
        class FourthScreen(Screen):
            pass
        
        root_widget = Builder.load_string("""
        ScreenManager:
            FirstScreen:
            SecondScreen:
            ThirdScreen:
            FourthScreen:
        <FirstScreen>:
            first_screen: first_screen
            name: '_first_screen_'
            Label:
                id: first_screen
                text: "Hi I'm The First Screen"
        <SecondScreen>:
            name: '_second_screen_'
            Label:
                id: second_screen
                text: "Hi I'm The Second Screen"
        <ThirdScreen>:
            name: '_third_screen_'
            Label:
                id: third_screen
                text: "Hi I'm The Third Screen"
        <FourthScreen>:
            name: '_fourth_screen_'
            Label:
                id: fourth_screen
                text: "Hi I'm The Fourth Screen"
        """)
        
        class SwitchingScreenApp(App):
            def build(self):
                Clock.schedule_once(self.screen_switch_one, 2)
                Clock.schedule_once(self.screen_switch_two, 4)
                Clock.schedule_once(self.screen_switch_three, 6)
                Clock.schedule_once(self.screen_switch_four, 8)
                Clock.schedule_once(self.text_replace_screen_one, 9)
                Clock.schedule_once(self.screen_switch_one, 10)
                return root_widget
        
            def text_replace_screen_one(a,b):
                root_widget.get_screen('_first_screen_').first_screen.text = "Hi I'm The Fifth Screen"
        
            def screen_switch_one(a, b):
                root_widget.current = '_first_screen_'
        
            def screen_switch_two(a, b):
                root_widget.current = '_second_screen_'
        
            def screen_switch_three(a, b):
                root_widget.current = '_third_screen_'
        
            def screen_switch_four(a, b):
                root_widget.current = '_fourth_screen_'
        
        if __name__ == '__main__':
            SwitchingScreenApp().run() 
        

        【讨论】:

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