142 lines
5.4 KiB
Python
142 lines
5.4 KiB
Python
import math
|
|
|
|
import toga
|
|
from toga.colors import WHITE, rgb
|
|
from toga.constants import Baseline
|
|
from toga.fonts import SANS_SERIF
|
|
from toga.style import Pack
|
|
|
|
|
|
class StartApp(toga.App):
|
|
def startup(self):
|
|
self.main_window = toga.MainWindow(size=(150, 250))
|
|
|
|
# Create empty canvas
|
|
self.canvas = toga.Canvas(
|
|
style=Pack(flex=1),
|
|
on_resize=self.on_resize,
|
|
on_press=self.on_press,
|
|
)
|
|
box = toga.Box(children=[self.canvas])
|
|
|
|
# Add the content on the main window
|
|
self.main_window.content = box
|
|
|
|
# Draw tiberius on the canvas
|
|
self.draw_tiberius()
|
|
|
|
# Show the main window
|
|
self.main_window.show()
|
|
|
|
def fill_head(self):
|
|
with self.canvas.Fill(color=rgb(149, 119, 73)) as head_filler:
|
|
head_filler.move_to(112, 103)
|
|
head_filler.line_to(112, 113)
|
|
head_filler.ellipse(73, 114, 39, 47, 0, 0, math.pi)
|
|
head_filler.line_to(35, 84)
|
|
head_filler.arc(65, 84, 30, math.pi, 3 * math.pi / 2)
|
|
head_filler.arc(82, 84, 30, 3 * math.pi / 2, 2 * math.pi)
|
|
|
|
def stroke_head(self):
|
|
with self.canvas.Stroke(line_width=4.0) as head_stroker:
|
|
with head_stroker.ClosedPath(112, 103) as closed_head:
|
|
closed_head.line_to(112, 113)
|
|
closed_head.ellipse(73, 114, 39, 47, 0, 0, math.pi)
|
|
closed_head.line_to(35, 84)
|
|
closed_head.arc(65, 84, 30, math.pi, 3 * math.pi / 2)
|
|
closed_head.arc(82, 84, 30, 3 * math.pi / 2, 2 * math.pi)
|
|
|
|
def draw_eyes(self):
|
|
with self.canvas.Fill(color=WHITE) as eye_whites:
|
|
eye_whites.arc(58, 92, 15)
|
|
eye_whites.arc(88, 92, 15, math.pi, 3 * math.pi)
|
|
|
|
# Draw eyes separately to avoid miter join
|
|
with self.canvas.Stroke(line_width=4.0) as eye_outline:
|
|
eye_outline.arc(58, 92, 15)
|
|
with self.canvas.Stroke(line_width=4.0) as eye_outline:
|
|
eye_outline.arc(88, 92, 15, math.pi, 3 * math.pi)
|
|
|
|
with self.canvas.Fill() as eye_pupils:
|
|
eye_pupils.arc(58, 97, 3)
|
|
eye_pupils.arc(88, 97, 3)
|
|
|
|
def draw_horns(self):
|
|
with self.canvas.Context() as r_horn:
|
|
with r_horn.Fill(color=rgb(212, 212, 212)) as r_horn_filler:
|
|
r_horn_filler.move_to(112, 99)
|
|
r_horn_filler.quadratic_curve_to(145, 65, 139, 36)
|
|
r_horn_filler.quadratic_curve_to(130, 60, 109, 75)
|
|
with r_horn.Stroke(line_width=4.0) as r_horn_stroker:
|
|
r_horn_stroker.move_to(112, 99)
|
|
r_horn_stroker.quadratic_curve_to(145, 65, 139, 36)
|
|
r_horn_stroker.quadratic_curve_to(130, 60, 109, 75)
|
|
|
|
with self.canvas.Context() as l_horn:
|
|
with l_horn.Fill(color=rgb(212, 212, 212)) as l_horn_filler:
|
|
l_horn_filler.move_to(35, 99)
|
|
l_horn_filler.quadratic_curve_to(2, 65, 6, 36)
|
|
l_horn_filler.quadratic_curve_to(17, 60, 37, 75)
|
|
with l_horn.Stroke(line_width=4.0) as l_horn_stroker:
|
|
l_horn_stroker.move_to(35, 99)
|
|
l_horn_stroker.quadratic_curve_to(2, 65, 6, 36)
|
|
l_horn_stroker.quadratic_curve_to(17, 60, 37, 75)
|
|
|
|
def draw_nostrils(self):
|
|
with self.canvas.Fill(color=rgb(212, 212, 212)) as nose_filler:
|
|
nose_filler.move_to(45, 145)
|
|
nose_filler.bezier_curve_to(51, 123, 96, 123, 102, 145)
|
|
nose_filler.ellipse(73, 114, 39, 47, 0, math.pi / 4, 3 * math.pi / 4)
|
|
with self.canvas.Fill() as nostril_filler:
|
|
nostril_filler.arc(63, 140, 3)
|
|
nostril_filler.arc(83, 140, 3)
|
|
with self.canvas.Stroke(line_width=4.0) as nose_stroker:
|
|
nose_stroker.move_to(45, 145)
|
|
nose_stroker.bezier_curve_to(51, 123, 96, 123, 102, 145)
|
|
|
|
def draw_text(self):
|
|
font = toga.Font(family=SANS_SERIF, size=20)
|
|
self.text_width, text_height = self.canvas.measure_text("Tiberius", font)
|
|
|
|
x = (150 - self.text_width) // 2
|
|
y = 175
|
|
|
|
with self.canvas.Stroke(color="REBECCAPURPLE", line_width=4.0) as rect_stroker:
|
|
self.text_border = rect_stroker.rect(
|
|
x - 5,
|
|
y - 5,
|
|
self.text_width + 10,
|
|
text_height + 10,
|
|
)
|
|
with self.canvas.Fill(color=rgb(149, 119, 73)) as text_filler:
|
|
self.text = text_filler.write_text("Tiberius", x, y, font, Baseline.TOP)
|
|
|
|
def draw_tiberius(self):
|
|
self.fill_head()
|
|
self.draw_eyes()
|
|
self.draw_horns()
|
|
self.draw_nostrils()
|
|
self.stroke_head()
|
|
self.draw_text()
|
|
|
|
def on_resize(self, widget, width, height, **kwargs):
|
|
# On resize, center the text horizontally on the canvas. on_resize will be
|
|
# called when the canvas is initially created, when the drawing objects won't
|
|
# exist yet. Only attempt to reposition the text if there's context objects on
|
|
# the canvas.
|
|
if widget.context:
|
|
left_pad = (width - self.text_width) // 2
|
|
self.text.x = left_pad
|
|
self.text_border.x = left_pad - 5
|
|
widget.redraw()
|
|
|
|
def on_press(self, widget, x, y, **kwargs):
|
|
self.main_window.info_dialog("Hey!", f"You poked the yak at ({x}, {y})")
|
|
|
|
|
|
def main():
|
|
return StartApp("Tutorial 4", "org.beeware.toga.tutorial")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main().main_loop()
|