Kivy的完整代码示例以KV语言编写的工作屏幕管理器参考

时间:2017-09-10 19:30:18

标签: user-interface kivy kivy-language

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

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

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

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

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

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

    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()
    

6 个答案:

答案 0 :(得分:3)

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

问题:1

将尽可能多地设置屏幕管理器的kv语言代码。即。可以通过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()

步骤2

在内联或单独的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"

输出

enter image description here

答案 1 :(得分:1)

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

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

  3. 这里是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个文件:

    <强> 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):
        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"
    

    我希望代码可以帮到你。

答案 2 :(得分:1)

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'

答案 3 :(得分:0)

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

但是我仍然想知道允许我将屏幕1上的文字更改为&#34;嗨我是第五屏幕的代码&#34;之前它在第二次显示在下面代码的第55行。这将有助于我了解如何更好地导航绑定以更新各个屏幕上的元素。

对此有任何帮助(使用完整的代码)将不胜感激。更新了下面的工作代码; .... brad ....

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()

答案 4 :(得分:0)

您只需在第55行添加此行。

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

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

所以这是完整的代码:

<强> 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 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()

我希望代码可以帮到你。

答案 5 :(得分:0)

为了保持每个帖子的简单和完整的工作代码的信条,我根据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()