Reputation: 41
I am building an app using Kivy and would like to draw a circle to the middle of a Widget as soon as the app starts up. I found how to run code on start in this question (How do I run a function once the form is loaded Kivy). However, as a comment points out, widths and heights are not initialized yet when calling on_start(). Does anyone know how I could do this?
I have the following code. Using this, the circle is drawn at position 50, 50, while I would like it in the middle of the Field widget.
main.py:
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle, Color, Ellipse
from kivy.lang import Builder
from kivy.properties import ObjectProperty
class Field(Widget):
def __init__(self, **kwargs):
super(Field, self).__init__(**kwargs)
def init_circle(self):
with self.canvas:
Color(1,1,1,1, mode='rgba')
r = 20
self.circle = Ellipse(pos=(self.width//2 - r, self.height//2 - r), size=(2*r, 2*r))
print(self.circle)
def move_circle(self):
cx, cy = self.circle.pos
self.circle.pos = (cx + 10, cy)
class RootClass(Widget):
field = ObjectProperty(None)
def __init__(self, **kwargs):
super(RootClass, self).__init__(**kwargs)
class MyMainApp(App):
def build(self):
self.r = RootClass()
return self.r
def on_start(self, **kwargs):
self.r.field.init_circle()
if __name__ == '__main__':
Builder.load_file("my.kv")
MyMainApp().run()
my.kv:
<RootClass>
field: field_id
BoxLayout:
size: root.size
orientation: "vertical"
Field:
id: field_id
size_hint: 1, 0.9
Button:
size_hint: 1, 0.1
text: "Move"
on_press:
root.field.move_circle()
Upvotes: 2
Views: 986
Reputation: 2888
Method 1:
Using bind
by binding to a callback method,
class Field(Widget):
def __init__(self, **kwargs):
super(Field, self).__init__(**kwargs)
# Bind a callback method, say here 'init_circle' to the prop. 'size' and 'pos'
# so that whenever those prop. change the method will be called.
# To prevent redrawing you may use method 'clear' or some other strategy.
self.bind(size = self.init_circle, pos = self.init_circle)
def init_circle(self, *args):
with self.canvas:
...
Method 2:
Using Clock
by scheduling the process,
def on_start(self, **kwargs):
Clock.schedule_once(self.r.field.init_circle)
Upvotes: 1