Search code examples
pythonobjectkivykivy-languagekivymd

Getting ids from the main.kv file KivyMD


This probably has a simple solution but i can't seen to figure it out. Take the follow code as reference

from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivymd.theming import ThemeManager
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivymd.uix.navigationdrawer import NavigationLayout, MDNavigationDrawer
from kivymd.uix.list import OneLineListItem, OneLineIconListItem
from kivymd.uix.list import MDList
from kivymd.uix.toolbar import MDToolbar

class HomeScreen(Screen):
    pass

class ContentDrawer(BoxLayout): 
    screen_manager = ObjectProperty() 
    nav_drawer = ObjectProperty()

class MainApp(MDApp):
    def __init__(self):
        self.GUI = Builder.load_file("main.kv")
        self.theme_cls = ThemeManager()

    def build(self):
        return self.GUI

if __name__ == "__main__":
    MainApp().run()


main.kv

<ContentDrawer>:
    ScrollView:
        MDList:
            OneLineIconListItem: 
                text: "Screen 1" 
                icon: 'basketball-hoop'
                on_press: 
                    root.nav_drawer.set_state("close") 
                    root.screen_manager.current = "add_buy_condition_screen"

            OneLineIconListItem: 
                text: "Screen 2" 
                icon: 'basketball'
                on_press: 
                    root.nav_drawer.set_state("close") 
                    root.screen_manager.current = "add_sell_condition_screen"

NavigationLayout: 
    MDNavigationDrawer: 
        id: nav_drawer
    
        ContentDrawer: 
            screen_manager: screen_manager 
            nav_drawer: nav_drawer

    ScreenManager:
        HomeScreen:
            name: "home_screen"
            id: home_screen
            BoxLayout:
                orientation:"vertical"
                MDToolbar:
                    pos_hint:{"top": 1}
                    elevation:10
                    title:"Lleno"
                    left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]

So I'm trying to create a tool bar, when i create it using the above code every works fine except that the MDNavigation drawer appears under the tool bar. I would like to create the box layout for the tool bar inside the Homescreen class, something like this.

class HomeScreen(Screen):
    
    def __init__(self, **kwargs):
        super(HomeScreen, self).__init__(**kwargs)
        print("My main app's ids: ", self.ids)
     
        self.nav_drawer = self.ids["nav_drawer"]

        self.header_box = BoxLayout(orientation="vertical")
        self.toolbar = MDToolbar(pos_hint={"top": 1}, elevation=10,
            title="Lleno", left_action_items= [["menu", lambda x: nav_drawer.set_state("open")]])

        self.header_box.add_widget(self.toolbar)   

        self.add_widget(self.header_box)

However I can't seem to get that self.nav_drawer id from my main.kv file, how can i get access to the id or what is another way to create the toolbar in such a way to when the MDNavigation drawer opens the toolbar goes underneath it. The print statement for self.ids returns an empty dict <class 'ObservableDict'>


Solution

  • The ids from a kv file are in the root of the rule that creates them, so the nav_drawer id is in the instance of NavigationLayout, not the HomeScreen. Also, the ids are not available in the __init__() method, since they haven't been created yet. You can delay the access of the ids by using Clock.schedule_once() or an on_kv_post() method.

    You can access the ids in your App using something like

    App.get_running_app().root.ids['nav_drawer']