Painter

kivy_garden.painter

Painter Widget

This package provides a widget upon which shapes can be drawn. This supports drawing a PaintCircle, PaintEllipse, PaintPolygon, PaintFreeformPolygon, and a PaintPoint using a PaintCanvasBehavior. PaintCanvasBehaviorBase is the high level controller that doesn’t know about specific shapes, only about the shape base class, PaintShape. PaintCanvasBehavior adds the specific functionality of the listed shapes.

See PaintShape for how to save shape metadata and then later reconstruct the shape.

Following is a simple example:

from kivy.uix.widget import Widget
from kivy.app import runTouchApp
from kivy.lang import Builder
from kivy.uix.behaviors.focus import FocusBehavior

class PainterWidget(PaintCanvasBehavior, FocusBehavior, Widget):

    def create_shape_with_touch(self, touch):
        shape = super(PainterWidget, self).create_shape_with_touch(touch)
        if shape is not None:
            shape.add_shape_to_canvas(self)
        return shape

    def add_shape(self, shape):
        if super(PainterWidget, self).add_shape(shape):
            shape.add_shape_to_canvas(self)
            return True
        return False


runTouchApp(Builder.load_string('''
BoxLayout:
    orientation: 'vertical'
    PainterWidget:
        draw_mode: mode.text or 'freeform'
        locked: lock.state == 'down'
        multiselect: multiselect.state == 'down'
    BoxLayout:
        size_hint_y: None
        height: "50dp"
        spacing: '20dp'
        Spinner:
            id: mode
            values: ['circle', 'ellipse', 'polygon', 'freeform', 'none']
            text: 'freeform'
        ToggleButton:
            id: lock
            text: "Lock"
        ToggleButton:
            id: multiselect
            text: "Multi-select"
'''))

To use it, select a paint shape, e.g. freeform and start drawing. Finished shapes can be dragged by their orange dot. Long clicking on any of the shape dots lets you edit the shape.

Adding shapes

Shapes can be added by either drawing them using touch, or by manually adding a shape.

When a shape needs to be created through the GUI, PaintCanvasBehaviorBase calls PaintCanvasBehaviorBase.create_shape_with_touch(), which needs to be implemented to create and return one of the possible shapes. See PaintCanvasBehavior for an example.

A shape can also be manually created using PaintShape.create_shape() and passing in the parameters. E.g.:

circle = PaintCircle.create_shape([0, 0], 5)
ellipse = PaintEllipse.create_shape([0, 0], 5, 10, 3.14)
polygon = PaintPolygon.create_shape(
    [0, 0, 300, 0, 300, 800, 0, 800], [0, 0])
point = PaintPoint.create_shape([0, 0])

Or by reconstructing it from a state dict. E.g.:

circle = PaintCircle.create_shape([0, 0], 5)
state = circle.get_state()
new_circle = PaintCircle.create_shape_from_state(state)

This only creates the shape. To add the shape to the canvas behavior do e.g.:

painter = PaintCanvasBehavior()
circle = PaintCircle.create_shape([0, 0], 5)
painter.add_shape(circle)
circle.add_shape_to_canvas(painter)

PaintShape.add_shape_to_canvas() is required to display the shape in the painter widget and it adds the graphic components to the painter’s canvas. But it can be skipped if the painter is used only as a controller and there’s no GUI active in which to display the shapes.

class kivy_garden.painter.PaintCanvasBehavior(**kwargs)

Bases: kivy_garden.painter.PaintCanvasBehaviorBase

Implements the PaintCanvasBehaviorBase to be able to draw any of the following shapes: ‘circle’, ‘ellipse’, ‘polygon’, ‘freeform’, and ‘point’. They are drawn using PaintCircle, PaintEllipse, PaintPolygon, PaintFreeformPolygon, and PaintPoint, respectively.

This is a demo class to be used as a guide for your own usage.

create_add_shape(cls_name, **inst_kwargs)

Creates a new shape instance and also adds it the painter with add_shape().

It has the same parameters and return value as create_shape().

create_shape(cls_name, **inst_kwargs)

Creates a new shape instance from the given arguments.

E.g.:

shape = painter.create_shape(
    'polygon', points=[0, 0, 300, 0, 300, 800, 0, 800])

It is the same as using PaintShape.create_shape() on the shape class.

Parameters
  • cls_name – The name of the shape class to create, e.g. "ellipse". It uses shape_cls_map to find the class to instantiate.

  • inst_kwargs – Configuration options for the new shape that will be passed as options to the class when it is instantiated.

Returns

The newly created shape instance.

create_shape_from_state(state, add=True)

Recreates a shape as given by the state and adds it to the painter with add_shape().

Parameters
Returns

The newly created shape instance.

create_shape_with_touch(touch)

Called internally whenever the user has done something with a touch such that the controller wants to create a new PaintShape to be added to the painter.

This should return a new PaintShape instance that will be added to the painter.

Parameters

touch – The touch that caused this call.

Returns

A new PaintShape instance to be added.

draw_mode

The shape to create when a user starts drawing with a touch. It can be one of 'circle', 'ellipse', 'polygon', 'freeform', 'point', 'none' and it starts drawing the corresponding shape in the painter widget.

When 'none', not shape will be drawn and only selection is possible.

shape_cls_map = {'circle': <class 'kivy_garden.painter.PaintCircle'>, 'ellipse': <class 'kivy_garden.painter.PaintEllipse'>, 'freeform': <class 'kivy_garden.painter.PaintFreeformPolygon'>, 'none': None, 'point': <class 'kivy_garden.painter.PaintPoint'>, 'polygon': <class 'kivy_garden.painter.PaintPolygon'>}

Maps draw_mode to the actual PaintShape subclass to be used for drawing when in this mode.

This can be overwritten to add support for drawing other, non-builtin, shapes.

shape_cls_name_map = {}

Automatically generated mapping that maps the names of classes provided in shape_cls_map to the actual class objects. This is used when reconstructing shapes e.g. in create_shape_from_state(), where we only have the class name in state.

