Right way to add a widget to an instance imported from kv file

36 views
Skip to first unread message

Juan Francisco López-Egea Martínez

unread,
Feb 8, 2019, 6:33:00 AM2/8/19
to Kivy users support
Hi, I'm trying to add a widget (button) to a GridLayout instance imported from Kv file, but find no way. I read in stackoverflow something about clock and lambdas, but still no lucky, so, I'm gonna ask it here, take a look just at "for" loop (the other things, label, color change, etc... neverminds). I must to say in Kv file there are some buttons added "at hand" (or hardcoded), i would like to be able to add/remove a widget from being parented to another on the fly.

Well, the code:

main.py:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty
from kivy.clock import Clock
from colorsys import hsv_to_rgb, rgb_to_hsv
from kivy.uix.gridlayout import GridLayout
#from kivy.uix.scrollview import ScrollView

#class Sview(ScrollView):
#    scrollviewClass = ObjectProperty(None)

#class Glayout(GridLayout):
#    gridLayoutClass = ObjectProperty(None)

class MoneyControl(Widget):
    cartel
= ObjectProperty(None)
    mainScrollView
= ObjectProperty(None)
    childGridLayout
= ObjectProperty(None)

    lay
= 3
    rainbow
= [0.0,1.0,1.0,1.0]

    buttonsList
= [None]
   
for i in range(100):
       
#ANY OF THIS WAYS TO ADD A WIDGET WORKS. WHICH ONE WOULD BE THE RIGHT ONE?
       
self.childGridLayout.add_widget(Button(text="This now works?")) #Opt1
       
#childGridLayout.add_widget(Button(text="This now works?")) #Opt2
       
#Clock.schedule_once(lambda dt: childGridLayout.add_widget(TbuttonOdd)) #Opt3
       
#Clock.schedule_once(lambda dt: self.childGridLayout.add_widget(TbuttonOdd)) #Opt4
       
#GridLayout(childGridLayout).add_widget(TbuttonOdd) #Opt5
   
print buttonsList

   
def hsva_to_rgba(self, hsva):
        rgba
= hsv_to_rgb(hsva[0], hsva[1], hsva[2])
        rgba
= list(rgba)
        rgba
.append(hsva[3])
       
return rgba

   
def update(self, dt):
       
self.lay += 1
       
self.cartel.text = str(self.lay)
       
#self.cartel.colormode = hsv
       
#self.cartel.color = self.lay*0.0001, self.lay*0.0002, self.lay*0.0004, 1
       
self.rainbow[0] += self.lay*0.0001
        finalRgba
= self.hsva_to_rgba(self.rainbow)
       
self.cartel.color = finalRgba


class MoneyControlApp(App):
   
def build(self):
        prog
= MoneyControl()
       
Clock.schedule_interval(prog.update, 1.0 / 60.0)
       
return prog

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



kv file:

#:kivy 1.0.9

<TbuttonEven@Button>:# nameYouWant @ class
    text
: "Test Text"
    size_hint_y
: None
    height
: 40
    background_normal
: ""
    background_color
: 0.7, 0.9, 0.7, 1.0

<TbuttonOdd@Button>:# nameYouWant @ class
    text
: "Different BgColor!"
    size_hint_y
: None
    height
: 40
    background_normal
: ""
    background_color
: 0.6, 0.85, 0.6, 1.0

<ScView@ScrollView>:
    size_hint
: None, None
   
#size: root.width, root.height
   
#top: 0
   
#center_x: root.width
    pos
: 100,200

<Glo@GridLayout>:
    cols
:1
    spacing
:0
    size_hint
: None, None
   
#size_hint_x: None #False en lugar de None?
   
#size_hint_y: None #False en lugar de None?
    height
: self.minimum_height

<MoneyControl@Widget>:
#MoneyControl:#RootWidget
    cartel
: crt
    mainScrollView
:rollerresults
    childGridLayout
:resultsBlock

   
ScView:
        id
:rollerresults
        size
: 800, 600

       
Glo:
            id
:resultsBlock

           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:
           
TbuttonEven:
           
TbuttonOdd:

   
Label:
        id
: crt
        font_size
: 20
        center_x
: root.width * 0.5
        top
