Kivy: Changing screens in screen manager with an on_press event

后端 未结 3 1032
旧时难觅i
旧时难觅i 2020-12-10 14:55

I would like to know how to change screens using an on_press event binded to a button, without using a KV file/KV language.

I have read through the Kivy documentatio

相关标签:
3条回答
  • 2020-12-10 15:29

    A working example with two screens, no kv file everything done in Python:

    import kivy
    kivy.require('1.8.0')
    
    from kivy.app import App
    from kivy.uix.screenmanager import Screen, ScreenManager 
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.label import Label
    from kivy.uix.button import Button
    from kivy.properties import ObjectProperty
    
    class ScreenOne(Screen):
    
        def __init__ (self,**kwargs):
            super (ScreenOne, self).__init__(**kwargs)
    
            my_box1 = BoxLayout(orientation='vertical')
            my_label1 = Label(text="BlaBlaBla on screen 1", font_size='24dp')
            my_button1 = Button(text="Go to screen 2",size_hint_y=None, size_y=100)
            my_button1.bind(on_press=self.changer)
            my_box1.add_widget(my_label1)
            my_box1.add_widget(my_button1)
            self.add_widget(my_box1)
    
        def changer(self,*args):
            self.manager.current = 'screen2'
    
    class ScreenTwo(Screen):
    
        def __init__(self,**kwargs):
            super (ScreenTwo,self).__init__(**kwargs)
    
            my_box1 = BoxLayout(orientation='vertical')
            my_label1 = Label(text="BlaBlaBla on screen 2",font_size='24dp')
            my_button1 = Button(text="Go to screen 1",size_hint_y=None, size_y=100)
            my_button1.bind(on_press=self.changer)
            my_box1.add_widget(my_label1)
            my_box1.add_widget(my_button1)
            self.add_widget(my_box1)
    
        def changer(self,*args):
            self.manager.current = 'screen1'
    
    class TestApp(App):
    
            def build(self):
                my_screenmanager = ScreenManager()
                screen1 = ScreenOne(name='screen1')
                screen2 = ScreenTwo(name='screen2')
                my_screenmanager.add_widget(screen1)
                my_screenmanager.add_widget(screen2)
                return my_screenmanager
    
    if __name__ == '__main__':
        TestApp().run()
    
    0 讨论(0)
  • 2020-12-10 15:40

    Another solution, was to use the setter method of EventDispatcher, to get a reference to the setter function for screen_manager.current

    button.bind(on_press=partial(sm.setter('current'), (sm, 'whatever'))
    

    of course, it's not very sexy, that's why kv is often a cleaner solution to these things, but it should work.

    ps: in case you don't know about it, partial comes from the functools module, and it's often useful to build these kind of callbacks with a preloaded parameter.

    0 讨论(0)
  • 2020-12-10 15:51

    One simple way to accomplish this is to define your own button subclass:

    class ScreenButton(Button):
        screenmanager = ObjectProperty()
        def on_press(self, *args):
            super(ScreenButton, self).on_press(*args)
            self.screenmanager.current = 'whatever'
    

    The on_press method is automatically called when the button is pressed, so the screenmanager's current property will be changed.

    Then you can have code something like:

    sm = ScreenManager()
    
    sc1 = Screen(name='firstscreen')
    sc1.add_widget(ScreenButton(screenmanager=sm))
    
    sc2 = Screen(name='whatever')
    sc2.add_widget(Label(text='another screen'))
    
    sm.add_widget(sc1)
    sm.add_widget(sc2)
    

    Clicking the button should switch the screens as required.

    Another way (which is probably how kv language actually does it) would be to manually use the bind method.

    def switching_function(*args):
        some_screen_manager.current = 'whatever'
    
    some_button.bind(on_press=switching_function)
    

    This would mean that switching_function is called whenever some_button is pressed. Of course there is a lot of flexibility here regarding how and when you define the function, so (for instance) you could do something more general like pass the screenmanager as the first argument to the function.

    I didn't test this code and it isn't a complete app, but hopefully the meaning is clear. Either method should work fine, you can choose the way that seems most sensible. I might construct a more complete example later.

    0 讨论(0)
提交回复
热议问题