class kivy_garden.painter.PaintCanvasBehaviorBase(**kwargs)

Bases: kivy._event.EventDispatcher

Abstract base class that can paint on a widget canvas. See PaintCanvasBehavior for a the implementation that can be used with touch to draw upon.

Accepted keyboard keys and their meaning

You must inherit from FocusBehavior to be able to be use the keyboard functionality.

Internal Logic

Each shape has a single point by which it is dragged. However, one can interact with other parts of the shape as determined by the shape instance. Selection happens by the controller when that point is touched. If multi-select or ctrl is held down, multiple shapes can be selected this way. The currently selected objects may be dragged by dragging any of their selection points.

First we check if a current_shape is active, if so, all touches are sent to it. On touch_up, it checks if done and if so finishes it.

Next we check if we need to select a shape by the selection points. If so, the touch will select or add to selection a shape. If no shape is near enough the selection point, the selection will be cleared when the touch moves or comes up.

Finally, if no shape is selected or active, we create a new one on up or if the mouse moves.

add_shape(shape)

Add the shape to shapes and to the painter.

Parameters

shapePaintShape instance to add.

Returns

A bool indicating whether the shape was successfully added.

check_new_shape_done(shape, state)

Checks whether the shape has been finished drawing. This is how the controller decides whether the shape can be considered done and moved on from.

The controller calls this with the current_shape at every touch to figure out if the shape is done and ready to be added to shapes.

Parameters
  • shape – The PaintShape to check.

  • state – The touch state (internal, not sure if this will stay.)

Returns

Whether the touch is completed and fully drawn.

clear_selected_shapes()

De-selects all currently selected shapes.

create_shape_with_touch(touch)

Called internally whenever the user has done something with a touch such that the controller wants to create a new PaintShape to be added to the painter.

This should return a new PaintShape instance that will be added to the painter.

Parameters

touch – The touch that caused this call.

Returns

A new PaintShape instance to be added.

current_shape: Optional[kivy_garden.painter.PaintShape] = None

Holds shape currently being edited. Can be a finished shape, e.g. if a point is selected.

Read only.

delete_all_shapes(keep_locked_shapes=True)

Removes all currently selected shapes from shapes.

Parameters

keep_locked_shapes – Whether to also delete the shapes that are locked

Returns

List of the shapes that were deleted, if any.

delete_selected_shapes()

De-selects and removes all currently selected shapes from shapes.

Returns

List of the shapes that were deleted, if any.

deselect_shape(shape)

De-selects the shape and removes it from selected_shapes.

Parameters

shapePaintShape instance to de-select.

Returns

A bool indicating whether the shape was successfully de-selected.

do_long_touch(touch, *largs)

Handles a long touch by the user.

duplicate_selected_shapes()

Duplicates all currently selected_shapes and adds them to shapes.

The new shapes are added a slight offset from the original shape positions.

Returns

The original selected_shapes that were duplicated.

duplicate_shape(shape)

Duplicate the shape and adds it to shapes.

The new shapes is added at a slight offset from the original shape position.

Parameters

shapePaintShape to duplicate.

Returns

The new PaintShape that was created.

end_shape_interaction()

Called by the painter to end interacting with the current_shape.

finish_current_shape()

Finishes the current shape being drawn and adds it to shapes.

Returns True if there was a unfinished shape that was finished.

get_closest_selection_point_shape(x, y)

Given a position, it returns the shape whose selection point is the closest to this position among all the shapes.

This is how we find the shape to drag around and select it. Each shape has a single selection point by which it can be selected and dragged. We find the shape with the closest selection point among all the shapes, and that shape is returned.

Parameters
  • x – The x pos.

  • y – The y pos.

Returns

The PaintShape that is the closest as described.

get_closest_shape(x, y)

Given a position, it returns the shape that has a point on its boundary that is the closest to this position, among all the shapes.

This is how we find the shape on e.g. a long touch when we start editing the shape. We find the closest point among all the boundary points of all the shapes, and the shape with the closest point is returned.

Parameters
  • x – The x pos.

  • y – The y pos.

Returns

The PaintShape that is the closest as described.

keyboard_on_key_down(window, keycode, text, modifiers)
keyboard_on_key_up(window, keycode)
lock_shape(shape)

Locks the shape so that it cannot be interacted with by touch.

Parameters

shape – The PaintShape to lock. It should be in shapes.

Returns

Whether the shape was successfully locked.

locked: bool

It locks all added shapes so they cannot be interacted with.

Setting it to True will finish any shapes being drawn and unselect them.

long_touch_delay: float = 0.7

Minimum delay after a touch down before a touch up, for the touch to be considered a long touch.

min_touch_dist: float = 10

Min distance of a touch to point for it to count as close enough to be able to select that point. It’s in kivy.metrics.dp() units.

multiselect: bool

Whether multiple shapes can be selected by holding down control.

Holding down the control key has the same effect as multiselect being True.

on_touch_down(touch)
on_touch_move(touch)
on_touch_up(touch)
remove_shape(shape)

Removes the shape from the painter and from shapes.

Parameters

shapePaintShape instance to remove.

Returns

A bool indicating whether the shape was successfully removed.

reorder_shape(shape, before_shape=None)

Move the shape up or down in depth, in terms of the shape order in shapes and in the canvas.

This effect whether a shape will obscure another.

Parameters
  • shapePaintShape instance to move from it’s current position.

  • before_shape – Where to add it. If None, it is moved at the end, otherwise it is moved after the given PaintShape in shapes.

select_shape(shape)

Selects the shape and adds it to selected_shapes.

Parameters

shapePaintShape instance to select.

Returns

A bool indicating whether the shape was successfully selected.

selected_shapes: List[kivy_garden.painter.PaintShape]

A list of PaintShape instances currently selected in the painting widget.

shapes: List[kivy_garden.painter.PaintShape]

