Add widget from python to a specific widget depth.

549 views
Skip to first unread message

Gouz

unread,
Apr 30, 2015, 2:26:02 AM4/30/15
to kivy-...@googlegroups.com
Hey guys I got in my kv file something like that:


<MainWindow>: # root BoxLayout
<ISelect>: # Screen 1
    my_list: my_list.__self__
BoxLayout:
BoxLayout:
            id: my_list
Button:
Label:
<MDes>: # Screen 2



So my question here would be.. Can I add from Python a new button on last boxlaout, next to the already appeared Button?
I tried to give an id to the last BoxLaout and ref it in kivy. and then something like that from inside the class:

class ISelect(Screen):

def __init__(self, **kwargs):
super(ISelect, self).__init__(**kwargs)
self.index_button_3 = Button(text='Hello world 1')
self.my_list.add_widget(self.index_button_3)



But python is not happy with it and complains AttributeError: 'ISelect' object has no attribute 'my_list'


Thx for your time
And sorry if what I write here makes no sence. hehhe

The Wonton

unread,
Apr 30, 2015, 9:13:21 AM4/30/15
to kivy-...@googlegroups.com
The page below talks about accessing widgets defined in a kv file from python.


In your kv file the only change I saw was to remove the .__self___ as it isn't needed.
<MainWindow>:  # root BoxLayout
<ISelect>
:  # Screen 1    
    my_list: my_list

    BoxLayout:
        BoxLayout:
            id: my_list
            Button:
        Label:
<MDes>:  # Screen 2

In your python file, you just need to import and create an ObjectProperty to reference the widget.
#With your other imports
from kivy.properties import ObjectProperty

class
ISelect(Screen):

my_list = ObjectProperty() # Note that this is at the class level...

 
def __init__(self, **kwargs):

 
super(ISelect, self).__init__(**kwargs)
 
self.index_button_3 = Button(text='Hello world 1')
 
self.my_list.add_widget(self.index_button_3)

That should work now. Hope that helps!


Alexander Taylor

unread,
Apr 30, 2015, 12:00:02 PM4/30/15
to kivy-...@googlegroups.com
Replace self.my_list with self.ids.my_list

Gouz

unread,
May 1, 2015, 7:29:02 AM5/1/15
to kivy-...@googlegroups.com
I tried this but it still aint working. It says.
AttributeError: 'NoneType' object has no attribute 'add_widget'

Also about removing __self__ .
Why is this necessery? From docs, isn't that the case?

To keep the widget alive, a direct reference to the label_widget widget must be kept. This is achieved using id.__self__ or label_widget.__self__ in this case. The correct way to do this would be:

<MyWidget>:
    label_widget: label_widget.__self__

Gouz

unread,
May 1, 2015, 7:31:43 AM5/1/15
to kivy-...@googlegroups.com
I also tried that but now the error was AttributeError: 'super' object has no attribute '__getattr__'

Gouz

unread,
May 1, 2015, 8:26:34 AM5/1/15
to kivy-...@googlegroups.com
This is the core:
https://gist.github.com/gouzouni/69a2b1aa78897916e689

How could I make it work?

Gouz

unread,
May 1, 2015, 8:43:26 AM5/1/15
to kivy-...@googlegroups.com
As mixedCas1 pointed, I might be initializing the kv file -after- object instantiation. I believe that might be the case.
Maybe I could put my addwidget inside my own function and call it after kv load.
However, I would like this to be called right after App start.
So at which point should I call that?

The Wonton

unread,
May 1, 2015, 10:04:27 AM5/1/15
to kivy-...@googlegroups.com
I'd recommend waiting for a better answer as this is really ugly.Off the top of my head, this was the only thing I could think of. If it is an issue of initializing the kv file after the object has already been created, you could try using the on_start method of the App. This is called after build, but before the app starts. So maybe something like this...

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.button import Button
from kivy.properties import ObjectProperty


class IndexSelection(Screen):
    topics_list
= ObjectProperty()

   
# The function that will be called to add the button
   
def add_but(self):
       
self.topics_but_2 = Button(text='Hello world 1')
       
self.topics_list.add_widget(self.topics_but_2)


class CIMScreenManager(ScreenManager):
   
pass


class MainWindow(BoxLayout):
   
pass


class CIMgui(App):
   
def build(self):
       
return MainWindow()

   
def on_start(self, **kwargs):
       
super(CIMgui, self).on_start(**kwargs)

       
# Ensure that the correct screen is selected and call the add_but() function.
       
# I'm sure there's a better way of doing this...
       
self.root.ids['manager'].current = 'IndexSelectionScreen'
       
self.root.ids['manager'].current_screen.add_but()


CIMgui().run()






Reply all
Reply to author
Forward
0 new messages