John Daly
John Daly

Reputation: 85

Adding a new Button on release of another button in Kivy

I'm trying to have a button where if it is clicked it will insert a new button. I cant get the bind to return the new button.

from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.scatter import Scatter
from kivy.uix.button import Button


class app(App):
    def build(self):
        layout = FloatLayout()
        button1 =Button(text="test",pos=(385,450),size_hint=(.1,.1))
        button1.bind(on_release=self.btn2)
        layout.add_widget(button1)
        return layout

    def btn2(self, event):
        print "worked"
        layout = FloatLayout()
        btn3 = Button(text="worked",size=(.1,.1),pos=(380,400))
        layout.add_widget(btn3)
        return layout

app().run()

Upvotes: 1

Views: 990

Answers (1)

Peter Badida
Peter Badida

Reputation: 12199

You are creating another instance of FloatLayout in the btn2 event with layout = FloatLayout(), however that instance isn't anywhere else, but in the btn2 method - i.e. you added a Button to FloatLayout, but that layout isn't visible and after the function ends it's highly possible that even doesn't exist, because it's garbage-collected by Python.

You can either use partial to pass the already existing instance of FloatLayout (where your previous Button is) like this if you need only one layout:

from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App

from functools import partial

class app(App):
    def build(self):
        layout = FloatLayout()
        button1 =Button(text="test",pos=(385,450),size_hint=(.1,.1))
        button1.bind(on_release=partial(self.btn2, layout))
        layout.add_widget(button1)
        return layout

    def btn2(self, layout, *args):
        print "worked"
        btn3 = Button(text="worked",size=(.1,.1),pos=(380,400))
        layout.add_widget(btn3)

app().run()

Or you can use the instance that's passed to method arguments from the event (the instance of a widget that dispatched the event):

from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App

class app(App):
    def build(self):
        layout = FloatLayout()
        button1 =Button(text="test",pos=(385,450),size_hint=(.1,.1))
        button1.bind(on_release=self.btn2)
        layout.add_widget(button1)
        return layout

    def btn2(self, button):
        layout = button.parent  # parent of the button is the "layout" from build()
        btn3 = Button(text="worked",size=(.1,.1),pos=(380,400))
        layout.add_widget(btn3)

app().run()

In both cases you only need to find the right instance to work with, not create another one that's not even used. Also return layout isn't necessary if you don't expect on_release to work with the layout variable (which it won't).

Upvotes: 1

Related Questions