Search code examples
pythonkivykivymd

Retrieving root ids gives empty dictionary


Description of Code: I have two ids for ScreenList objects (proof_list and menu_list). When I click on a list item (instance_item), I want their associated parent's id. The check_id function should accomplish this by invoking get_id(instance_item.parent) to print their parent's id which would be either proof_list or menu_list.

Problem: get_id doesn't retrieve self.root.ids full dictionary. I checked by printing the result, which gave an empty dictionary. Out of curiosity, I tried printing self.root.ids in my on_start method, and it gave a full dictionary of ids. I need to access self.root.ids in get_id, so it can check whether an instance is in that dictionary of ids and return its id if true.

Questions: I believe this is an initialization issue, but I don't know where to start in fixing this. So my questions are:

  1. Why does it give the full dictionary in the on_start method?
  2. How can my get_id method retrieve the full id dictionary like the on_start method?

I know my issue concerns initialization. However, I am still learning and am confused about what to do, so I'd appreciate the help.

Here is a very simplified code example.

from kivymd.app import MDApp
from kivymd.theming import ThemableBehavior
from kivy.lang import Builder
from kivymd.uix.list import MDList, OneLineListItem, TwoLineListItem, ThreeLineListItem, ThreeLineIconListItem, \
            OneLineIconListItem
from kivy.core.window import Window
from proof_nav import proof_helper
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty, StringProperty
        
class ScreenList(ThemableBehavior, MDList):
    screen_manager = ObjectProperty()

    def check_id(self, instance_item):
        e1 = ProofApp()
        parent_id = e1.get_id(instance_item.parent)
        print(parent_id)

class ProofApp(MDApp):

    def build(self):
        screen = Builder.load_string(proof_helper)
        return screen

    def on_start(self):
        print(self.root.ids)

    def get_id(self, instance_item):
        for id, widget in self.root.ids.items():
            if instance_item == widget:
                print(self.root.ids)
                return str(id)
        print(self.root.ids)
        return ""




ProofApp().run()

This is the string file I loaded:

proof_helper = """
            
Screen:
    MDNavigationLayout:
        ScreenManager:
            id: screen_manager
                                
            Screen:
                name: 'menu'
                BoxLayout:
                    orientation: 'vertical'
                    MDToolbar:
                        title: "Menu Screen"
                        elevation: 8
                    
                    ScrollView:
                        ScreenList:
                            id: menu_list
                            screen_manager:screen_manager
                            OneLineListItem:
                                text: "Some Item"
                                on_release: self.parent.check_id(self)
                        
            
            Screen:
                name: 'screen2'
                BoxLayout:
                    orientation: 'vertical'
                    MDToolbar:
                        title: "Proofs"
                        elevation: 8

                    ScrollView:
                        ScreenList:
                            id: proof_list
                            screen_manager:screen_manager
                            OneLineListItem:
                                text: "Another Item"
                                on_release: self.parent.check_id(self)

"""

Solution

  • The problem is that in your check_id() method, the code:

    e1 = ProofApp()
    

    is creating a new instance of ProofApp. The new instance of ProofApp has no relation to the instance that you are running. You must use the currently running instance of the App, which you can get by calling MDApp.get_running_app(). So, your check_id() method should be something like:

    def check_id(self, instance_item):
        # e1 = ProofApp()
        e1 = MDApp.get_running_app()
        parent_id = e1.get_id(instance_item.parent)
        print(parent_id)