A list of PaintShape instances currently added to the painting widget.

start_shape_interaction(shape, pos=None)

Called by the painter to start interacting with a shape e.g. when a touch was close to a point of the shape.

This adds the shape to current_shape.

Parameters
  • shape – The shape to start interacting with.

  • pos – The mouse pos, if available that caused the interaction.

unlock_shape(shape)

Unlocks the shape so that it can be interacted with again by touch.

Parameters

shape – The PaintShape to unlock. It should be in shapes.

Returns

Whether the shape was successfully unlocked.

class kivy_garden.painter.PaintCircle(**kwargs)

Bases: kivy_garden.painter.PaintShape

A shape that represents a circle.

The shape has a single point by which it can be dragged or the radius expanded.

add_area_graphics_to_canvas(name, canvas)

Add graphics instructions to canvas such that the inside area of the shapes will be colored in with the color instruction below it in the canvas.

See the examples how to use it.

Parameters
  • name – The group name given to the graphics instructions when they are added to the canvas. This is how the canvas can remove them all at once.

  • canvas – The canvas to which to add the instructions.

add_shape_to_canvas(paint_widget)

Must be called on the shape to add it to the canvas on which the shape should be displayed when it’s being drawn.

If this is never called, the shape won’t ever be shown visually.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def add_shape(self, shape):
        if super(PainterWidget, self).add_shape(shape):
            shape.add_shape_to_canvas(self)
            return True
        return False
Parameters

paint_widget – A Widget to who’s canvas the graphics instructions displaying the shapes will be added.

Returns

True if it was added, otherwise False e.g. if it has previously already been added.

center

A 2-tuple containing the center position of the circle.

This can be set, and the shape will translate itself to the new center pos.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

classmethod create_shape(center=(0, 0), radius=10.0, **inst_kwargs)

Creates a new circle instance from the given arguments.

E.g.:

shape = PaintCircle.create_shape([0, 0], 5)
Parameters
  • center – The center of the circle.

  • radius – The radius of the circle.

  • inst_kwargs – Configuration options for the new shape that will be passed as options to the class when it is instantiated.

Returns

The newly created circle instance.

deselect()

(internal) Called by PaintCanvasBehaviorBase.deselect_shape() to de-select the shape.

Don’t call this directly.

Returns

True if we just de- selected the shape, otherwise False if it was already de- selected.

ellipse_color_inst = None

(internal) The color instruction coloring the perimeter.

get_interaction_point_dist(pos)

Returns the minimum of the distance to any point in the shape that we can interact with. These are all the points that can be manipulated e.g. to change the shape size or orientation etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no interaction points available.

get_selection_point_dist(pos)

Returns the minimum of the distance to a selection point that we can interact with. Selections points is the differently colored point (orange) by which the shape can be dragged or selected etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no selection point available.

get_state(state=None)

Returns a configuration dictionary that can be used to duplicate the shape with all the configuration values of the shape. See PaintShape.

Parameters

state – A dict, or None. If not None, the config data will be added to the dict, otherwise a new dict is created and returned.

Returns

A dict with all the config data of the shape.

handle_touch_down(touch, opos=None)

(internal) called by PaintCanvasBehaviorBase to handle a touch down that is relevant to this shape.

Parameters
  • touch – The kivy touch.

  • opos – The original starting position of the touch e.g. touch.opos if the touch has moved before this was called.

handle_touch_move(touch)

(internal) called by PaintCanvasBehaviorBase to handle a touch move that is relevant to this shape.

Parameters

touch – The kivy touch.

handle_touch_up(touch, outside=False)

(internal) called by PaintCanvasBehaviorBase to handle a touch up that is relevant to this shape.

Parameters
is_valid = True

Whether the shape is in a valid state. If finish() when not in a valid state, PaintCanvasBehavior will not keep the shape.

Read only.

lock()

(internal) Called by PaintCanvasBehaviorBase.lock_shape() to lock the shape.

Don’t call this directly.

Returns

True if we just locked the shape, otherwise False if it was already locked.

perim_ellipse_inst = None

(internal) The graphics instruction representing the perimeter.

radius

The radius of the circle.

This can be set, and the shape will resize itself to the new size.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

ready_to_finish = True

Whether the shape is ready to be finished. Used by PaintCanvasBehavior to decide whether to finish the shape. See finish().

Read only.

remove_shape_from_canvas()

Must be called on the shape to remove it from the canvas to which it has previously been added with add_shape_to_canvas().

If this is never called, the shape won’t be removed and will remain visible.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def remove_shape(self, shape):
        if super(PainterWidget, self).remove_shape(shape):
            shape.remove_shape_from_canvas()
            return True
        return False
Returns

paint_widget to which the shapes has previously been added, if it was added previously, otherwise None.

rescale(scale)

Rescales the all the perimeter points/lines distance from the center of the shape by the fractional amount scale.

E.g. if a point on the perimeter is at distance X from the center of the shape, after this function it’ll be at distance scale * X from the center of the shape.

Parameters

scale – amount by which to scale

select()

(internal) Called by PaintCanvasBehaviorBase.select_shape() to select the shape.

Don’t call this directly.

Returns

True if we just selected the shape, otherwise False if it was already selected.

selection_point_inst = None

(internal) The graphics instruction representing the selection point.

start_interaction(pos)

(internal) called by PaintCanvasBehaviorBase.start_shape_interaction() when it wants to start interacting with a shape, e.g. if there was a long touch near the shape.

Parameters

pos – The position of the touch that caused this interaction.

Returns

Whether we started interacting. False if e.g. it was already interacting.

stop_interaction()

(internal) called by PaintCanvasBehaviorBase.end_shape_interaction() when it wants to stop interacting with a shape.

Returns

Whether we ended interacting. False if e.g. we were not already interacting.

translate(dpos=None, pos=None)

Translates the shape by dpos or to be at pos.

This should only be called

Parameters
  • dpos – The change in x, y by which to translate the shape, if not None.

  • pos – The final position to which to set the shape, if not None.

