0

I am a beginner to Kivy (though not to Python), and I am struggling to get the ids from a kv string into my main code. I have the following, but the 'print' statement tells me that there are no IDs. The application itself runs with no errors.

import kivy
kivy.require('2.1.0')

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.image import Image

kvString = """
MainScreen:
  id: maincontainer
  cols: 1
  thumbnails: thumbnails.__self__
  GridLayout:
    id: thumbnails
    cols: 3
    rows: 3
    Image:
      source: "test.png"
"""

class MainScreen(GridLayout):
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        # This prints 0
        print("Ids: {}".format(len(self.ids.items())))

class ExampleApp(App):
    def build(self):
        root = Builder.load_string(kvString)
        return root
        
if __name__ == "__main__":
    ExampleApp().run()
  • 2
    The `ids` will be empty until the `kv` rules are applied, and that happens after `__init__()` is run. So, you just need to call your `print` later. – John Anderson Mar 27 '22 at 15:18
  • 1
    [How can I execute a method after kivy has loaded all widgets from a kv file? - Stack Overflow](https://stackoverflow.com/questions/47237079/how-can-i-execute-a-method-after-kivy-has-loaded-all-widgets-from-a-kv-file) – furas Mar 27 '22 at 15:59

1 Answers1

1

When I ran your code, I got a critical warning that there are no screens, and therefore the app will terminate. As soon as I switched MainScreen to a screen, it worked out perfectly. Here is the code:

.py

import kivy
kivy.require('2.1.0')

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.image import Image

sm = ScreenManager()

#I removed some unnecessary code such as the cols, thumbnail, etc.
kvString = """
<MainScreen>
  GridLayout:
    id: thumbnails
    cols: 3
    rows: 3
    Image:
      source: "test.png"
"""
#NEEDS TO INHERIT SCREEN
class MainScreen(Screen):
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        # This now prints 1
        print(f'There are {len(self.ids.items())} id(s)')

class ExampleApp(App):
    def build(self):
        root = Builder.load_string(kvString)
        #Adds the screen
        sm.add_widget(MainScreen(name='screen'))
        return sm

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