Eric MacLeod
Eric MacLeod

Reputation: 461

How can I change an attribute of a parents class instance

I'm trying to make a custom layout using kivy, I need to generate a gridlayout with scrollview buttons and put it inside of another layout.

Everytime I click the button that generates the buttons it pushes the "get links" button up and if I click it a second time instead of adding buttons to the existing gridlayout it creates a new gridlayout.

This is the app before I press the 'get links' button before I press the button

The first time I press the 'get links' button First time the button is pressed

The second time the button is pressed enter image description here

class RootWidget(BoxLayout):
    pass

class Scrollbox(BoxLayout):
    def __init__(self, **kwargs):
        super(Scrollbox, self).__init__(**kwargs)
        self.orientation = 'vertical'

class CustomLayout(FloatLayout):

    def __init__(self, **kwargs):
        # make sure we aren't overriding any important functionality
        super(CustomLayout, self).__init__(**kwargs)

        with self.canvas.before:
            Color(0, 1, 0, 1)  # green; colors range from 0-1 instead of 0-255
            self.rect = Rectangle(size=self.size, pos=self.pos)

        self.bind(size=self._update_rect, pos=self._update_rect)

    def _update_rect(self, instance, value):
        self.rect.pos = instance.pos
        self.rect.size = instance.size

class MainApp(App):

    link_buttons = 0

    def build(self):
        root = RootWidget()
        c = CustomLayout()
        s = Scrollbox()
        root.add_widget(c)
        root.add_widget(s)

        def on_enter(self):
            func = Function()
            buttons = func.buttons()
            s.add_widget(buttons)

        get_buttons = Button(
            text='Get links',
            size_hint=(1, 0),
            pos=(20, 20))
        s.add_widget(get_buttons)

        get_buttons.bind(on_press=on_enter)
        return root

class Function(MainApp):

    def buttons(self):
        if self.link_buttons == 0:
            layout = GridLayout(cols=1, padding=1, spacing=10,
                    size_hint=(None, None), width=10)
            layout.bind(minimum_height=layout.setter('height'))
            self.link_buttons += 1

        for buttn in range(20):
            btn = Button(text='test', size=(200, 50),
                     size_hint=(None, None))
            try:
                self.layout.add_widget(btn)
            except:
                layout.add_widget(btn)

        # create a scroll view, with a size < size of the grid
        root = ScrollView(size_hint=(None, None), size=(200, 400),
             pos_hint={'center_x': .5, 'center_y': .5}, do_scroll_x=False)
        root.add_widget(layout)
        return root

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

Upvotes: 0

Views: 46

Answers (1)

Yoav Glazner
Yoav Glazner

Reputation: 8066

You have a few problems:

1) Function inherts from MainApp - don't do that - its weird!!

2) You are recreating the ScrollView on each click

Here is a modified (part of) the source code that worked for me

class MainApp(App):

    link_buttons = 0

    def build(self):
        layout = GridLayout(cols=1, padding=1, spacing=10,
                    size_hint=(None, None), width=10)
        layout.bind(minimum_height=layout.setter('height'))
        sv = ScrollView(size_hint=(None, None), size=(200, 400),
             pos_hint={'center_x': .5, 'center_y': .5}, do_scroll_x=False)
        sv.add_widget(layout)
        self.layout = layout
        root = RootWidget()
        c = CustomLayout()
        s = Scrollbox()
        root.add_widget(c)
        root.add_widget(s)
        s.add_widget(sv)



        get_buttons = Button(
            text='Get links',
            size_hint=(1, 0),
            pos=(20, 20))
        s.add_widget(get_buttons)

        get_buttons.bind(on_press=self.buttons)
        return root



    def buttons(self, btn):


        layout = self.layout  
        self.link_buttons += 1

        for buttn in range(20):
            btn = Button(text='test', size=(200, 50),
                     size_hint=(None, None))

            self.layout.add_widget(btn)

Upvotes: 1

Related Questions