Returns

Whether the shape was successfully translated.

unlock()

(internal) Called by PaintCanvasBehaviorBase.unlock_shape() to unlock the shape.

Don’t call this directly.

Returns

True if we just un locked the shape, otherwise False if it was already un locked.

class kivy_garden.painter.PaintEllipse(**kwargs)

Bases: kivy_garden.painter.PaintShape

A shape that represents an ellipse.

The shape has a single point by which it can be dragged or the radius expanded.

add_area_graphics_to_canvas(name, canvas)

Add graphics instructions to canvas such that the inside area of the shapes will be colored in with the color instruction below it in the canvas.

See the examples how to use it.

Parameters
  • name – The group name given to the graphics instructions when they are added to the canvas. This is how the canvas can remove them all at once.

  • canvas – The canvas to which to add the instructions.

add_shape_to_canvas(paint_widget)

Must be called on the shape to add it to the canvas on which the shape should be displayed when it’s being drawn.

If this is never called, the shape won’t ever be shown visually.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def add_shape(self, shape):
        if super(PainterWidget, self).add_shape(shape):
            shape.add_shape_to_canvas(self)
            return True
        return False
Parameters

paint_widget – A Widget to who’s canvas the graphics instructions displaying the shapes will be added.

Returns

True if it was added, otherwise False e.g. if it has previously already been added.

angle

The angle in radians by which the x-axis is rotated counter clockwise. This allows the ellipse to be rotated rather than just be aligned to the default axes.

This can be set, and the shape will reorient itself to the new size.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

center

A 2-tuple containing the center position of the ellipse.

This can be set, and the shape will translate itself to the new center pos.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

classmethod create_shape(center=(0, 0), radius_x=10.0, radius_y=15.0, angle=0, **inst_kwargs)

Creates a new ellipse instance from the given arguments.

E.g.:

shape = PaintEllipse.create_shape([0, 0], 5, 10, 0)
Parameters
  • center – The center of the ellipse.

  • radius_x – The radius_x of the ellipse.

  • radius_y – The radius_y of the ellipse.

  • angle – The angle of the ellipse in radians.

  • inst_kwargs – Configuration options for the new shape that will be passed as options to the class when it is instantiated.

Returns

The newly created ellipse instance.

deselect()

(internal) Called by PaintCanvasBehaviorBase.deselect_shape() to de-select the shape.

Don’t call this directly.

Returns

True if we just de- selected the shape, otherwise False if it was already de- selected.

ellipse_color_inst = None

(internal) The color instruction coloring the perimeter.

get_interaction_point_dist(pos)

Returns the minimum of the distance to any point in the shape that we can interact with. These are all the points that can be manipulated e.g. to change the shape size or orientation etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no interaction points available.

get_selection_point_dist(pos)

Returns the minimum of the distance to a selection point that we can interact with. Selections points is the differently colored point (orange) by which the shape can be dragged or selected etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no selection point available.

get_state(state=None)

Returns a configuration dictionary that can be used to duplicate the shape with all the configuration values of the shape. See PaintShape.

Parameters

state – A dict, or None. If not None, the config data will be added to the dict, otherwise a new dict is created and returned.

Returns

A dict with all the config data of the shape.

handle_touch_down(touch, opos=None)

(internal) called by PaintCanvasBehaviorBase to handle a touch down that is relevant to this shape.

Parameters
  • touch – The kivy touch.

  • opos – The original starting position of the touch e.g. touch.opos if the touch has moved before this was called.

handle_touch_move(touch)

(internal) called by PaintCanvasBehaviorBase to handle a touch move that is relevant to this shape.

Parameters

touch – The kivy touch.

handle_touch_up(touch, outside=False)

(internal) called by PaintCanvasBehaviorBase to handle a touch up that is relevant to this shape.

Parameters
is_valid = True

Whether the shape is in a valid state. If finish() when not in a valid state, PaintCanvasBehavior will not keep the shape.

Read only.

lock()

(internal) Called by PaintCanvasBehaviorBase.lock_shape() to lock the shape.

Don’t call this directly.

Returns

True if we just locked the shape, otherwise False if it was already locked.

perim_ellipse_inst = None

(internal) The graphics instruction representing the perimeter.

radius_x

The x-radius of the circle.

This can be set, and the shape will resize itself to the new size.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

radius_y

The y-radius of the circle.

This can be set, and the shape will resize itself to the new size.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

ready_to_finish = True

Whether the shape is ready to be finished. Used by PaintCanvasBehavior to decide whether to finish the shape. See finish().

Read only.

remove_shape_from_canvas()

Must be called on the shape to remove it from the canvas to which it has previously been added with add_shape_to_canvas().

If this is never called, the shape won’t be removed and will remain visible.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def remove_shape(self, shape):
        if super(PainterWidget, self).remove_shape(shape):
            shape.remove_shape_from_canvas()
            return True
        return False
Returns

paint_widget to which the shapes has previously been added, if it was added previously, otherwise None.

rescale(scale)

Rescales the all the perimeter points/lines distance from the center of the shape by the fractional amount scale.

E.g. if a point on the perimeter is at distance X from the center of the shape, after this function it’ll be at distance scale * X from the center of the shape.

Parameters

scale – amount by which to scale

rotate_inst = None

(internal) The graphics instruction that rotates the ellipse.

select()

(internal) Called by PaintCanvasBehaviorBase.select_shape() to select the shape.

Don’t call this directly.

Returns

True if we just selected the shape, otherwise False if it was already selected.

selection_point_inst = None

(internal) The graphics instruction representing the selection point on the first axis.

selection_point_inst2 = None

(internal) The graphics instruction representing the second selection point for the second axis.

start_interaction(pos)

(internal) called by PaintCanvasBehaviorBase.start_shape_interaction() when it wants to start interacting with a shape, e.g. if there was a long touch near the shape.

Parameters

pos – The position of the touch that caused this interaction.

