Search code examples
python-3.xkivykivy-language

Kivy Builder.load_file() not working as expected


I am trying to run a small kivy app. When I use Builder.load_string() my app runs okay, when I use Builder.load_file() all I get is a blank screen. Here is my code

main.py - Using Builder.load_string()

from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.chip import MDChip
from kivy.uix.screenmanager import ScreenManager, Screen


Builder.load_string("""
<MenuScreen>:
    BoxLayout:
        Button:
            text: 'Goto settings'
            on_press:
                root.manager.transition.direction = 'left'
                root.manager.current = 'settings'
        Button:
            text: 'Quit'

<SettingsScreen>:
    BoxLayout:
        Button:
            text: 'My settings button'
        Button:
            text: 'Back to menu'
            on_press:
                root.manager.transition.direction = 'right'
                root.manager.current = 'menu'
""")


class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass


sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))


class MyWidget(MDChip):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class MainApp(MDApp):
    def __init__(self, **kwargs):
        self.title = "My Material Application"
        super().__init__(**kwargs)

    def build(self):
        return sm


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

Here is the same code with Builder.load_file()

main.py

from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.chip import MDChip
from kivy.uix.screenmanager import ScreenManager, Screen


class MenuScreen(Screen):
    pass


class SettingsScreen(Screen):
    pass


sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))


class MyWidget(MDChip):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class MainApp(MDApp):
    def __init__(self, **kwargs):
        self.title = "My Material Application"
        super().__init__(**kwargs)

    def build(self):
        self.root = Builder.load_file('main.kv')
        return sm


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

main.kv

<MenuScreen>:
    BoxLayout:
        Button:
            text: 'Goto settings'
            on_press:
                root.manager.transition.direction = 'left'
                root.manager.current = 'settings'
        Button:
            text: 'Quit'

<SettingsScreen>:
    BoxLayout:
        Button:
            text: 'My settings button'
        Button:
            text: 'Back to menu'
            on_press:
                root.manager.transition.direction = 'right'
                root.manager.current = 'menu'

All I get when I run the code is a blank screen.

What am I doing wrong?


Solution

  • Apparently you have to include the following code in def build(self)

    sm = ScreenManager()
    sm.add_widget(MenuScreen(name='menu'))
    sm.add_widget(SettingsScreen(name='settings'))
    

    So final main.py file will be

    from kivy.lang import Builder
    from kivymd.app import MDApp
    from kivymd.uix.chip import MDChip
    from kivy.uix.screenmanager import ScreenManager, Screen
    
    
    class MenuScreen(Screen):
        pass
    
    
    class SettingsScreen(Screen):
        pass
    
    
    class MyWidget(MDChip):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
    
    
    class MainApp(MDApp):
        def __init__(self, **kwargs):
            self.title = "My Material Application"
            super().__init__(**kwargs)
    
        def build(self):
            self.root = Builder.load_file('main.kv')
            sm = ScreenManager()
            sm.add_widget(MenuScreen(name='menu'))
            sm.add_widget(SettingsScreen(name='settings'))
            return sm
    
    
    if __name__ == "__main__":
        MainApp().run()