Search code examples
pythonbuttonkivy

Kivy On pressing a Button, a New Button is created which takes to Second Screen


I have a code where there are two Screens: "Main" & "Second", when you press a button in the Main Screen a new button is created in the same screen. I need the new button created to take me to the Second Screen. Please Help as I need it for a bigger project soon.

Normal Code:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import Screen,ScreenManager

class Main(Screen):
   pass
class Second(Screen):
   pass
class Manager(ScreenManager):
   pass
kv=Builder.load_file("test1.kv")
movie=Manager()
movie.add_widget(Main(name="main"))
movie.add_widget(Second(name="second"))

class Movie(App):
   def build(self):
       return movie

Movie().run()

Kv Code:

#: import Button kivy.uix.button.Button
<Main>:
    name: "main"
    GridLayout:
        id: GL
        cols: 1
        size_hint: (.5,.5)
        pos_hint: {"center_x":.5,"center_y":.5}
        Button:
            text: "Press Me"
            on_press:
                Btn=Button(text="Second",size_hint=(.5,.5),pos_hint= {"center_x":.5,"center_y":.5})
                GL.add_widget(Btn)
                #Btn.bind(on_press= ????)

<Second>:
    name: "second"
    Button:
        text: "Go Back!"
        size_hint: (.5,.5)
        pos_hint: {"center_x":.5,"center_y":.5}
        on_press:
            app.root.current="main"

Solution

  • The simplest way is to just define a method in the Main class that does the Screen change:

    class Main(Screen):
        def switch(self, button_instance):
           self.manager.current = 'second'
    

    Then reference that method in the kv:

        Button:
            text: "Press Me"
            on_press:
                Btn=Button(text="Second",size_hint=(.5,.5),pos_hint= {"center_x":.5,"center_y":.5}, on_press=root.switch)
                GL.add_widget(Btn)
    

    A more complex approach that doesn't require any additional methods works by using the python setattr() method to set the current Screen of the ScreenManager:

        Button:
            text: "Press Me"
            on_press:
                Btn=Button(text="Second",size_hint=(.5,.5),pos_hint= {"center_x":.5,"center_y":.5})
                Btn.bind(on_press=lambda ins: partial(setattr, root.manager, 'current', 'second')())
                GL.add_widget(Btn)
    

    The lambda is required to avoid passing the Button instance to the setattr() method. Also, an import is required for partial in the kv:

    #: import partial functools.partial