'kivy: How to pass arguments to a Widget Class

I want to create a UI passing an argument to a part of my interface. I know that, in this example, I could just put the label text as a variable and change it from the code, but this is a very simplyfied example. What i really need is to delete and recreate an object (a layout widget) inside my main Screen using different arguments each time.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label

class MyBox(Boxlayout):
    def __init__(self, text, **kwargs):
        super(MyBox, self).__init__(**kwargs)
        self.text = text
        lbl = Label(text=self.text)
        btn = Button(text=f'Modify "{self.text}" label')
        self.add_widget(lbl)
        self.add_widget(btn)
            
class MainWidget(BoxLayout):
    text1 = 'Hello Kivy'
    text2 = 'Goodbye Kivy'
    # I want this text to be passed to the MyBox object

class MainApp(App):
    pass

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

And the kv file:

MainWidget:

<MainWidget>:
    orientation: 'vertical'
    Label:
        text: 'Title'
    Label:
        text: 'Subtitle'
    MyBox:
    Label:
        text: 'Bottom text'
    Button:
        text: 'Exit'

<MyBox>:

Later (I haven't done it yet) i would like to change the middle section deleting that MyBox object and creating it back again passing another argument.



Solution 1:[1]

In order to pass more arguments to a kivy class' __init__, you have to create a Kivy attribute, which is just replacing the normal attribute definition:

class myClass(ParentClass):
    def __init__(self,*args,**kwargs):
        super().__init__(**kwargs)
        self.attribute="hello world"
        #do stuff

into a Kivy attribute definition:

from kivy.uix.widget import Widget
from kivy.properties import StringProperty
class myClass(Widget):
#remember to always define Kivy properties before defining __init__
    attribute=StringProperty("hello world")
    def __init__(self,*args,**kwargs):
        super().__init__(**kwargs)
        #do stuff

This is how you let Kivy know to expect more arguments, and avoid the dreaded TypeError: Properties [property] passed to __init__ may not be existing property names. Valid properties are [list of kivy properties]

I hope this helps someone looking for the answer, though it seems you've already found a different solution to your problem.

This knowledge came from debugging and reading this page: https://kivy.org/doc/stable/api-kivy.properties.html?highlight=properties

In my case, passing properties like this was the way to go. Feel free to comment if you found another way to do it so this can be a more helpful search result.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 LasevIX_