I am trying to create a GUI application in kivy where one function that will get activated on a button press schedules the execution of another function at a later time, which creates a new widget.
This is what I am attempting to implement.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.clock import Clock
Builder.load_file('test.kv')
class MyLayout(Widget):
def schedule_widget(self):
Clock.schedule_once(MyLayout.add_label, 5)
def add_label(self):
self.ids.id.add_widget(Label(text=f'Hello World'))
class MyApp(App):
def build(self):
return MyLayout()
if __name__ == '__main__':
MyApp().run()
<MyLayout>
BoxLayout:
orientation: 'horizontal'
size: root.width, root.height
id: id
Button:
text: 'Add A Label in 5 seconds'
on_release: app.root.schedule_widget()
It crashes and returns the error AttributeError: 'float' object has no attribute 'ids'
, when the button is clicked. If I replace the on_release:
to directly execute the add_label
function, it successfully adds the label even though it is doing the same thing, just without the delay.
You are treating add_label()
as a static method, but it is not. The error comes from add_label()
expecting its argument to be self
, but instead it is getting the dt
(delta time) provided by Clock.schedule_once()
. Try modifying your MyLayout
class as:
class MyLayout(Widget):
def schedule_widget(self):
Clock.schedule_once(self.add_label, 5) # use `self` to access method
def add_label(self, dt): # add dt argument
self.ids.layoutId.add_widget(Label(text=f'Hello World')) # use correct id