New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convert Canvas Widget to Use a Drawing Stack #383
Changes from 67 commits
9847b3a
b0f0a96
38f2783
6e57a3c
068eed2
772568c
119fe0b
8d2f185
07cb34d
63ba1f3
cb0c3ba
4634c7f
718bd51
7143693
83f3f18
503fc10
a99e997
09f7b71
8b86b9e
bfff265
d5eb4f7
c19e059
9382102
572173d
f320a11
1264fdb
480b001
c64bda8
3cd1f94
4cd33e0
6ab42f5
0c9a57f
79b750c
4ccef5a
e81fce3
9e8a3b8
0473854
ecc54e4
cd6d8d7
b7c1bb3
e3251e4
c5a0a8d
98c3536
e57c4c8
f3e2eeb
474c60e
3bee912
dc41e78
7b4fff5
8ca82f3
3b9d47e
6ac44c8
0547001
8a0f97c
c76a0d4
36adc08
97f5604
8745508
ba997c4
d3a5a0e
945c138
6b8e86f
46730bf
b710538
f279823
cb6eafd
a00769f
c661832
dfe7193
0b5e443
7fddf73
f466f93
ab669ae
d3f6732
da7a5d5
368921e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,16 +15,70 @@ The canvas is used for creating a blank widget that you can draw on. | |
Usage | ||
----- | ||
|
||
Simple usage to draw a black circle on the screen using the arc drawing object: | ||
|
||
.. code-block:: Python | ||
|
||
import toga | ||
canvas = toga.Canvas(style=Pack(flex=1)) | ||
box = toga.Box(children=[canvas]) | ||
with canvas.fill() as fill: | ||
fill.arc(50, 50, 15) | ||
|
||
More advanced usage for something like a vector drawing app where you would | ||
want to modify the parameters of the drawing objects. Here we draw a black | ||
circle and black rectangle. We then change the size of the circle, move the | ||
rectangle, and finally delete the rectangle. | ||
|
||
.. code-block:: Python | ||
|
||
import toga | ||
canvas = toga.Canvas(style=Pack(flex=1)) | ||
box = toga.Box(children=[canvas]) | ||
with canvas.fill() as fill: | ||
arc1 = fill.arc(x=50, y=50, radius=15) | ||
rect1 = fill.rect(x=50, y=50, width=15, height=15) | ||
|
||
arc1.x, arc1.y, arc1.radius = (25, 25, 5) | ||
rect1.x = 75 | ||
fill.remove(rect1) | ||
|
||
Use of drawing contexts, for example with a platformer game. Here you would | ||
want to modify the x/y coordinate of a drawing context that draws each | ||
character on the canvas. First, we create a hero context. Next, we create a | ||
black circle and a black outlined rectangle for the hero's body. Finally, we | ||
move the hero by 10 on the x-axis. | ||
|
||
.. code-block:: Python | ||
|
||
import toga | ||
canvas = toga.Canvas(style=Pack(flex=1)) | ||
box = toga.Box(children=[canvas]) | ||
with canvas.context() as hero: | ||
with hero.fill() as body: | ||
body.arc(50, 50, 15) | ||
with hero.stroke() as outline: | ||
outline.rect(50, 50, 15, 15) | ||
|
||
hero.translate(10, 0) | ||
|
||
canvas = toga.Canvas() | ||
|
||
Reference | ||
--------- | ||
|
||
Main Interface | ||
^^^^^^^^^^^^^^ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might it help to use automodule here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great suggestion, I updated to use the automodule with exclude-members. |
||
.. autoclass:: toga.widgets.canvas.Canvas | ||
:members: | ||
:undoc-members: | ||
:inherited-members: | ||
:exclude-members: canvas, propogate_canvas, add_child, redraw, | ||
add_drawing_object | ||
|
||
Lower-Level Classes | ||
^^^^^^^^^^^^^^^^^^^ | ||
|
||
.. automodule:: toga.widgets.canvas | ||
:members: | ||
:exclude-members: Canvas |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,33 +12,37 @@ One of the main capabilities needed to create many types of GUI applications is | |
the ability to draw and manipulate lines, shapes, text, and other graphics. To | ||
do this in Toga, we use the Canvas Widget. | ||
|
||
Utilizing the Canvas is easy as determining the drawing operations you want to | ||
perform, placing them in a function, and then creating a new Canvas while | ||
passing the function to the on_draw parameter. | ||
Utilizing the Canvas is as easy as determining the drawing operations you want to | ||
perform and then creating a new Canvas. All drawing objects that are created | ||
with one of the drawing operations are returned so that they can be modified or | ||
removed. | ||
|
||
1. We first define the drawing operations we want to perform in a new function:: | ||
|
||
def draw_tiberius(self, canvas, context): | ||
self.canvas.set_context(context) | ||
self.fill_head() | ||
def draw_eyes(self): | ||
with self.canvas.fill(color='rgba(255, 255, 255, 1)') as eye_whites: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this color syntax still current? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think so. This is a valid format in the color method in travertino. Would you prefer that we use named colors in the examples like WHITE and BLACK? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I swapped to using the built-in Toga color definitions, and the rgb() definition. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You've changed to travertino rgb elsewhere, but not in this specific example :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping this one in case it's been missed. |
||
eye_whites.arc(58, 92, 15) | ||
eye_whites.arc(88, 92, 15, math.pi, 3 * math.pi) | ||
|
||
The function you want to draw with should also be defined to include canvas and | ||
context arguments, and make use of the set_context method. | ||
Notice that we also created and used a new fill context called eye_whites. The | ||
"with" keyword that is used for the fill operation causes everything draw using | ||
the context to be filled with a color. In this example we filled two circular | ||
eyes with the color white. | ||
|
||
2. Next we create a new Canvas, and pass in the draw_tiberius method:: | ||
2. Next we create a new Canvas:: | ||
|
||
self.canvas = toga.Canvas(on_draw=self.draw_tiberius) | ||
self.canvas = toga.Canvas(style=Pack(flex=1)) | ||
|
||
That's all there is to! In this example we also add our canvas to the MainWindow | ||
through use of the Box Widget:: | ||
|
||
box = toga.Box(children=[self.canvas]) | ||
self.main_window.content = box | ||
|
||
You'll also notice in the full example below that some of the drawing operations | ||
use the "with" keyword to utilize context managers including closed_path, fill, | ||
and stroke. This reduces the repetition of commands while utilizing these basic | ||
drawing capabilities. | ||
You'll also notice in the full example below that the drawing operations utilize | ||
contexts in addition to fill including context, closed_path, and stroke. This | ||
reduces the repetition of commands as well as groups drawing operations so that | ||
they can be modified together. | ||
|
||
.. image:: screenshots/tutorial-4.png | ||
|
||
|
@@ -47,7 +51,4 @@ Here's the source code | |
.. literalinclude:: /../examples/tutorial4/tutorial/app.py | ||
:language: python | ||
|
||
Although not shown in this tutorial, it is also possible to directly do simple | ||
draw operations without passing in the on_draw callable function. | ||
|
||
In this example, we see a new Toga widget - :class:`.Canvas`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor note - this isn't drawing an "image", it's drawing a filled circle. Explaining exactly what is going to be drawn (and why) would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, more detailed added to what is supposed to be drawn.