accessing instances across classes between .py and .kv

930 views
Skip to first unread message

griffo

unread,
May 16, 2017, 1:56:19 PM5/16/17
to Kivy users support
I am having a problem accessing variables from my RootWidget. Here is my setup (btw this is driving me insane so I'm very grateful of any help).

In my kivy file I have the following:
           
<RootWidget>
 TabbedPanelItem:
    text: 'Initialize'
    BoxLayout:
        orientation:'vertical'
    StepSequenceTab:
        id: initialize_tab
    Button:
        size_hint_y: None
        height: '50dp'
        text: 'Save Protocol'
        on_release: root.run_protocol()

Now in my main.py file I have two classes which create StepSequenceTab:

class SequenceWidget(BoxLayout):
   
def __init__(self, **kwargs):
       
super(SequenceWidget, self).__init__(**kwargs)
       
        layout
= GridLayout(id='grid_layout',cols=1,orientation='vertical',size_hint_y=None)
        layout
.bind(minimum_height=layout.setter('height'))
       
       
for row in range(24):
            col1
= TypeInput(id='type_input',text='',values=('Pump', 'Pause'))
            col2
= PumpInput(id='pump_input',text='',values=('Multi', 'Single','Valve'))
            col3
= ValveInput(id='valve_input',text='',values=('0', '1','2','3','4','5'))
            col4
= DirectionInput(id='direction_input',text='',values=('Pickup','Dispense'))
            col5
= VolumeInput(id='volume_input',text=''  ,height=50) #,padding_y=( height - line_height ) / 2.)
            col6
= FlowRateInput(id='flowrate_input',text='',height=50) #,padding_y=( height - line_height ) / 2.)
            col7
= CmdStrInput(id='cmdstr_input',text=''  ,height=50) #,padding_y=( height - line_height ) / 2.,readonly=True)
            col8
= ProgressBarOutput(id='progress_input',size_hint_x= 1,value=50)
            cols
= [col1,col2,col3,col4,col5,col6,col7,col8]
            row_layout
= BoxLayout(id='cmd_row'+str(row+1),orientation='horizontal',width=1600,height=40,size_hint=(None, None))
           
           
for col in cols:
                row_layout
.add_widget(col)

            layout
.add_widget(row_layout)

        root
= ScrollView(id='scroll_view',do_scroll_x=False)
        root
.add_widget(layout)
       
self.add_widget(root)

class StepSequenceTab(BoxLayout):
          def __init__(self, **kwargs):
        super(StepSequenceTab, self).__init__(**kwargs)

        header = BoxLayout(id='box_layout',size_hint_y=None,height=50,orientation='horizontal')
        
        header.add_widget(BubbleButton(id='type_col',text='Type'))
        header.add_widget(BubbleButton(id='pump_col',text='Pump'))
        header.add_widget(BubbleButton(id='valve_col',text='Valve #'))
        header.add_widget(BubbleButton(id='direction_col',text='Direction'))
        header.add_widget(BubbleButton(id='volume_col',text='Volume (uL)'))
        header.add_widget(BubbleButton(id='rate_col',text='Rate (uL/hr)'))
        header.add_widget(BubbleButton(id='string_col',text='String'))
        header.add_widget(BubbleButton(id='progress_col',text='Progress (%)'))

        layout_outer = BoxLayout(id='outer_box_layout',orientation='vertical')
        wid = SequenceWidget(id='sequence_widget')

        layout_outer.add_widget(header)
        layout.add_widget(wid)
        self.add_widget(layout_outer)

Now inside my RootWidget in my main.py I also have;

class RootWidget(FloatLayout):
    def __init__(self):
        super(RootWidget, self).__init__()

    def run_protocol(self):
        print(self.ids.initialize_tab)

For a visual, my screen looks like this -- where the the inner table is a scrollview with many rows to enter in information. I want to be able to access those rows in the RootWidget.



Basically I want to be able to do:

print(self.ids.cmd_row1.volume_input.text)

and to print out the text value for volume_input (i.e. volume_input.text) then loop through cmd_row2 and basically build up a table of that information within the scrollview after the user has entered in that information (within the rootwidget). I can't access these variables because I think I'm confused over parent-child relationships in Python verses what the id means in kivy. It isn't clear to me that the instances are passed through the classes. i.e. whether root can see the variables inside StepSequenceTab let alone SequenceWidget.

Any help is greatly appreciated. 




mjkuwp94

unread,
May 16, 2017, 2:29:36 PM5/16/17
to Kivy users support
looks like an interesting project!

sorry I cannot help a lot other than to say I am working with a similar problem.  One thing I learned is that the id: is only accessible and meaningful inside the .kv file.

If you Google around you will find years' old conversations about similar problems.  Looking at these is a bit dangerous since things may have changed.

 A problem (my opinion) is that Kivy has many ways to do the same thing and each time I see the problem the project structure is a tiny bit different.

Jacek Blocki

unread,
May 17, 2017, 7:12:43 AM5/17/17
to Kivy users support
Add ObjectProperty() to a class from which you want to reference an object and map the object to your property in kv:

In your .py:

class RootWidget(FloatLayout):
    #  ObjectProperty can reference any object
    sst = ObjectProperty()
    bl = ObjectProperty()

In .kv file

<RootWidget>
    #  set ObjectPropery() values to object you want to reference
    sst: initialize_tab
    bl: name_bl

    TabbedPanelItem:
        text: 'Initialize'
    BoxLayout:
            id: name_bl

            orientation:'vertical'
        StepSequenceTab:
            id: initialize_tab
        Button:
            size_hint_y: None
            height: '50dp'
            text: 'Save Protocol'
            on_release: root.run_protocol()

RootWidget methods can now access BoxLayout widget via self.bl
BR, Jacek

Brendan Griffen

unread,
May 17, 2017, 1:29:50 PM5/17/17
to kivy-...@googlegroups.com
Hi Jacek; thanks. though how is this different from just setting id: initialize_tab inside StepSequenceTab and accessing it via self.ids.initialize_tab? When I do print(self.ids.initialize_tab) or print(self.sst), I get the same result. Since StepSequenceTab is a class in my main.py, I still can't access the variables within the class, like self.sst.cmd_row2.type_input.
Thanks.
Brendan

--
You received this message because you are subscribed to a topic in the Google Groups "Kivy users support" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/kivy-users/-WlN4c5mCY4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to kivy-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jacek Blocki

unread,
May 17, 2017, 4:59:38 PM5/17/17
to Kivy users support
Brendan,
Have a look at the docs: https://kivy.org/docs/api-kivy.uix.widget.html?highlight=widget#module-kivy.uix.widget
ids is a dictionary, syntax for class variable access should be:
self.ids['cmd_row1'].variable not self.ids.cmd_row1.variable

Please note comment in Widget code:
ids = DictProperty({})
'''This is a dictionary of ids defined in your kv language. This will only
be populated if you use ids in your kv language code.

Your define id 'cmd_row1' in python, it would not go to ids dictionary so unfortunately you cannot use it that way.  You can make own dictionary in SequenceWidget class like selff.row_ids={} and add each row to it for further reference: row_ids['cmd_row{}.format(row)] = row_layout
JB

Brendan Griffen

unread,
May 18, 2017, 3:13:46 AM5/18/17
to kivy-...@googlegroups.com
Hi Jacek; Thanks. Yes I am no aware of how ids work inside kivy - they are distinct from the python component. Though your suggestion creates a dictionary inside the SequenceWidget - how do I access this inside the RootWidget? I'll still obviously get; AttributeError: 'RootWidget' object has no attribute 'row_ids'. Thanks.

Reply all
Reply to author
Forward
0 new messages