pythonpython-3.xkivyscreenkivymd

Kivy/md - How to change Screens with ScreenManager, can I do it this way...?


I've got this simple code to change screens. I'm just wondering what the correct variable to change in callback() is to invoke a screen change. I've seen this done other ways, but wanted to make sure I have a static MDToolbar so when the screen changes, the toolbar does not move. The code below does does not change screen in callback()in this .py code:

from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivymd.app import MDApp
from kivy.loader import Loader
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.label import MDLabel
from kivymd.uix.floatlayout import MDFloatLayout

class TCalc(MDApp):

    def callback(self,obj):
    
        self.root.current = "tipscreen2"


    def build(self):
        return Builder.load_file('dip.kv')

TCalc().run()

dip.kv:

MDNavigationLayout:
    orientation: 'vertical'

    MDToolbar:
        id: toolbar
        right_action_items: [["cog", lambda x: app.callback(x)]]

    ScreenManager:
        id: screen_manager

        Screen:
            name: "tipscreen1"
            MDFloatLayout:
                MDLabel:
                    text: "Screen 1"

        Screen:
            name: "tipscreen2"
            MDFloatLayout:
                MDLabel:
                    text: "Screen 2"

    MDNavigationDrawer:
        id: nav_drawer
        MDNavigationDrawerMenu:

Solution

  • The code below does does not change screen in callback()in...

    That's because in method callback you did self.root.current. This is supposed to be applicable if your self.root is a ScreenManager instance which is indeed not the case here.

    Now, by doing lambda x: app.callback(x) you are actually passing the instance itself (here, MDActionTopAppBarButton). So if you want to pass some var. through the callback method to change screens, one of the different ways could be simply pass the ScreenManager object (here a weak reference actually). Or, you can just access the ScreenManager by ids (again a weak reference) directly from python. Both way the solution could be something like this,

    In kvlang,

            right_action_items: [["cog", lambda x: app.callback(x)]]
    # or,       right_action_items: [["cog", app.callback]]
    

    In python,

        def callback(self,sm):
    # or,   def callback(self, *args):
    
            sm.current = "tipscreen2"
    # or,       self.root.ids.screen_manager.current = "tipscreen2"