: root.height * 0.5
        text
: "hola"
        color
: 1, .3, .8, 1


Whats the right way to access the functions of a... layout instance? I can access and modify Label instance properties, but not the gridLayout ones!...

ZenCODE

unread,
Feb 8, 2019, 9:20:29 AM2/8/19
to Kivy users support
This line is correct.

self.childGridLayout.add_widget(Button(text="This now works?")) #Opt1

But your kv rule does not make sense. Glo?

        Glo:
            id
:resultsBlock

Surely that should be "GridLayout:"?



Juan Francisco López-Egea Martínez

unread,
Feb 8, 2019, 5:21:46 PM2/8/19
to Kivy users support
Glo is an instance of the class Glo (GridLayOut) defined a little bit more up, and an id to that instance, to be able to add buttons later.

Is that way a wrong way to do it?.

Thank you for your time and support ZenCODE.

ZenCODE

unread,
Feb 9, 2019, 1:05:48 AM2/9/19
to Kivy users support
No, that is fine. I missed that. But then surely

    self.childGridLayout.add_widget(Button(text="This now works?")) #Opt1

works, as the comment indicates? So what exactly is the problem?

Juan Francisco López-Egea Martínez

unread,
Feb 9, 2019, 3:42:08 AM2/9/19
to Kivy users support
It says to me:

NameError: name 'self' is not defined.

Thing that drives me crazy, since self.cartel for example works wonderfully to be able to modify text and color...

I'm using Kivy v1.9.0
Is a matter of use Kivy master version?

ZenCODE

unread,
Feb 9, 2019, 4:34:56 AM2/9/19
to Kivy users support
Yes, you have put that code in the class definition, not in any method. Try

class MoneyControl(Widget):
    cartel
= ObjectProperty(None)
    mainScrollView
= ObjectProperty(None)
    childGridLayout
= ObjectProperty(None)

    lay
= 3
    rainbow
= [0.0,1.0,1.0,1.0]

   
def __init__(self, **kwargs):

        buttonsList
= [None]
       
for i in range(100):
           
#ANY OF THIS WAYS TO ADD A WIDGET WORKS. WHICH ONE WOULD BE THE RIGHT ONE?

Juan Francisco López-Egea Martínez

unread,
Feb 10, 2019, 7:58:44 AM2/10/19
to Kivy users support
Done. But still same error as at beginning: AttributeError: 'NoneType' object has no attribute 'add_widget'

main.py:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty
from kivy.clock import Clock
from colorsys import hsv_to_rgb, rgb_to_hsv
from kivy.uix.gridlayout import GridLayout
#from kivy.uix.scrollview import ScrollView

#class Sview(ScrollView):
#    scrollviewClass = ObjectProperty(None)

#class Glayout(GridLayout):
#    gridLayoutClass = ObjectProperty(None)

class MoneyControl(Widget):
    cartel
= ObjectProperty(None)
    mainScrollView
= ObjectProperty(None)
    childGridLayout
= ObjectProperty(None)
    lay
= 3
    rainbow
= [0.0,1.0,1.0,1.0]

   
def __init__(self, **kwargs):
        buttonsList
= [None]
       
for i in range(100):

           
self.childGridLayout.add_widget(Button(text="This now works?")) #Opt1
#    print buttonsList


   
def hsva_to_rgba(self, hsva):
        rgba
= hsv_to_rgb(hsva[0], hsva[1], hsva[2])
        rgba
= list(rgba)
        rgba
.append(hsva[3])
       
return rgba

   
def update(self, dt):
       
self.lay += 1
       
self.cartel.text = str(self.lay)
       
#self.cartel.colormode = hsv
       
#self.cartel.color = self.lay*0.0001, self.lay*0.0002, self.lay*0.0004, 1
       
self.rainbow[0] += self.lay*0.0001
        finalRgba
= self.hsva_to_rgba(self.rainbow)
       
self.cartel.color = finalRgba


class MoneyControlApp(App):
   
def build(self):
        prog
= MoneyControl()
       
Clock.schedule_interval(prog.update, 1.0 / 60.0)
       
return prog

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


I'm starting to ask myself if there is something terribly bad on my machine or what is happening...

Reply all
Reply to author
Forward
0 new messages