Returns

Whether we started interacting. False if e.g. it was already interacting.

stop_interaction()

(internal) called by PaintCanvasBehaviorBase.end_shape_interaction() when it wants to stop interacting with a shape.

Returns

Whether we ended interacting. False if e.g. we were not already interacting.

translate(dpos=None, pos=None)

Translates the shape by dpos or to be at pos.

This should only be called

Parameters
  • dpos – The change in x, y by which to translate the shape, if not None.

  • pos – The final position to which to set the shape, if not None.

Returns

Whether the shape was successfully translated.

unlock()

(internal) Called by PaintCanvasBehaviorBase.unlock_shape() to unlock the shape.

Don’t call this directly.

Returns

True if we just un locked the shape, otherwise False if it was already un locked.

class kivy_garden.painter.PaintFreeformPolygon(**kwargs)

Bases: kivy_garden.painter.PaintPolygon

A shape that represents a polygon.

As opposed to PaintPolygon, points are added to shape during the first touch, while the user holds the touch down and moves the touch, and the shape is finished when the user release the touch.

Otherwise, it’s the same as PaintPolygon.

handle_touch_down(touch, opos=None)

(internal) called by PaintCanvasBehaviorBase to handle a touch down that is relevant to this shape.

Parameters
  • touch – The kivy touch.

  • opos – The original starting position of the touch e.g. touch.opos if the touch has moved before this was called.

handle_touch_move(touch)

(internal) called by PaintCanvasBehaviorBase to handle a touch move that is relevant to this shape.

Parameters

touch – The kivy touch.

handle_touch_up(touch, outside=False)

(internal) called by PaintCanvasBehaviorBase to handle a touch up that is relevant to this shape.

Parameters
class kivy_garden.painter.PaintPoint(**kwargs)

Bases: kivy_garden.painter.PaintShape

A shape that represents a single point and it can be dragged by this point.

add_area_graphics_to_canvas(name, canvas)

Add graphics instructions to canvas such that the inside area of the shapes will be colored in with the color instruction below it in the canvas.

See the examples how to use it.

Parameters
  • name – The group name given to the graphics instructions when they are added to the canvas. This is how the canvas can remove them all at once.

  • canvas – The canvas to which to add the instructions.

add_shape_to_canvas(paint_widget)

Must be called on the shape to add it to the canvas on which the shape should be displayed when it’s being drawn.

If this is never called, the shape won’t ever be shown visually.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def add_shape(self, shape):
        if super(PainterWidget, self).add_shape(shape):
            shape.add_shape_to_canvas(self)
            return True
        return False
Parameters

paint_widget – A Widget to who’s canvas the graphics instructions displaying the shapes will be added.

Returns

True if it was added, otherwise False e.g. if it has previously already been added.

circle_inst = None

(internal) The graphics instruction representing the circle around the point.

color_inst = None

(internal) The color instruction coloring the circle and point.

classmethod create_shape(position=(0, 0), **inst_kwargs)

Creates a new point instance from the given arguments.

E.g.:

shape = PaintPoint.create_shape([0, 0])
Parameters
  • position – The position of the circle.

  • inst_kwargs – Configuration options for the new shape that will be passed as options to the class when it is instantiated.

Returns

The newly created point instance.

deselect()

(internal) Called by PaintCanvasBehaviorBase.deselect_shape() to de-select the shape.

Don’t call this directly.

Returns

True if we just de- selected the shape, otherwise False if it was already de- selected.

get_interaction_point_dist(pos)

Returns the minimum of the distance to any point in the shape that we can interact with. These are all the points that can be manipulated e.g. to change the shape size or orientation etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no interaction points available.

get_selection_point_dist(pos)

Returns the minimum of the distance to a selection point that we can interact with. Selections points is the differently colored point (orange) by which the shape can be dragged or selected etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no selection point available.

get_state(state=None)

Returns a configuration dictionary that can be used to duplicate the shape with all the configuration values of the shape. See PaintShape.

Parameters

state – A dict, or None. If not None, the config data will be added to the dict, otherwise a new dict is created and returned.

Returns

A dict with all the config data of the shape.

handle_touch_down(touch, opos=None)

(internal) called by PaintCanvasBehaviorBase to handle a touch down that is relevant to this shape.

Parameters
  • touch – The kivy touch.

  • opos – The original starting position of the touch e.g. touch.opos if the touch has moved before this was called.

handle_touch_move(touch)

(internal) called by PaintCanvasBehaviorBase to handle a touch move that is relevant to this shape.

Parameters

touch – The kivy touch.

handle_touch_up(touch, outside=False)

(internal) called by PaintCanvasBehaviorBase to handle a touch up that is relevant to this shape.

Parameters
is_valid = True

Whether the shape is in a valid state. If finish() when not in a valid state, PaintCanvasBehavior will not keep the shape.

Read only.

lock()

(internal) Called by PaintCanvasBehaviorBase.lock_shape() to lock the shape.

Don’t call this directly.

Returns

True if we just locked the shape, otherwise False if it was already locked.

point_inst = None

(internal) The graphics instruction representing the point.

position

A 2-tuple containing the position of the point.

This can be set, and the shape will translate itself to the new pos.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

ready_to_finish = True

Whether the shape is ready to be finished. Used by PaintCanvasBehavior to decide whether to finish the shape. See finish().

Read only.

remove_shape_from_canvas()

Must be called on the shape to remove it from the canvas to which it has previously been added with add_shape_to_canvas().

If this is never called, the shape won’t be removed and will remain visible.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def remove_shape(self, shape):
        if super(PainterWidget, self).remove_shape(shape):
            shape.remove_shape_from_canvas()
            return True
        return False
Returns

paint_widget to which the shapes has previously been added, if it was added previously, otherwise None.

rescale(scale)

Rescales the all the perimeter points/lines distance from the center of the shape by the fractional amount scale.

E.g. if a point on the perimeter is at distance X from the center of the shape, after this function it’ll be at distance scale * X from the center of the shape.

