Search code examples
pythonkivykivy-languagekivymd

Is there any way to assign text field value to a variable through the App class


I want to assign a kivy text field value to a variable through the App class

This is a bit different case as the text field is placed inside a box layout which is registered as a Factory widget

This is the code


from kivymd.app import App
from kivy.lang import Builder
from kivy.factory import Factory 

kv='''
#:import Factory kivy.factory.Factory

# this is object 1 which will be added to main grid

<object_1@BoxLayout>:

    orientation:'vertical'
    size_hint_y:None
    adaptive_height: True
    height:self.minimum_height 
    id:obj_1

    TextInput:
        size_hint:None,None 
        id:txt



#main grid

BoxLayout:
    orientation:'vertical'
    size_hint_y:None
    adaptive_height: True
    height:self.minimum_height 

    GridLayout:
        cols:1
        size_hint_y:None 
        adaptive_height:True
        height:self.minimum_height 
        id:sc_grid          
        Button:
            size_hint:None,None 
            text: 'Add 1'
            on_press:
                app.add_1()          
                    
        Button:
            size_hint:None,None 
            text: 'Assign value'
            on_press:
                app.Assign()                
                
'''

class MyApp(App):
    
    def build(self):
        return Builder.load_string(kv)

    
    def add_1(self):
        self.root.ids.sc_grid.add_widget(Factory.object_1())

    # this crashes

    def Assign(self):
        txt_1=self.root.ids.txt.text
        
MyApp().run()

I've asked a similar question before but i didn't got any appropriate answers, so i decided to upload one with more clarification

In the above code

●on pressing the button Add1 , Factory widget(BoxLayout) which contains the text field is added to the main Layout

●I've also created another button 'Assign value' to assign the value to a variable

I want it to be assigned though the app class itself

You have the complete freedom to do any modifications as i only need the logic behind it

Thanks in advance


Solution

  • The ids defined in the kv are only added to the ids dictionary of the widget that is the root of the rule where the id is defined. So the txt id will not appear in the BoxLayout that is the root widget of the App. That id will only appear in the ids of an instance of object_1. So you may need to save a reference to the added object_1, like this:

    def add_1(self):
        self.obj_1 = Factory.object_1()
        self.root.ids.sc_grid.add_widget(self.obj_1)
    

    Then you can access the txt id like this:

    def Assign(self):
        txt_1=self.obj_1.ids.txt.text
    

    Of course, if the add_1() method gets called more than once, you will only be able to reference the last added object_1.

    On another note, any class names used in kv should be capitalized. Doing otherwise may cause syntax errors. So, you should rename object_1 to Object_1.