Skip to content

DrawingAction

Representation of a drawing action performed on a Canvas.

For many if not most applications, the interface documented for Canvas is sufficient. However, it is also possible to directly manipulate a Canvas's stored instructions, thereby modifying the results in a non-linear fashion.

Usage

Each drawing operation that has been performed on a Canvas is represented by an object of class DrawingAction. Each drawing method has a corresponding DrawingAction subclass of the same name, except in CamelCase. For example, the line_to() method creates a LineTo object, and LineTo is a subclass of DrawingAction.

The current state of the drawing context is represented by a state object. All states are subclasses of the abstract BaseState; the simplest is State. Initially, a canvas has only one state; this initial state is always accessible via the canvas's root_state attribute.

Each state stores a list of its associated drawing actions.

import toga

canvas = toga.Canvas()

print(canvas.root_state)
# State()
print(canvas.root_state.drawing_actions)
# []

canvas.rect(0, 0, 10, 10)
canvas.stroke()

print(canvas.root_state.drawing_actions)
# [Rect(x=0, y=0, width=10, height=10),
#  Stroke(stroke_style=None, line_width=None, line_dash=None)]

When you save and then restore the state of the drawing context using a context manager (e.g., state(), stroke(), or fill()), a new state object is created and inserted into the currently active state's drawing_actions. This is possible because BaseState is itself a subclass of DrawingAction.

Continuing from the previous example:

with canvas.state():
    canvas.line_width = 10
    canvas.line_dash = [1, 2]

canvas.fill()

print(canvas.root_state.drawing_actions)
# [Rect(x=0, y=0, width=10, height=10),
#  Stroke(stroke_style=None, line_width=None, line_dash=None),
#  State(),
#  Fill(fill_rule=FillRule.NONZERO, fill_style=None)]

The actions corresponding to setting line width and line dash are contained inside the State(), like so:

root_state ─┬─ Rect
            ├─ Stroke
            ├─ State ──┬─ SetLineWidth
            └─ Fill    └─ SetLineDash

Note that the the Fill isn't inside the State, because its method was called after the context manager exited.

Accessing specific drawing actions

A state's drawing actions are a list, and can be accessed using list syntax. For example, if you wanted to access the Fill object in the previous example, you could use:

fill = canvas.root_state.drawing_actions[3]

However, this is not very practical, especially if the action of interest is nested within several states. A better way is to leverage the fact that each drawing method returns its drawing action. The line calling the fill method could be modified to:

fill = canvas.fill()

And now fill is a direct reference to the Fill object. This Fill object can then be modified as required.

The same is true even when a method is being used as a context manager, using with ... as ... syntax. For instance, the following code would bind fill, stroke, and move_to to the Fill, Stroke, and MoveTo drawing actions created by the methods called:

with canvas.fill() as fill:
    with canvas.stroke() as stroke:
        move_to = canvas.move_to(0, 0)

Modifying attributes of drawing actions

DrawingAction objects also have attributes corresponding to the equivalent method's parameters. If you modify these attributes, it will retroactively alter what is drawn on the canvas. For example, consider the following code and its output:

import toga

canvas = toga.Canvas(width=200, height=200)
with canvas.stroke() as stroke:
    canvas.move_to(50, 50)
    first_line = canvas.line_to(150, 50)
    canvas.line_to(50, 150)

Initial output

An initial set of strokes on a canvas.

Since we've saved references, we can alter the parameters of the stroke and the first line segment. After altering attributes like this, the canvas's redraw() method must be called to ensure the results are rendered on screen.

stroke.line_width = 20
first_line.y = 150

canvas.redraw()

After editing

An updated stroke path and width, after calling redraw() on the canvas.

The line has gotten wider, and the second point has moved down to a y coordinate of 150, which alters the orientation of both line segments.

Creating and adding new drawing actions

DrawingAction objects can also be created directly, and the list of DrawingAction objects on a state can be manually altered. As with altering attributes, and direct modification of the lists of drawing actions should be followed by a call to the canvas's redraw method.

An extra point could be added to the above path like so:

from toga.widgets.canvas import LineTo

new_point = LineTo(150, 50)
stroke.drawing_actions.insert(1, new_point)

canvas.redraw()

After adding a new drawing action

An updated stroke with an additional line segment, after calling redraw() on the canvas.

This example uses insert, but drawing_actions is a list, with all of a list's normal methods, including append, remove, and extend. Remember to call redraw after any such alterations.

Reference

toga.widgets.canvas.DrawingAction

Bases: ABC

A Canvas drawing operation.

Every canvas drawing method creates a DrawingAction, adds it to the currently active state, and returns it. Each argument passed to the method becomes a property of the DrawingAction, which can be modified as shown in Modifying attributes of Drawing actions.

A DrawingAction can also be created manually. Their constructors take the same arguments as the corresponding Canvas drawing method, and their classes have the same names, but capitalized.

toga.widgets.canvas.BaseState

BaseState()

Bases: DrawingAction, DrawingActionDispatch, ABC

A base class for all drawing actions that can function as state-saving context managers.

drawing_actions instance-attribute

drawing_actions: list[DrawingAction]