Parameters

scale – amount by which to scale

select()

(internal) Called by PaintCanvasBehaviorBase.select_shape() to select the shape.

Don’t call this directly.

Returns

True if we just selected the shape, otherwise False if it was already selected.

start_interaction(pos)

(internal) called by PaintCanvasBehaviorBase.start_shape_interaction() when it wants to start interacting with a shape, e.g. if there was a long touch near the shape.

Parameters

pos – The position of the touch that caused this interaction.

Returns

Whether we started interacting. False if e.g. it was already interacting.

stop_interaction()

(internal) called by PaintCanvasBehaviorBase.end_shape_interaction() when it wants to stop interacting with a shape.

Returns

Whether we ended interacting. False if e.g. we were not already interacting.

translate(dpos=None, pos=None)

Translates the shape by dpos or to be at pos.

This should only be called

Parameters
  • dpos – The change in x, y by which to translate the shape, if not None.

  • pos – The final position to which to set the shape, if not None.

Returns

Whether the shape was successfully translated.

unlock()

(internal) Called by PaintCanvasBehaviorBase.unlock_shape() to unlock the shape.

Don’t call this directly.

Returns

True if we just un locked the shape, otherwise False if it was already un locked.

class kivy_garden.painter.PaintPolygon(**kwargs)

Bases: kivy_garden.painter.PaintShape

A shape that represents a polygon.

Points are added to the shape one touch down at a time and to finish the shape, one double clicks.

The shape has a single point by which it can be dragged. All the points that make up the polygon, however, can be edited once the shape is selected.

add_area_graphics_to_canvas(name, canvas)

Add graphics instructions to canvas such that the inside area of the shapes will be colored in with the color instruction below it in the canvas.

See the examples how to use it.

Parameters
  • name – The group name given to the graphics instructions when they are added to the canvas. This is how the canvas can remove them all at once.

  • canvas – The canvas to which to add the instructions.

add_shape_to_canvas(paint_widget)

Must be called on the shape to add it to the canvas on which the shape should be displayed when it’s being drawn.

If this is never called, the shape won’t ever be shown visually.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def add_shape(self, shape):
        if super(PainterWidget, self).add_shape(shape):
            shape.add_shape_to_canvas(self)
            return True
        return False
Parameters

paint_widget – A Widget to who’s canvas the graphics instructions displaying the shapes will be added.

Returns

True if it was added, otherwise False e.g. if it has previously already been added.

classmethod create_shape(points=(), selection_point=(), **inst_kwargs)

Creates a new polygon instance from the given arguments.

E.g.:

shape = PaintPolygon.create_shape(
    [0, 0, 300, 0, 300, 800, 0, 800], [0, 0])
Parameters
  • points – The list of points of the polygon.

  • selection_point – The selection_point of the polygon.

  • inst_kwargs – Configuration options for the new shape that will be passed as options to the class when it is instantiated.

Returns

The newly created polygon instance.

deselect()

(internal) Called by PaintCanvasBehaviorBase.deselect_shape() to de-select the shape.

Don’t call this directly.

Returns

True if we just de- selected the shape, otherwise False if it was already de- selected.

finish()

Called by PaintCanvasBehaviorBase.finish_current_shape() when it wants to finish the shape and possibly add it to the PaintCanvasBehaviorBase.shapes.

This needs to be called after a shape is constructed manually before it is added with PaintCanvasBehaviorBase.add_shape(). See PaintCanvasBehavior for an example.

Returns

True if we just finished the shape, otherwise False if it was already finished.

get_interaction_point_dist(pos)

Returns the minimum of the distance to any point in the shape that we can interact with. These are all the points that can be manipulated e.g. to change the shape size or orientation etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no interaction points available.

get_selection_point_dist(pos)

Returns the minimum of the distance to a selection point that we can interact with. Selections points is the differently colored point (orange) by which the shape can be dragged or selected etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no selection point available.

get_state(state=None)

Returns a configuration dictionary that can be used to duplicate the shape with all the configuration values of the shape. See PaintShape.

Parameters

state – A dict, or None. If not None, the config data will be added to the dict, otherwise a new dict is created and returned.

Returns

A dict with all the config data of the shape.

handle_touch_down(touch, opos=None)

(internal) called by PaintCanvasBehaviorBase to handle a touch down that is relevant to this shape.

Parameters
  • touch – The kivy touch.

  • opos – The original starting position of the touch e.g. touch.opos if the touch has moved before this was called.

handle_touch_move(touch)

(internal) called by PaintCanvasBehaviorBase to handle a touch move that is relevant to this shape.

Parameters

touch – The kivy touch.

handle_touch_up(touch, outside=False)

(internal) called by PaintCanvasBehaviorBase to handle a touch up that is relevant to this shape.

Parameters
is_valid = False

Whether the shape is in a valid state. If finish() when not in a valid state, PaintCanvasBehavior will not keep the shape.

Read only.

lock()

(internal) Called by PaintCanvasBehaviorBase.lock_shape() to lock the shape.

Don’t call this directly.

Returns

True if we just locked the shape, otherwise False if it was already locked.

perim_close_inst = None

(internal) The graphics instruction representing the closing of the perimeter.

perim_color_inst = None

(internal) The color instruction coloring the perimeter.

perim_line_inst = None

(internal) The graphics instruction representing the perimeter.

perim_points_inst = None

(internal) The graphics instruction representing the perimeter points.

points

A list of points (x1, y1, x2, y2, …) that make up the perimeter of the polygon.

There must be at least 3 points for the shape to be is_valid. The shape auto-closes so the last point doesn’t have to be the same as the first.

This can be set, and the shape will properly update. However, if changed manually, selection_point should also be changed to have a corresponding point in points.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

ready_to_finish = False

Whether the shape is ready to be finished. Used by PaintCanvasBehavior to decide whether to finish the shape. See finish().

Read only.

remove_shape_from_canvas()

