Kivy:启动时在屏幕中间绘制圆圈

Kivy: Draw circle to middle of screen on startup

我正在使用 Kivy 构建一个应用程序,并希望在应用程序启动后立即在 Widget 的中间画一个圆圈。我在这个问题 (How do I run a function once the form is loaded Kivy) 中找到了如何 运行 开始编码。但是,正如评论指出的那样,调用 on_start() 时宽度和高度尚未初始化。有谁知道我该怎么做?

我有以下代码。使用它,圆圈绘制在位置 50、50,而我希望它位于 Field 小部件的中间。

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()

方法一: 通过绑定到回调方法使用 bind

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:
    ...

方法二: 通过调度进程使用Clock

    def on_start(self, **kwargs):
        Clock.schedule_once(self.r.field.init_circle)