I'd like to control a simple Ellipse widget created in Kivy using KV Language. I have been working on this for days having read and worked through the exercises in the book Kivy: Interactive Applications in Python by Roberto Ulloa and Ben Rousch's online workshop at https://bradfortner.wordpress.com/2017/07/19/good-kivy-tutorial/.
While the examples provided in those tutorials seem to work fine on pre-defined Kivy widgets (ie. Buttons and Labels) I'm having trouble controlling Widgets that I define such as a circular ellipse as shown in the code below.
In the code (below) I create the circular ellipse class Widget (named Ball) on lines 10 and 45. I place the Ball Widget on my layout (line 29) and then id the Widget as my_circle (line 30). Finally I provide the code to link the widget to Python (line 26) so Python code can control the Widget.
However when I press the "Shrink Circle" button and the shrink_circle() function is called there is no effect on the widget. Any idea where the code goes wrong? I'd love to know because it's become quite the mystery to me and I cant find anything simple that explains what I need to do to correct this.
Full code below.
Appreciated in advance.
....brad....
# Modified from https://github.com/brousch/pyohio-kivy-tutorial/blob/master/tutorial/step11_tts/saythis.kv
import kivy
from kivy.lang import Builder
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
kivy.require("1.9.1")
Builder.load_string('''
<Ball>:
size: 1, 1
canvas:
Color:
rgba: 1, 1, 1, 1
Ellipse:
pos: 350,290
size: 70,70
<ShrinkThis>:
button_font_size: '30sp'
canvas:
Color:
rgba: 0, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
my_circle: my_circle
BoxLayout:
orientation: 'horizontal'
Ball:
id: my_circle
Button:
text: 'Shrink Circle'
font_size: root.button_font_size
size_hint: 1, None
on_press: root.shrink_circle()
''')
class ShrinkThis(BoxLayout):
my_circle = ObjectProperty(None)
def shrink_circle(self):
self.my_circle.size = (10,10)
class Ball(Widget):
pass
class ShrinkThisApp(App):
def build(self):
return ShrinkThis()
if __name__ == '__main__':
ShrinkThisApp().run()
Remember that kivy canvas
is not a widget and it isn't the space in which you paint, it is just a set of instructions to draw. Ball
should be a widget.
On the other hand, the size
property is ignored if size_hint
property is not disabled.
Simplified example:
import kivy
kivy.require("1.9.1")
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
Builder.load_string('''
<Ball@Widget>
size: 70, 70
pos: 350,290
size_hint: None, None
canvas:
Color:
rgba: 1, 1, 1, 1
Ellipse:
pos: self.pos
size: self.size
<ShrinkThis>:
button_font_size: '30sp'
my_circle: my_circle
Ball:
id: my_circle
Button:
text: 'Shrink Circle'
font_size: root.button_font_size
size_hint: 1, None
on_press: root.shrink_circle()
''')
Output: