Bryce
Bryce

Reputation: 207

Instantiation of Kivy Children Widgets between Python and Kivy Language

I am having issues getting Kivy to instantiate children Widgets. The issue here I believe is with how I am setting up the root widget. According to many examples I have seen including kivy's own documentation I should be able to instantiate children widgets to a root widget in the .kv file without using <> as such:

initApp.kv root_rule:

Root_Widget:
    Test_Screen:

<Test_Screen>:
    BoxLayout:
       *there is stuff here, leaving blank to keep this question shorter*

Python File: (Note that the add_widget() is commented out)

class Test_Screen(Screen):
    pass

class Root_Widget(ScreenManager):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # self.add_widget(Test_Screen())
    pass

class InitApp(App):
    def build(self):
        return Root_Widget()

if __name__ == '__main__':
    InitApp().run()

However, this only leads to a blank app. There are two ways to fix this:

  1. Uncomment the self.add_widget(Test_Screen()) line OR
  2. Add <> to around the Root_Widget in the .kv file so it would then be a class rule:

initApp.kv class_rule:

<Root_Widget>:
    Test_Screen:

<Test_Screen>:
    BoxLayout:
        *there is stuff here, leaving blank to keep this question shorter*

Question

My question is, what is the difference here? Nesting Test_Screen underneath Root_Widget in the .kv file should be the exact same as calling the add_widget() method correct? Is this true and if so how/why is it different when setting Root_Widget as a class rule VS. a root rule?

Are there unforeseen consequences to saying that Root_Widget is a class rule rather than a root rule? It seems to work just fine using this approach but I don't know if it will cause other trouble as the app becomes more complex.

Upvotes: 1

Views: 381

Answers (1)

ikolim
ikolim

Reputation: 16001

Blank Window/App

The blank window/app could be due to one of the following:

  • kv file name mismatch e.g. app class name, class InitApp(App): then kv filename should be init.kv. If you are not using Builder to load kv then the kv file name should be init.kv and not InitApp.kv
  • No root widget in the return statement
  • No root rule in the kv file

kv filename - By name convention

By name convention

Kivy looks for a Kv file with the same name as your App class in lowercase, minus “App” if it ends with ‘App’ e.g:

MyApp -> my.kv

Solution - Blank Window/App

Instantiate and add a Label widget under Test_Screen as follow:

<Test_Screen>:
    BoxLayout:
        Label:
            text: "kv file - Root Rule vs Class Rule"

Question 1

what is the difference here? Nesting Test_Screen underneath Root_Widget in the kv file should be the exact same as calling the add_widget() method correct?

Answer 1

Yes it is the same.

Kivy App - without kv file

  • Use add_widget(Test_Screen()) function to instantiate add children widgets under the parent.

Kivy App - with kv file

  • Instantiate and add children widgets under the parent using Test_Screen:
  • Can use both e.g. using add_widget(Button()) to dynamically instantiate and add children widgets to a ScrollView.

Question 2

Is this true and if so how/why is it different when setting Root_Widget as a class rule VS. a root rule?

Answer 2

When the kv file is parsed, the root rule will be set as the root attribute of the App instance. Whereas a class rule, defines how any instance of that class will be graphically represented.

Question 3

Are there unforeseen consequences to saying that Root_Widget is a class rule rather than a root rule?

Answer 3

I don't believe there is any unforeseen consequences. The only thing to note when using root rule or class rule in kv file are as follow.

kv file - Using root rule

If in your kv file, you have a root rule defined i.e. Root_Widget: then in your Python code, you can do one of the following:

Option 1

The kv file is init.kv

class InitApp(App):
    pass

Option 2

The kv file is not init.kv but InitApp.kv

class InitApp(App):

    def build(self):
        return Builder.load_file("InitApp.kv")

kv file - Using class rule

If in your kv file, you have a class rule defined i.e. <Root_Widget>: then in your Python code, you can do one of the following:

Option 1

The kv file is init.kv

class InitApp(App):

    def build(self):
        return Root_Widget()

Option 2

The kv file is not init.kv but InitApp.kv

class InitApp(App):

    def build(self):
        Builder.load_file("InitApp.kv")
        return Root_Widget()

Upvotes: 2

Related Questions