The list of all drawing actions contained by this state.

If you add or remove drawing actions to this list, you'll need to call Canvas.redraw() for the changes to be rendered.

toga.widgets.canvas.SetFillStyle dataclass

SetFillStyle(fill_style: ColorT = color_property())

Bases: DrawingAction

The DrawingAction representing assigning to the fill_style context attribute.

toga.widgets.canvas.SetStrokeStyle dataclass

SetStrokeStyle(stroke_style: ColorT = color_property())

Bases: DrawingAction

The DrawingAction representing assigning to the stroke_style context attribute.

toga.widgets.canvas.SetLineWidth dataclass

SetLineWidth(line_width: float)

Bases: DrawingAction

The DrawingAction representing assigning to the line_width context attribute.

toga.widgets.canvas.SetLineDash dataclass

SetLineDash(line_dash: list[float])

Bases: DrawingAction

The DrawingAction representing assigning to the line_dash context attribute.

toga.widgets.canvas.Save

Bases: DrawingAction

The DrawingAction representing the save() method.

toga.widgets.canvas.Restore

Bases: DrawingAction

The DrawingAction representing the restore() method.

toga.widgets.canvas.State dataclass

State()

Bases: BaseState

The DrawingAction representing the stateh() method. Functions as a context manager.

toga.widgets.canvas.BeginPath

Bases: DrawingAction

The DrawingAction representing the begin_path() method.

toga.widgets.canvas.ClosePath dataclass

ClosePath()

Bases: BaseState

The DrawingAction representing the close_path() method. Can function as a context manager.

toga.widgets.canvas.MoveTo dataclass

MoveTo(x: float, y: float)

Bases: DrawingAction

The DrawingAction representing the move_to() method.

toga.widgets.canvas.LineTo dataclass

LineTo(x: float, y: float)

Bases: DrawingAction

The DrawingAction representing the line_to() method.

toga.widgets.canvas.BezierCurveTo dataclass

BezierCurveTo(
    cp1x: float, cp1y: float, cp2x: float, cp2y: float, x: float, y: float
)

Bases: DrawingAction

The DrawingAction representing the bezier_curve_to() method.

toga.widgets.canvas.QuadraticCurveTo dataclass

QuadraticCurveTo(cpx: float, cpy: float, x: float, y: float)

Bases: DrawingAction

The DrawingAction representing the quadratic_curve_to() method.

toga.widgets.canvas.Arc dataclass

Arc(
    x: float,
    y: float,
    radius: float,
    startangle: float = 0.0,
    endangle: float = 2 * pi,
    counterclockwise: bool | None = None,
    anticlockwise: InitVar[bool | None] = None,
)

Bases: DrawingAction

The DrawingAction representing the arc() method.

toga.widgets.canvas.Ellipse dataclass

Ellipse(
    x: float,
    y: float,
    radiusx: float,
    radiusy: float,
    rotation: float = 0.0,
    startangle: float = 0.0,
    endangle: float = 2 * pi,
    counterclockwise: bool | None = None,
    anticlockwise: InitVar[bool | None] = None,
)

Bases: DrawingAction

The DrawingAction representing the ellipse() method.

toga.widgets.canvas.Rect dataclass

Rect(x: float, y: float, width: float, height: float)

Bases: DrawingAction

The DrawingAction representing the rect() method.

toga.widgets.canvas.Fill dataclass

Fill(
    fill_rule: FillRule = NONZERO,
    *,
    fill_style: ColorT | None | object = color_property(),
    color: InitVar[ColorT | None | object] = color_property(),
)

Bases: BaseState

The DrawingAction representing the fill() method. Can function as a context manager.

toga.widgets.canvas.Stroke dataclass

Stroke(
    *,
    stroke_style: ColorT | None | object = color_property(),
    color: InitVar[ColorT | None | object] = color_property(),
    line_width: float | None = None,
    line_dash: list[float] | None = None,
)

Bases: BaseState

The DrawingAction representing the stroke() method. Can function as a context manager.

toga.widgets.canvas.WriteText dataclass

WriteText(
    text: str,
    x: float = 0.0,
    y: float = 0.0,
    font: Font | None = None,
    baseline: Baseline = ALPHABETIC,
    line_height: float | None = None,
)

Bases: DrawingAction

The DrawingAction representing the write_text() method.

toga.widgets.canvas.DrawImage dataclass

DrawImage(
    image: Image,
    x: float = 0.0,
    y: float = 0.0,
    width: float | None = None,
    height: float | None = None,
)

Bases: DrawingAction

The DrawingAction representing the draw_image() method.

toga.widgets.canvas.Rotate dataclass

Rotate(radians: float)

Bases: DrawingAction

The DrawingAction representing the rotate() method.

toga.widgets.canvas.Scale dataclass

Scale(sx: float, sy: float)

Bases: DrawingAction

The DrawingAction representing the scale() method.

toga.widgets.canvas.Translate dataclass

Translate(tx: float, ty: float)

Bases: DrawingAction

The DrawingAction representing the translate() method.

toga.widgets.canvas.ResetTransform

Bases: DrawingAction

The DrawingAction representing the reset_transform() method.