Reputation: 339
My Main class returns a instance of ScreenManager. This ScreenManager has a widget with a Screen class, and I want this Screen class to use a widget which is a Layout that I defined earlier.
When I execute the code, it only show a black screen with no more information. It should show a Button instead.
This is my file minimum.py
:
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.app import App
class LayoutWithButton(BoxLayout):
def __init__(self, **kwargs):
super(LayoutWithButton, self).__init__(**kwargs)
class MainScreenApp(Screen):
def __init__(self, **kwargs):
super(MainScreenApp, self).__init__(**kwargs)
button_layout = LayoutWithButton()
self.add_widget(button_layout)
screen_manager = ScreenManager()
screen_manager.add_widget(MainScreenApp(name='main'))
class TestMainApp(App):
def build(self):
return screen_manager
if __name__ == '__main__':
TestMainApp().run()
And this is my file testmain.kv
:
<LayoutWithButton>:
Button:
text: 'hello'
Even so, if I replace the line self.add_widget(button_layout)
of the class MainScreenApp with the line self.add_widget(Button())
it works well.
What am I doing wrong?
Upvotes: 1
Views: 827
Reputation: 4513
The problem is that kv file is not loaded until TestMainApp
is initialized. As you instanciate MainScreenApp
before this, the rules defined within the kv have no effect.
A very simple solution is to move instanciation of MainScreenApp
to App
subclass:
class MainApp(App):
def build(self):
screen_manager = ScreenManager()
screen_manager.add_widget(MainScreenApp(name='main'))
return screen_manager
You can also force the kv load before instantiating:
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang.builder import Builder
from kivy.app import App
class LayoutWithButton(BoxLayout):
pass
class MainScreenApp(Screen):
def __init__(self, **kwargs):
super(MainScreenApp, self).__init__(**kwargs)
button_layout = LayoutWithButton()
self.add_widget(button_layout)
Builder.load_file("testmain.kv")
screen_manager = ScreenManager()
screen_manager.add_widget(MainScreenApp(name='main'))
class TestApp(App):
def build(self):
return screen_manager
if __name__ == '__main__':
TestApp().run()
Another option is do everything in your kv:
from kivy.uix.screenmanager import ScreenManager
from kivy.app import App
class RootWidget(ScreenManager):
pass
class MainTestApp(App):
def build(self):
return MainWindow()
if __name__ == '__main__':
MainTestApp().run()
maintest.kv:
<LayoutWithButton@BoxLayout>:
Button:
text: 'hello'
<MainScreenApp@Screen>:
LayoutWithButton:
<RootWidget>:
MainScreenApp:
name: "main"
Upvotes: 4
Reputation: 23
From testmain.kv you should remove that < and > from the class name. You only use it when you are styling it and will also be calling it many many times.
Example how your code should look like:
LayoutWithButton: Button: text: 'hello'
When to use < and >:
<LayoutWithButton>:
pos_hint: 0, .5
Button:
text: 'hello'
BoxLayout:
LayoutWithButton:
pos_hint: 0, .5
Good luck!
Upvotes: 1