Table Of Contents
- Widget class
- Using Properties
- Basic drawing
- Widget touch event bubbling
- Usage of
Widget.center,Widget.right, andWidget.top WidgetWidget.add_widget()Widget.apply_class_lang_rules()Widget.clear_widgets()Widget.collide_point()Widget.collide_widget()Widget.export_as_image()Widget.export_to_png()Widget.get_parent_window()Widget.get_root_window()Widget.get_window_matrix()Widget.on_motion()Widget.on_touch_down()Widget.on_touch_move()Widget.on_touch_up()Widget.proxy_refWidget.register_for_motion_event()Widget.remove_widget()Widget.to_local()Widget.to_parent()Widget.to_widget()Widget.to_window()Widget.unregister_for_motion_event()Widget.walk()Widget.walk_reverse()
WidgetException
Widget class¶
The Widget class is the base class required for creating Widgets.
This widget class was designed with a couple of principles in mind:
Event Driven
Widget interaction is built on top of events that occur. If a property changes, the widget can respond to the change in the ‘on_<propname>’ callback. If nothing changes, nothing will be done. That’s the main goal of the
Propertyclass.Separation Of Concerns (the widget and its graphical representation)
Widgets don’t have a draw() method. This is done on purpose: The idea is to allow you to create your own graphical representation outside the widget class. Obviously you can still use all the available properties to do that, so that your representation properly reflects the widget’s current state. Every widget has its own
Canvasthat you can use to draw. This separation allows Kivy to run your application in a very efficient manner.Bounding Box / Collision
Often you want to know if a certain point is within the bounds of your widget. An example would be a button widget where you only want to trigger an action when the button itself is actually touched. For this, you can use the
collide_point()method, which will return True if the point you pass to it is inside the axis-aligned bounding box defined by the widget’s position and size. If a simple AABB is not sufficient, you can override the method to perform the collision checks with more complex shapes, e.g. a polygon. You can also check if a widget collides with another widget withcollide_widget().
We also have some default values and behaviors that you should be aware of:
A
Widgetis not aLayout: it will not change the position or the size of its children. If you want control over positioning or sizing, use aLayout.The default size of a widget is (100, 100). This is only changed if the parent is a
Layout. For example, if you add aLabelinside aButton, the label will not inherit the button’s size or position because the button is not a Layout: it’s just another Widget.The default size_hint is (1, 1). If the parent is a
Layout, then the widget size will be the parent layout’s size.on_touch_down(),on_touch_move(),on_touch_up()don’t do any sort of collisions. If you want to know if the touch is inside your widget, usecollide_point().
Using Properties¶
When you read the documentation, all properties are described in the format:
<name> is a <property class> and defaults to <default value>.
e.g.
textis aStringPropertyand defaults to ‘’.
If you want to be notified when the pos attribute changes, i.e. when the widget moves, you can bind your own callback function like this:
def callback_pos(instance, value):
print('The widget', instance, 'moved to', value)
wid = Widget()
wid.bind(pos=callback_pos)
Read more about Properties.
Basic drawing¶
Widgets support a range of drawing instructions that you can use to customize the look of your widgets and layouts. For example, to draw a background image for your widget, you can do the following:
def redraw(self, args):
self.bg_rect.size = self.size
self.bg_rect.pos = self.pos
widget = Widget()
with widget.canvas:
widget.bg_rect = Rectangle(source="cover.jpg", pos=self.pos, size=self.size)
widget.bind(pos=redraw, size=redraw)
To draw a background in kv:
Widget:
canvas:
Rectangle:
source: "cover.jpg"
size: self.size
pos: self.pos
These examples only scratch the surface. Please see the kivy.graphics
documentation for more information.
Widget touch event bubbling¶
When you catch touch events between multiple widgets, you often need to be aware of the order in which these events are propagated. In Kivy, events bubble up from the first child upwards through the other children. If a widget has children, the event is passed through its children before being passed on to the widget after it.
As the add_widget() method inserts widgets at
index 0 by default, this means the event goes from the most recently added
widget back to the first one added. Consider the following:
box = BoxLayout()
box.add_widget(Label(text="a"))
box.add_widget(Label(text="b"))
box.add_widget(Label(text="c"))
The label with text “c” gets the event first, “b” second and “a” last. You can reverse this order by manually specifying the index:
box = BoxLayout()
box.add_widget(Label(text="a"), index=0)
box.add_widget(Label(text="b"), index=1)
box.add_widget(Label(text="c"), index=2)
Now the order would be “a”, “b” then “c”. One thing to keep in mind when using
kv is that declaring a widget uses the
add_widget() method for insertion. Hence, using
BoxLayout:
MyLabel:
text: "a"
MyLabel:
text: "b"
MyLabel:
text: "c"
would result in the event order “c”, “b” then “a” as “c” was actually the last added widget. It thus has index 0, “b” index 1 and “a” index 2. Effectively, the child order is the reverse of its listed order.
This ordering is the same for the on_touch_move()
and on_touch_up() events.
In order to stop this event bubbling, a method can return True. This tells Kivy the event has been handled and the event propagation stops. For example:
class MyWidget(Widget):
def on_touch_down(self, touch):
If <some_condition>:
# Do stuff here and kill the event
return True
else:
return super(MyWidget, self).on_touch_down(touch)
This approach gives you good control over exactly how events are dispatched
and managed. Sometimes, however, you may wish to let the event be completely
propagated before taking action. You can use the
Clock to help you here:
class MyWidget(Label):
def on_touch_down(self, touch, after=False):
if after:
print "Fired after the event has been dispatched!"
else:
Clock.schedule_once(lambda dt: self.on_touch_down(touch, True))
return super(MyWidget, self).on_touch_down(touch)
Usage of Widget.center, Widget.right, and Widget.top¶
A common mistake when using one of the computed properties such as
Widget.right is to use it to make a widget follow its parent with a
KV rule such as right: self.parent.right. Consider, for example:
FloatLayout:
id: layout
width: 100
Widget:
id: wid
right: layout.right
The (mistaken) expectation is that this rule ensures that wid’s right will always be whatever layout’s right is - that is wid.right and layout.right will always be identical. In actual fact, this rule only says that “whenever layout’s right changes, wid’s right will be set to that value”. The difference being that as long as layout.right doesn’t change, wid.right could be anything, even a value that will make them different.
Specifically, for the KV code above, consider the following example:
>>> print(layout.right, wid.right)
(100, 100)
>>> wid.x = 200
>>> print(layout.right, wid.right)
(100, 300)
As can be seen, initially they are in sync, however, when we change wid.x they go out of sync because layout.right is not changed and the rule is not triggered.
The proper way to make the widget follow its parent’s right is to use
Widget.pos_hint. If instead of right: layout.right we did
pos_hint: {‘right’: 1}, then the widgets right will always be set to be
at the parent’s right at each layout update.
- class kivy.uix.widget.Widget(**kwargs)¶
Bases:
kivy.uix.widget.WidgetBaseWidget class. See module documentation for more information.
- Events:
- on_touch_down: (touch, )
Fired when a new touch event occurs. touch is the touch object.
- on_touch_move: (touch, )
Fired when an existing touch moves. touch is the touch object.
- on_touch_up: (touch, )
Fired when an existing touch disappears. touch is the touch object.
- on_kv_post: (base_widget, )
Fired after all the kv rules associated with the widget and all other widgets that are in any of those rules have had all their kv rules applied. base_widget is the base-most widget whose instantiation triggered the kv rules (i.e. the widget instantiated from Python, e.g.
MyWidget()).Changed in version 1.11.0.
Warning
Adding a __del__ method to a class derived from Widget with Python prior to 3.4 will disable automatic garbage collection for instances of that class. This is because the Widget class creates reference cycles, thereby preventing garbage collection.
Changed in version 1.0.9: Everything related to event properties has been moved to the
EventDispatcher. Event properties can now be used when constructing a simple class without subclassingWidget.Changed in version 1.5.0: The constructor now accepts on_* arguments to automatically bind callbacks to properties or events, as in the Kv language.
- add_widget(widget, index=0, canvas=None)¶
Add a new widget as a child of this widget.
- Parameters:
- widget:
Widget Widget to add to our list of children.
- index: int, defaults to 0
Index to insert the widget in the list. Notice that the default of 0 means the widget is inserted at the beginning of the list and will thus be drawn on top of other sibling widgets. For a full discussion of the index and widget hierarchy, please see the Widgets Programming Guide.
New in version 1.0.5.
- canvas: str, defaults to None
Canvas to add widget’s canvas to. Can be ‘before’, ‘after’ or None for the default canvas.
New in version 1.9.0.
- widget:
>>> from kivy.uix.button import Button >>> from kivy.uix.slider import Slider >>> root = Widget() >>> root.add_widget(Button()) >>> slider = Slider() >>> root.add_widget(slider)
- apply_class_lang_rules(root=None, ignored_consts={}, rule_children=None)¶
Method that is called by kivy to apply the kv rules of this widget’s class.
- Parameters:
This is useful to be able to execute code before/after the class kv rules are applied to the widget. E.g. if the kv code requires some properties to be initialized before it is used in a binding rule. If overwriting remember to call
super, otherwise the kv rules will not be applied.In the following example,
class MyWidget(Widget): pass class OtherWidget(MyWidget): pass
- <MyWidget>:
my_prop: some_value
- <OtherWidget>:
other_prop: some_value
When
OtherWidgetis instantiated withOtherWidget(), the widget’sapply_class_lang_rules()is called and it applies the kv rules of this class -<MyWidget>and<OtherWidget>.Similarly, when the widget is instantiated from kv, e.g.
<MyBox@BoxLayout>: height: 55 OtherWidget: width: 124
OtherWidget’sapply_class_lang_rules()is called and it applies the kv rules of this class -<MyWidget>and<OtherWidget>.Note
It applies only the class rules not the instance rules. I.e. in the above kv example in the
MyBoxrule whenOtherWidgetis instantiated, itsapply_class_lang_rules()applies the<MyWidget>and<OtherWidget>rules to it - it does not apply thewidth: 124rule. Thewidth: 124rule is part of theMyBoxrule and is applied by theMyBox’s instance’sapply_class_lang_rules().Changed in version 1.11.0.
- clear_widgets(children=None)¶
Remove all (or the specified)
childrenof this widget. If the ‘children’ argument is specified, it should be a list (or filtered list) of children of the current widget.Changed in version 1.8.0: The children argument can be used to specify the children you want to remove.
Changed in version 2.1.0: Specifying an empty
childrenlist leaves the widgets unchanged. Previously it was treated likeNoneand all children were removed.
- collide_point(x, y)¶
Check if a point (x, y) is inside the widget’s axis aligned bounding box.
- Parameters:
- x: numeric
x position of the point (in parent coordinates)
- y: numeric
y position of the point (in parent coordinates)
- Returns:
A bool. True if the point is inside the bounding box, False otherwise.
>>> Widget(pos=(10, 10), size=(50, 50)).collide_point(40, 40) True
- collide_widget(wid)¶
Check if another widget collides with this widget. This function performs an axis-aligned bounding box intersection test by default.
- Parameters:
- wid:
Widgetclass Widget to test collision with.
- wid:
- Returns:
bool. True if the other widget collides with this widget, False otherwise.
>>> wid = Widget(size=(50, 50)) >>> wid2 = Widget(size=(50, 50), pos=(25, 25)) >>> wid.collide_widget(wid2) True >>> wid2.pos = (55, 55) >>> wid.collide_widget(wid2) False
- export_to_png(filename, *args, **kwargs)¶
Saves an image of the widget and its children in png format at the specified filename. Works by removing the widget canvas from its parent, rendering to an
Fbo, and callingsave().Note
The image includes only this widget and its children. If you want to include widgets elsewhere in the tree, you must call
export_to_png()from their common parent, or usescreenshot()to capture the whole window.Note
The image will be saved in png format, you should include the extension in your filename.
New in version 1.9.0.
- Parameters:
- filename: str
The filename with which to save the png.
- scale: float
The amount by which to scale the saved image, defaults to 1.
New in version 1.11.0.
- get_parent_window()¶
Return the parent window.
- Returns:
Instance of the parent window. Can be a
WindowBaseorWidget.
- get_root_window()¶
Return the root window.
- Returns:
Instance of the root window. Can be a
WindowBaseorWidget.
- get_window_matrix(x=0, y=0)¶
Calculate the transformation matrix to convert between window and widget coordinates.
- Parameters:
- x: float, defaults to 0
Translates the matrix on the x axis.
- y: float, defaults to 0
Translates the matrix on the y axis.
- on_motion(etype, me)¶
Called when a motion event is received.
- Parameters:
- etype: str
Event type, one of “begin”, “update” or “end”
- me:
MotionEvent Received motion event
- Returns:
bool True to stop event dispatching
New in version 2.1.0.
Warning
This is an experimental method and it remains so while this warning is present.
- on_touch_down(touch)¶
Receive a touch down event.
- Parameters:
- touch:
MotionEventclass Touch received. The touch is in parent coordinates. See
relativelayoutfor a discussion on coordinate systems.
- touch:
- Returns:
bool If True, the dispatching of the touch event will stop. If False, the event will continue to be dispatched to the rest of the widget tree.
- on_touch_move(touch)¶
Receive a touch move event. The touch is in parent coordinates.
See
on_touch_down()for more information.
- on_touch_up(touch)¶
Receive a touch up event. The touch is in parent coordinates.
See
on_touch_down()for more information.
- property proxy_ref¶
Return a proxy reference to the widget, i.e. without creating a reference to the widget. See weakref.proxy for more information.
New in version 1.7.2.
- register_for_motion_event(type_id, widget=None)¶
Register to receive motion events of type_id.
Override
on_motion()or bind to on_motion event to handle the incoming motion events.- Parameters:
- type_id: str
Motion event type id (eg. “touch”, “hover”, etc.)
- widget: Widget
Child widget or self if omitted
New in version 2.1.0.
Note
Method can be called multiple times with the same arguments.
Warning
This is an experimental method and it remains so while this warning is present.
- remove_widget(widget)¶
Remove a widget from the children of this widget.
- Parameters:
- widget:
Widget Widget to remove from our children list.
- widget:
>>> from kivy.uix.button import Button >>> root = Widget() >>> button = Button() >>> root.add_widget(button) >>> root.remove_widget(button)
- to_local(x, y, relative=False)¶
Transform parent coordinates to local (current widget) coordinates.
See
relativelayoutfor details on the coordinate systems.- Parameters:
- relative: bool, defaults to False
Change to True if you want to translate coordinates to relative widget coordinates.
- to_parent(x, y, relative=False)¶
Transform local (current widget) coordinates to parent coordinates.
See
relativelayoutfor details on the coordinate systems.- Parameters:
- relative: bool, defaults to False
Change to True if you want to translate relative positions from a widget to its parent coordinates.
- to_widget(x, y, relative=False)¶
Convert the coordinate from window to local (current widget) coordinates.
See
relativelayoutfor details on the coordinate systems.
- to_window(x, y, initial=True, relative=False)¶
If
initialis True, the default, it transforms parent coordinates to window coordinates. Otherwise, it transforms local (current widget) coordinates to window coordinates.See
relativelayoutfor details on the coordinate systems.
- unregister_for_motion_event(type_id, widget=None)¶
Unregister to receive motion events of type_id.
- Parameters:
- type_id: str
Motion event type id (eg. “touch”, “hover”, etc.)
- widget: Widget
Child widget or self if omitted
New in version 2.1.0.
Note
Method can be called multiple times with the same arguments.
Warning
This is an experimental method and it remains so while this warning is present.
- walk(restrict=False, loopback=False)¶
Iterator that walks the widget tree starting with this widget and goes forward returning widgets in the order in which layouts display them.
- Parameters:
- restrict: bool, defaults to False
If True, it will only iterate through the widget and its children (or children of its children etc.). Defaults to False.
- loopback: bool, defaults to False
If True, when the last widget in the tree is reached, it’ll loop back to the uppermost root and start walking until we hit this widget again. Naturally, it can only loop back when restrict is False. Defaults to False.
- Returns:
A generator that walks the tree, returning widgets in the forward layout order.
For example, given a tree with the following structure:
GridLayout: Button BoxLayout: id: box Widget Button Widget
walking this tree:
>>> # Call walk on box with loopback True, and restrict False >>> [type(widget) for widget in box.walk(loopback=True)] [<class 'BoxLayout'>, <class 'Widget'>, <class 'Button'>, <class 'Widget'>, <class 'GridLayout'>, <class 'Button'>] >>> # Now with loopback False, and restrict False >>> [type(widget) for widget in box.walk()] [<class 'BoxLayout'>, <class 'Widget'>, <class 'Button'>, <class 'Widget'>] >>> # Now with restrict True >>> [type(widget) for widget in box.walk(restrict=True)] [<class 'BoxLayout'>, <class 'Widget'>, <class 'Button'>]
New in version 1.9.0.
- walk_reverse(loopback=False)¶
Iterator that walks the widget tree backwards starting with the widget before this, and going backwards returning widgets in the reverse order in which layouts display them.
This walks in the opposite direction of
walk(), so a list of the tree generated withwalk()will be in reverse order compared to the list generated with this, provided loopback is True.- Parameters:
- loopback: bool, defaults to False
If True, when the uppermost root in the tree is reached, it’ll loop back to the last widget and start walking back until after we hit widget again. Defaults to False.
- Returns:
A generator that walks the tree, returning widgets in the reverse layout order.
For example, given a tree with the following structure:
GridLayout: Button BoxLayout: id: box Widget Button Widget
walking this tree:
>>> # Call walk on box with loopback True >>> [type(widget) for widget in box.walk_reverse(loopback=True)] [<class 'Button'>, <class 'GridLayout'>, <class 'Widget'>, <class 'Button'>, <class 'Widget'>, <class 'BoxLayout'>] >>> # Now with loopback False >>> [type(widget) for widget in box.walk_reverse()] [<class 'Button'>, <class 'GridLayout'>] >>> forward = [w for w in box.walk(loopback=True)] >>> backward = [w for w in box.walk_reverse(loopback=True)] >>> forward == backward[::-1] True
New in version 1.9.0.
- exception kivy.uix.widget.WidgetException¶
Bases:
ExceptionFired when the widget gets an exception.