Must be called on the shape to remove it from the canvas to which it has previously been added with add_shape_to_canvas().

If this is never called, the shape won’t be removed and will remain visible.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def remove_shape(self, shape):
        if super(PainterWidget, self).remove_shape(shape):
            shape.remove_shape_from_canvas()
            return True
        return False
Returns

paint_widget to which the shapes has previously been added, if it was added previously, otherwise None.

rescale(scale)

Rescales the all the perimeter points/lines distance from the center of the shape by the fractional amount scale.

E.g. if a point on the perimeter is at distance X from the center of the shape, after this function it’ll be at distance scale * X from the center of the shape.

Parameters

scale – amount by which to scale

select()

(internal) Called by PaintCanvasBehaviorBase.select_shape() to select the shape.

Don’t call this directly.

Returns

True if we just selected the shape, otherwise False if it was already selected.

selection_point

A 2-tuple indicating the position of the selection point.

This can be set, and the shape will properly update. However, if changed manually, points should contain a corresponding point at this pos by which it is selected.

This is read only while a user is interacting with the shape with touch, or if the shape is not finished.

selection_point_inst = None

(internal) The graphics instruction representing the selection point.

set_valid()

Called internally after the shape potentially is_valid, to set is_valid in case the shape is now valid.

This needs to be called after a shape is constructed manually before it is added with PaintCanvasBehaviorBase.add_shape(). See PaintCanvasBehavior for an example.

start_interaction(pos)

(internal) called by PaintCanvasBehaviorBase.start_shape_interaction() when it wants to start interacting with a shape, e.g. if there was a long touch near the shape.

Parameters

pos – The position of the touch that caused this interaction.

Returns

Whether we started interacting. False if e.g. it was already interacting.

stop_interaction()

(internal) called by PaintCanvasBehaviorBase.end_shape_interaction() when it wants to stop interacting with a shape.

Returns

Whether we ended interacting. False if e.g. we were not already interacting.

translate(dpos=None, pos=None)

Translates the shape by dpos or to be at pos.

This should only be called

Parameters
  • dpos – The change in x, y by which to translate the shape, if not None.

  • pos – The final position to which to set the shape, if not None.

Returns

Whether the shape was successfully translated.

unlock()

(internal) Called by PaintCanvasBehaviorBase.unlock_shape() to unlock the shape.

Don’t call this directly.

Returns

True if we just un locked the shape, otherwise False if it was already un locked.

class kivy_garden.painter.PaintShape(line_color=(0, 1, 0, 1), line_color_locked=(0.4, 0.56, 0.36, 1), selection_point_color=(1, 0.5, 0.31, 1), **kwargs)

Bases: kivy._event.EventDispatcher

Base class for shapes used by PaintCanvasBehavior when creating new shapes when drawing.

All the data that configures a shape can be gotten by calling get_state(). The shape can then be re-created by creating the shape and calling set_state().

For example:

shape = PaintCircle(...)
state = shape.get_state()
my_yaml.save_config(filename, state)

# then later
state = my_yaml.load_file(filename)
shape = PaintCircle()
shape.set_state(state)
shape.set_valid()
shape.finish()
if not shape.is_valid:
    raise ValueError(
        'Shape {} is not valid and cannot be added'.format(shape))
painter.add_shape(shape)

A shape can also be copied more directly with PaintCanvasBehaviorBase.duplicate_shape(). Or manually with e.g.:

import copy
shape = PaintCircle(...)
new_shape = copy.deepcopy(shape)
painter.add_shape(new_shape)
new_shape.translate(dpos=(15, 15))
Events
on_update:

Dispatched whenever the shape is changed in any way, e.g. translated etc. This is only dispatched once the shape is finished.

add_area_graphics_to_canvas(name, canvas)

Add graphics instructions to canvas such that the inside area of the shapes will be colored in with the color instruction below it in the canvas.

See the examples how to use it.

Parameters
  • name – The group name given to the graphics instructions when they are added to the canvas. This is how the canvas can remove them all at once.

  • canvas – The canvas to which to add the instructions.

add_shape_to_canvas(paint_widget)

Must be called on the shape to add it to the canvas on which the shape should be displayed when it’s being drawn.

If this is never called, the shape won’t ever be shown visually.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def add_shape(self, shape):
        if super(PainterWidget, self).add_shape(shape):
            shape.add_shape_to_canvas(self)
            return True
        return False
Parameters

paint_widget – A Widget to who’s canvas the graphics instructions displaying the shapes will be added.

Returns

True if it was added, otherwise False e.g. if it has previously already been added.

color_instructions = []

A list of all the color instructions used to color the shapes.

Read only.

classmethod create_shape(**inst_kwargs)

Creates a new shape instance of this class from the given arguments.

See each subclass for the shape arguments.

E.g.:

shape = PaintPolygon.create_shape(
    [0, 0, 300, 0, 300, 800, 0, 800], [0, 0])
Parameters

inst_kwargs – Configuration options for the new shape that will be passed as options to the class when it is instantiated.

Returns

The newly created shape instance.

classmethod create_shape_from_state(state)

Recreates a shape of this class using the state.

Parameters

state – the state dict as returned by get_state().

Returns

The newly created shape instance.

deselect()

(internal) Called by PaintCanvasBehaviorBase.deselect_shape() to de-select the shape.

Don’t call this directly.

Returns

True if we just de- selected the shape, otherwise False if it was already de- selected.

finish()

Called by PaintCanvasBehaviorBase.finish_current_shape() when it wants to finish the shape and possibly add it to the PaintCanvasBehaviorBase.shapes.

This needs to be called after a shape is constructed manually before it is added with PaintCanvasBehaviorBase.add_shape(). See PaintCanvasBehavior for an example.

Returns

True if we just finished the shape, otherwise False if it was already finished.

finished = False

Whether the shape has been finished drawing. See finish().

Read only.

get_interaction_point_dist(pos)

Returns the minimum of the distance to any point in the shape that we can interact with. These are all the points that can be manipulated e.g. to change the shape size or orientation etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no interaction points available.

get_selection_point_dist(pos)

Returns the minimum of the distance to a selection point that we can interact with. Selections points is the differently colored point (orange) by which the shape can be dragged or selected etc.

Parameters

pos – The position to which to compute the min point distance.

Returns

The minimum distance to pos, or a very large number if there’s no selection point available.

get_state(state=None)

Returns a configuration dictionary that can be used to duplicate the shape with all the configuration values of the shape. See PaintShape.

Parameters

state – A dict, or None. If not None, the config data will be added to the dict, otherwise a new dict is created and returned.

Returns

A dict with all the config data of the shape.

graphics_name = ''

The group name given to all the canvas instructions added to the instruction_group. These are the lines, points etc.

Read only and is automatically set when the shape is created.

handle_touch_down(touch, opos=None)

(internal) called by PaintCanvasBehaviorBase to handle a touch down that is relevant to this shape.

Parameters
  • touch – The kivy touch.

  • opos – The original starting position of the touch e.g. touch.opos if the touch has moved before this was called.

handle_touch_move(touch)

(internal) called by PaintCanvasBehaviorBase to handle a touch move that is relevant to this shape.

Parameters

touch – The kivy touch.

handle_touch_up(touch, outside=False)

(internal) called by PaintCanvasBehaviorBase to handle a touch up that is relevant to this shape.

Parameters
hide_shape_in_canvas()

Hides the shape so that it is not visible in the widget to which it was added with add_shape_to_canvas().

instruction_group = None

A InstructionGroup instance to which all the canvas instructions that the shape displays is added to.

This is added to the host paint_widget by add_shape_to_canvas().

Read only.

interacting = False

Whether PaintCanvasBehavior is currently interacting with this shape e.g. in PaintCanvasBehavior.current_shape. See start_interaction().

Read only.

is_valid = False

Whether the shape is in a valid state. If finish() when not in a valid state, PaintCanvasBehavior will not keep the shape.

Read only.

line_color = (0, 1, 0, 1)

The line color of lines and/or points shown.

line_color_locked = (0.4, 0.56, 0.36, 1)

The line color of lines and/or points shown when the shape is locked.

line_width

The line width of lines shown, in dp().

lock()

(internal) Called by PaintCanvasBehaviorBase.lock_shape() to lock the shape.

Don’t call this directly.

Returns

True if we just locked the shape, otherwise False if it was already locked.

locked

Whether the shape is currently locked and PaintCanvasBehaviorBase won’t interact with it. See lock().

Read only. Call PaintCanvasBehaviorBase.lock_shape() to change.

move_to_top()

(internal) Called by PaintCanvasBehaviorBase.reorder_shape() to move the shape to the top of the canvas.

Don’t call this directly.

Returns

True if we were able to move it up..

on_update(*largs)
paint_widget = None

When the shape is added to a widget with add_shape_to_canvas(), it is the widget to which it is added.

Read only.

pointsize

The point size of points shown, in dp().

ready_to_finish = False

Whether the shape is ready to be finished. Used by PaintCanvasBehavior to decide whether to finish the shape. See finish().

Read only.

remove_shape_from_canvas()

Must be called on the shape to remove it from the canvas to which it has previously been added with add_shape_to_canvas().

If this is never called, the shape won’t be removed and will remain visible.

A typical pattern of how this is used is:

class PainterWidget(PaintCanvasBehavior, Widget):
    def remove_shape(self, shape):
        if super(PainterWidget, self).remove_shape(shape):
            shape.remove_shape_from_canvas()
            return True
        return False
Returns

paint_widget to which the shapes has previously been added, if it was added previously, otherwise None.

rescale(scale)

Rescales the all the perimeter points/lines distance from the center of the shape by the fractional amount scale.

E.g. if a point on the perimeter is at distance X from the center of the shape, after this function it’ll be at distance scale * X from the center of the shape.

Parameters

scale – amount by which to scale

select()

(internal) Called by PaintCanvasBehaviorBase.select_shape() to select the shape.

Don’t call this directly.

Returns

True if we just selected the shape, otherwise False if it was already selected.

selected = False

Whether the shape is currently selected in selected_shapes. See select().

Read only. Call PaintCanvasBehaviorBase.select_shape() to change.

selection_point_color = (1, 0.5, 0.31, 1)

The color of the point by which the shape is selected/dragged.

set_state(state)

Takes a configuration dictionary and applies it to the shape. See PaintShape and get_state().

Parameters

state – A dict with shape specific configuration values.

set_valid()

Called internally after the shape potentially is_valid, to set is_valid in case the shape is now valid.

This needs to be called after a shape is constructed manually before it is added with PaintCanvasBehaviorBase.add_shape(). See PaintCanvasBehavior for an example.

show_shape_in_canvas()

Shows the shape in the widget’s canvas. Call this after hide_shape_in_canvas() to display the shape again.

start_interaction(pos)

(internal) called by PaintCanvasBehaviorBase.start_shape_interaction() when it wants to start interacting with a shape, e.g. if there was a long touch near the shape.

Parameters

pos – The position of the touch that caused this interaction.

Returns

Whether we started interacting. False if e.g. it was already interacting.

stop_interaction()

(internal) called by PaintCanvasBehaviorBase.end_shape_interaction() when it wants to stop interacting with a shape.

Returns

Whether we ended interacting. False if e.g. we were not already interacting.

translate(dpos=None, pos=None)

Translates the shape by dpos or to be at pos.

This should only be called

Parameters
  • dpos – The change in x, y by which to translate the shape, if not None.

  • pos – The final position to which to set the shape, if not None.

Returns

Whether the shape was successfully translated.

unlock()

(internal) Called by PaintCanvasBehaviorBase.unlock_shape() to unlock the shape.

Don’t call this directly.

Returns

True if we just un locked the shape, otherwise False if it was already un locked.