cs110_p1
1## DON"T OPEN THIS FILE! USE THE PURPLE BUTTON ON THE ASSIGNMENT 2## to see what functions are available and what their inputs are! 3 4################################################################### 5 6## PROCEED AT YOUR OWN RISK! THERE BE DRAGONS! 7 8_VERSION = "2025.1.1" 9 10## 2025.1.1 11# Feature: adds ability to fill the screen with the window 12# Feature: grid - add show_label param 13 14################################################################### 15### IGNORE EVERYTHING THAT STARTS WITH A _ 16from random import randint 17from math import sqrt, pi, radians, sin, cos, floor 18from time import sleep 19from tkinter import Tk, Canvas 20 21 22__docformat__ = "google" 23 24_a_canvas = None 25_resize_enabled = False 26 27 28Shape_Drawing_Functions = "" 29 30 31def arc(points=[], width=5, color="hot pink", line_steps=15, tag="", ): 32 """ 33 A reporter function that draws an arc ("curve") given a list of points. 34 Args: 35 points (`list`): The points outlining the curve; this should be a list of tuples (coordinates). 36 Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line! 37 color (`str`): What color to make the shape. 38 tag (`str`): The tag to assign to the shape. 39 40 Returns: 41 `Shape`: The arc that was created. 42 """ 43 return _a_canvas.create_line( 44 points, 45 width=width, 46 fill=color, 47 splinesteps=line_steps, 48 smooth=True, 49 tags=tag, 50 , 51 ) 52 53 54def car(top_left=(0, 0), size=100, body_color="#3D9970", wheel_color="black", tag=""): 55 """ 56 Draws a cool car. 57 58 Args: 59 top_left (`tuple`): A coordinate at which to draw the car. 60 body_color (`str`): Color to make the body of the car. 61 wheel_color (`str`): Color to make the wheel of the car. 62 tag (`str`): The tag to assign to the shape. 63 """ 64 x, y = top_left 65 rectangle((x + 5 * size / 10, y), size, size / 10 * 4, color=body_color, tag=tag) 66 rectangle( 67 (x, y + size - 7 * size / 10), 68 size * 2, 69 size / 10 * 4.5, 70 color=body_color, 71 tag=tag, 72 ) 73 circle( 74 (x + 5 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag 75 ) 76 circle( 77 (x + 15 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag 78 ) 79 80 81def circle(center=(0, 0), radius=25, color="hot pink", outline="", tag="", ): 82 """ 83 A reporter function that draws a circle. 84 Args: 85 center (`tuple`): A coordinate representing the center of the shape. 86 radius (`int`): Specifies the circle"s radius. 87 color (`str`): What color to draw the shape. 88 outline (`str`): What color should the border of the shape be. 89 tag (`str`): The tag to assign to the shape. 90 91 Returns: 92 `Shape`: The circle that was created. 93 """ 94 return oval( 95 center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 96 ) 97 98 99def cloud(center=(0, 0), size=30, color="white", tag=""): 100 """ 101 Reporter function that draws a cloud to the screen. 102 Args: 103 center (`tuple`): the point on which to center the cloud 104 size (`int`): how big (roughly) the cloud is drawn 105 color (`str`): which determines the color of the cloud 106 tag (`str`): to give the cloud a name 107 108 Returns: 109 `Shape`: The cloud that was created. 110 """ 111 for i in range(10): 112 x_offset = randint((-1 * size * 1.333), (size * 1.333)) 113 y_offset = randint(0, (size * 0.667)) 114 circle( 115 center=(center[0] + x_offset, center[1] + y_offset), 116 radius=randint((size * 0.667), (size * 1.667)), 117 color=color, 118 tag=tag, 119 ) 120 return tag 121 122 123def diamond( 124 center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 125): 126 """ 127 A reporter function that draws a rectangle. 128 Args: 129 center (`tuple`): A coordinate representing the center of the shape. 130 width (`int`): How wide to draw the shape. 131 height (`int`): How tall to draw the shape. 132 color (`str`): What color to draw the shape. 133 outline (`str`): What color should the border of the shape be. 134 tag (`str`): The tag to assign to the shape. 135 136 Returns: 137 `Shape`: The shape that was created. 138 """ 139 point_0 = (center[0] - width / 2, center[1]) 140 point_1 = (center[0], center[1] - height / 2) 141 point_2 = (center[0] + width / 2, center[1]) 142 point_3 = (center[0], center[1] + height / 2) 143 return _a_canvas.create_polygon( 144 point_0, 145 point_1, 146 point_2, 147 point_3, 148 fill=_safe_color(color), 149 tags=tag, 150 outline=outline, 151 , 152 ) 153 154 155def grid(width=None, height=None, interval=100, show_labels=True): 156 """ 157 Draws a grid on a screen with intervals of 100. 158 159 Args: 160 width (`int`): The width of the grid to draw (defaults to the whole window) 161 height (`int`): The height of the grid to draw (defaults to the whole window) 162 interval (`int`): The interval to draw the grid on. 163 show_labels (`bool`): Whether or not to show coordinate labels. 164 165 """ 166 167 if width is None 168 width = get_window_width() 169 170 if height is None 171 height = get_window_height() 172 173 # Creates all vertical lines at intervals of 100 174 for i in range(0, width, interval): 175 _a_canvas.create_line(i, 0, i, height, tag="grid", fill="black") 176 # Creates all horizontal lines at intervals of 100 177 for i in range(0, height, interval): 178 _a_canvas.create_line(0, i, width, i, tag="grid", fill="black") 179 180 if show_labels 181 # Creates axis labels 182 offset = 2 183 for y in range(0, height, interval): 184 for x in range(0, width, interval): 185 _a_canvas.create_oval( 186 x - offset, 187 y - offset, 188 x + offset, 189 y + offset, 190 fill="black", 191 tag="grid", 192 ) 193 _a_canvas.create_text( 194 x + offset, 195 y + offset, 196 text="({0}, {1})".format(x, y), 197 anchor="nw", 198 font=("Purisa", 8), 199 fill="black", 200 tag="grid", 201 ) 202 203 204_cache = [] 205 206 207def image(image_path, position=(200, 200), rotation=None, scale=None, tag="", ): 208 """ 209 Draws a given image on the screen. NOTE: Requires the `pillow` package to be installed - contact 210 Prof. Bain or post on edSTEM if you"d like more details! 211 212 Args: 213 image_path (`str`): Location of the image file on your computer. 214 position (`tuple`): A coordinate at which to render the image. 215 rotation (`int`): A number of degrees to rotate the given image. 216 scale (`int`): A scaling factor to multiply the image size by. 217 tag (`str`): A string representing the "name" fo this shape. 218 """ 219 # import PIL libraries 220 from PIL import Image, ImageTk 221 222 anchor = "nw" 223 224 import os 225 226 # 1. create PIL image and apply any image transformations: 227 dir_path = os.path.dirname(os.path.realpath(__file__)) 228 image_path = os.path.join(dir_path, image_path) 229 pil_image = Image.open(image_path) 230 if scale 231 size = (round(pil_image.size[0] * scale), round(pil_image.size[1] * scale)) 232 pil_image = pil_image.resize(size) 233 if rotation 234 pil_image = pil_image.rotate(rotation) # note: returns a copy 235 236 # 2. convert to tkinter-compatible image format: 237 tkinter_image = ImageTk.PhotoImage(pil_image) 238 _cache.append( 239 tkinter_image 240 ) # workaround for known tkinter bug: http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm 241 242 # 3. draw image on canvas: 243 _a_canvas.create_image( 244 *position, image=tkinter_image, anchor=anchor, tags=tag, 245 ) 246 247 248def line(points=[], curvy=False, color="hot pink", tag="", ): 249 """ 250 A reporter function that draws a line given a list of points. 251 Args: 252 points (`list`): The points that define the line; this should be a list of tuples (coordinates). 253 curvy (`bool`): Makes a curvy line instead. 254 color (`str`): What color to make the shape. 255 tag (`str`): The tag to assign to the shape. 256 257 Returns: 258 `Shape`: The line that was created. 259 """ 260 return _a_canvas.create_line(points, fill=color, smooth=curvy, tags=tag, ) 261 262 263def oval( 264 center=(0, 0), 265 radius_x=25, 266 radius_y=50, 267 color="hot pink", 268 outline="", 269 tag="", 270 , 271): 272 """ 273 A reporter function that draws an oval. 274 Args: 275 center (`tuple`): A coordinate representing the center of the shape. 276 radius_x (`int`): Specifies the oval"s radius on the x-axis. 277 radius_y (`int`): Specifies the oval"s radius on the y-axis. 278 color (`str`): What color to draw the shape. 279 outline (`str`): What color should the border of the shape be. 280 tag (`str`): The tag to assign to the shape. 281 282 Returns: 283 `Shape`: The oval that was created. 284 """ 285 x = center[0] 286 y = center[1] 287 x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y) 288 steps = 100 289 # major and minor axes 290 a = (x1 - x0) / 2.0 291 b = (y1 - y0) / 2.0 292 # center 293 xc = x0 + a 294 yc = y0 + b 295 point_list = [] 296 # create the oval as a list of points 297 for i in range(steps): 298 # Calculate the angle for this step 299 theta = (pi * 2) * (float(i) / steps) 300 x = a * cos(theta) 301 y = b * sin(theta) 302 point_list.append(round(x + xc)) 303 point_list.append(round(y + yc)) 304 305 return _a_canvas.create_polygon( 306 point_list, fill=_safe_color(color), tags=tag, 307 ) 308 309 310def pixel_art(top_left, artwork, palette, pixel=10, tag=""): 311 """ 312 Draws a pixel art design! 313 314 Args: 315 top_left (`tuple`): the top left coordinate of the pixel art 316 artwork (sequence of sequences): the art to draw 317 palette (sequence): the palette of colors to use for each different square 318 pixel (`int`, optional): how big each individual pixel should be 319 tag (`str`, optional): the tag to assign to every square in the row 320 321 Note: this doesn"t return anything so make sure to use a tag if you want to animate / modify. 322 """ 323 x = top_left[0] 324 y = top_left[1] 325 for row in artwork 326 # draw each row at the specified (x, y) position: 327 _draw_row(row, (x, y), colors=palette, pixel=pixel, tag=tag) 328 # ...and don"t forget to shift the y-value down by the proper 329 # amount so that the next row won"t draw on top of the first one: 330 y += pixel 331 332 333def polygon(points=[], color="hot pink", outline="", tag="", ): 334 """ 335 A reporter function that draws a polygon given a list of points. 336 Args: 337 points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates). 338 defaults to an empty list. 339 outline (`str`): What color should the border of the shape be. 340 color (`str`): What color to make the shape. 341 342 Returns: 343 `Shape`: The polygon that was created. 344 """ 345 return _a_canvas.create_polygon(points, fill=_safe_color(color), tags=tag, ) 346 347 348def rectangle( 349 top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 350): 351 """ 352 A reporter function that draws a rectangle. 353 Args: 354 top_left (`tuple`): A coordinate representing the top left-hand corner of the shape. 355 width (`int`): How wide to draw the shape. 356 height (`int`): How tall to draw the shape. 357 color (`str`): What color to draw the shape. 358 outline (`str`): What color should the border of the shape be. 359 tag (`str`): The tag to assign to the shape. 360 361 Returns: 362 `Shape`: The rectangle that was created. 363 """ 364 point_0 = top_left 365 point_1 = (top_left[0] + width, top_left[1]) 366 point_2 = (top_left[0] + width, top_left[1] + height) 367 point_3 = (top_left[0], top_left[1] + height) 368 return _a_canvas.create_polygon( 369 point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 370 ) 371 372 373def spiral( 374 center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 375): 376 """ 377 A reporter function that draws a spiral. 378 Args: 379 center (`tuple`): A coordinate representing the center of the shape. 380 width (`int`): Specifies the total width of the spiral. 381 roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y) 382 start (`int`): Where on the spiral to start drawing. 383 spirals (`int`): How many loops to draw. 384 line_width (`int`): How wide for the line to be drawn. 385 tag (`str`): The tag to assign to the shape. 386 387 Returns: 388 `Shape`: The spiral that was created. 389 """ 390 theta = 0.0 391 r = start 392 all_points = [] 393 prev_pos = _polar_to_cartesian(r, theta) 394 distance = width / 4 / pi / spirals 395 all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1])) 396 while theta < 2 * spirals * pi 397 theta += roughness 398 r = start + distance * theta 399 pos = _polar_to_cartesian(r, theta) 400 all_points.append((pos[0] + center[0], pos[1] + center[1])) 401 402 return arc(points=all_points, width=line_width, ) 403 404 405def square(top_left=(0, 0), size=25, color="hot pink", outline="", tag="", ): 406 """ 407 A reporter function that draws a square. 408 Args: 409 top_left (`tuple`): A coordinate representing the top left-hand corner of the shape. 410 size (`int`): How big to draw the shape. 411 color (`str`): What color to draw the shape. 412 outline (`str`): What color should the border of the shape be. 413 tag (`str`): The tag to assign to the shape. 414 415 Returns: 416 `Shape`: The square that was created. 417 """ 418 return rectangle( 419 top_left=top_left, width=size, height=size, color=color, tag=tag, 420 ) 421 422 423def star( 424 center=(0, 0), 425 radius=50, 426 color="hot pink", 427 outer_radius=75, 428 points=5, 429 outline="", 430 tag="", 431 , 432): 433 """ 434 A reporter function that draws a star. 435 Args: 436 center (`tuple`): A coordinate representing the center of the shape. 437 radius (`int`): Specifies the radius of the inside part of the star. 438 color (`str`): Specifies the color of the star. 439 outer_radius (`int`): Specifies the radius of the outside part of the star. 440 points (`int`): Specifies the number of points for the star. 441 outline (`str`): What color should the border of the shape be. 442 tag (`str`): The tag to assign to the shape. 443 444 Returns: 445 `Shape`: The star that was created. 446 """ 447 arc_segment = 360 / points 448 vertices = [] 449 for i in range(points): 450 inner_point = ( 451 radius * cos(radians(arc_segment * i)) + center[0], 452 -1 * radius * sin(radians(arc_segment * i)) + center[1], 453 ) 454 vertices.append(inner_point) 455 outer_point = ( 456 outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0], 457 -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2)) 458 + center[1], 459 ) 460 vertices.append(outer_point) 461 return polygon(vertices, color=color, tag=tag, ) 462 463 464def text( 465 top_left=(0, 0), text="", font=("Purisa", 32), color="black", tag="", 466): 467 """ 468 A reporter function that draws text to the screen 469 Args: 470 top_left (`tuple`): coordinate pair to specify the location. 471 text (`str`): What text to draw. 472 font (`tuple`): A tuple where the first element is a string for the font name and the second is an 473 int with the font size. 474 color (`str`): What color should the text be. 475 tag (`str`): The name to tag this thing with. 476 477 Returns: 478 `Shape`: The text that was created. 479 """ 480 return _a_canvas.create_text( 481 top_left, text=text, font=font, fill=color, tags=tag, 482 ) 483 484 485def triangle( 486 bottom_center=(0, 0), 487 width=25, 488 top_shift=0, 489 height=0, 490 color="hot pink", 491 outline="", 492 tag="", 493 , 494): 495 """ 496 A reporter function that draws a triangle. 497 Args: 498 bottom_center (`tuple`): A coordinate representing the bottom center of the shape. 499 width (`int`): Specifies the width of the base of the triangle. 500 top_shift (`int`): Specifies the how far to the left or right to shift the top of 501 the triangle from the bottom center. 502 height (`int`): Specifies the triangle"s height. 503 color (`str`): What color to draw the shape. 504 outline (`str`): What color should the border of the shape be. 505 tag (`str`): The tag to assign to the shape. 506 507 Returns: 508 `Shape`: The triangle that was created. 509 """ 510 if height == 0 511 height = width * sqrt(3) / 2 512 point_0 = (bottom_center[0] - width / 2, bottom_center[1]) 513 point_1 = (bottom_center[0] + width / 2, bottom_center[1]) 514 point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height) 515 516 return _a_canvas.create_polygon( 517 point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 518 ) 519 520 521def wedge( 522 center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="", 523): 524 """ 525 A reporter function that draws a circle. 526 Args: 527 center (`tuple`): A coordinate representing the center of the shape. 528 radius (`int`): Specifies the circle"s radius. 529 angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw. 530 color (`str`): What color to draw the shape. 531 outline (`str`): What color should the border of the shape be. 532 tag (`str`): The tag to assign to the shape. 533 534 Returns: 535 `Shape`: The wedge that was created. 536 """ 537 point_list = [center[0], center[1]] 538 for i in range(0, 0 + angle): 539 x1 = center[0] + radius * cos(radians(i)) 540 point_list.append(x1) 541 y1 = center[1] + radius * sin(radians(i)) 542 point_list.append(y1) 543 544 point_list.append(center[0]) 545 point_list.append(center[1]) 546 547 return _a_canvas.create_polygon( 548 point_list, fill=_safe_color(color), outline=outline, tags=tag, 549 ) 550 551 552Shape_Modifier_Functions = "" 553 554 555def above(shape1, shape2, offset_x=0, offset_y=0): 556 """ 557 A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center 558 to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any 559 specified offset. 560 561 Args: 562 shape1 (`Shape` or Tag): The first shape to use. 563 shape2 (`Shape` or Tag): The second shape to use. 564 offset_x (`int`): How much to shift shape 2 in the x-direction after moving it. 565 offset_y (`int`): How much to shift shape 2 in the x-direction after moving it. 566 567 Returns: 568 `Shape`: The modified shape1. 569 """ 570 overlay(shape1, shape2) 571 _a_canvas.move( 572 shape1, 573 0 + offset_x, 574 -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y, 575 ) 576 return shape1 577 578 579def align(shape1, shape2, via="middle", offset_x=0, offset_y=0): 580 """ 581 A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with 582 whatever property of `shape2` is selected with the `via` input. 583 584 Args: 585 shape1 (`Shape` or Tag): The first shape to use. 586 shape2 (`Shape` or Tag): The second shape to use. 587 via (`str`): Has to be one of, the following options: `"center"` (horizontal center), 588 `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"` 589 offset_x (`int`): How much to shift in the x-axis after alignment 590 offset_y (`int`): How much to shift in the y-axis after alignment 591 592 Returns: 593 `Shape`: The modified shape1. 594 """ 595 via_options = ["center", "middle", "top", "bottom", "left", "right"] 596 if via not in via_options 597 raise ValueError( 598 "The via input must be one of " 599 + (via_options) 600 + " but instead we found " 601 + (via) 602 ) 603 604 outline1 = _get_outline(shape1) 605 outline2 = _get_outline(shape2) 606 607 if via == "center" 608 _a_canvas.move( 609 shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y 610 ) 611 612 elif via == "middle" 613 _a_canvas.move( 614 shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y 615 ) 616 617 elif via == "top" 618 _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y) 619 620 elif via == "bottom" 621 _a_canvas.move( 622 shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y 623 ) 624 625 elif via == "left" 626 _a_canvas.move( 627 shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y 628 ) 629 630 elif via == "right" 631 _a_canvas.move( 632 shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y 633 ) 634 635 return shape1 636 637 638def beside(shape1, shape2, offset_x=0, offset_y=0): 639 """ 640 A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center 641 to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any 642 specified offset. 643 644 Args: 645 shape1 (`Shape` or Tag): The first shape to use. 646 shape2 (`Shape` or Tag): The second shape to use. 647 offset_x (`int`): How much to shift shape 2 in the x-direction after moving it. 648 offset_y (`int`): How much to shift shape 2 in the x-direction after moving it. 649 650 Returns: 651 `Shape`: The modified shape1. 652 """ 653 overlay(shape1, shape2) 654 _a_canvas.move( 655 shape1, 656 (get_width(shape2) + get_width(shape1)) / 2 + offset_x, 657 0 + offset_y, 658 ) 659 return shape1 660 661 662def below(shape1, shape2, offset_x=0, offset_y=0): 663 """ 664 A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center 665 to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any 666 specified offset. 667 668 Args: 669 shape1 (`Shape` or Tag): The first shape to use. 670 shape2 (`Shape` or Tag): The second shape to use. 671 offset_x (`int`): How much to shift shape 2 in the x-direction after moving it. 672 offset_y (`int`): How much to shift shape 2 in the x-direction after moving it. 673 674 Returns: 675 `Shape`: The modified shape1. 676 """ 677 overlay(shape1, shape2) 678 _a_canvas.move( 679 shape1, 680 0 + offset_x, 681 (get_height(shape2) + get_height(shape1)) / 2 + offset_y, 682 ) 683 return shape1 684 685 686def change_color(shape, color): 687 """ 688 Change the fill color of a tagged object. 689 690 Args: 691 shape (`Shape` or Tag): The shape or tag to re-fill. 692 color (`str`): A color name or hex code to re-fill with. 693 """ 694 ids = _a_canvas.find_withtag(shape) 695 for id in ids 696 _a_canvas.itemconfig(id, fill=color) 697 698 699def delete(shape): 700 """ 701 A function that deletes a shape from our screen. 702 703 Args: 704 shape (`Shape` or Tag): The shape to delete. 705 """ 706 _a_canvas.delete(shape) 707 708 709def assign_tag(shape, tag): 710 """ 711 A function that assigns a `Shape` or other tagged object a new tag. This will 712 overwrite any existing tag that matches the provided `tag` argument. This means that if you have 713 a shape with multiple tags, _this function will only overwrite that one tag_. You would need to run 714 the function multiple times to rewrite the remaining tags. 715 716 Args: 717 shape (`Shape` or Tag): The shape to which you"d like to assign a new tag 718 tag (`str`): A new valid tag for this shape. 719 720 """ 721 ids = _a_canvas.find_withtag(shape) 722 for id in ids 723 the_tags = (_a_canvas.gettags(id)) 724 if shape in the_tags # if it has a tag replace it 725 index = the_tags.index(shape) 726 the_tags[index] = tag 727 else # otherwise it didn"t have a tag 728 the_tags.append(tag) 729 _a_canvas.itemconfig(id, tags=the_tags) 730 731 732def duplicate(shape, color=None): 733 """ 734 A reporter function that perfectly copies a shape and returns that copy. 735 736 Args: 737 shape (`Shape` or Tag): The shape to duplicate. 738 color (`str`): A new color to use with the duplicated shape. 739 740 Returns: 741 `Shape`: The new duplicated shape. 742 """ 743 shape_type = _a_canvas.type(shape) 744 shape_config = _a_canvas.itemconfig(shape) 745 shape_coords = _a_canvas.coords(shape) 746 the_copy = None 747 if shape_type == "polygon" 748 new_config = {key shape_config[key][-1] for key in shape_config.keys()} 749 if color != None 750 new_config["fill"] = color 751 the_copy = _a_canvas.create_polygon(shape_coords, new_config) 752 return the_copy 753 754 755def mirror(shape): 756 """ 757 A function that takes a shape and flips it across its vertical 758 axis, returning the modified shape. 759 760 Args: 761 shape (`Shape` or Tag): The shape in question. 762 763 """ 764 center = get_center(shape)[0] 765 shape_ids = _a_canvas.find_withtag(shape) 766 for shape_id in shape_ids 767 flipped_coordinates = [] 768 shape_coords = _a_canvas.coords(shape_id) 769 counter = 0 770 for num in shape_coords 771 if counter % 2 == 0 772 if num < center 773 flipped_coordinates.append(num + 2 * (center - num)) 774 elif num > center 775 flipped_coordinates.append(num - 2 * (num - center)) 776 else 777 flipped_coordinates.append(num) 778 else 779 flipped_coordinates.append(num) 780 counter += 1 781 _a_canvas.coords(shape_id, flipped_coordinates) 782 783 784def move(shape, x_shift=0, y_shift=0): 785 """ 786 Purpose: Move the x and y position of all shapes that have been tagged 787 with the tag argument 788 789 Args: 790 shape (`Shape` or Tag): The shape in question. 791 x_shift (`int`; optional): amount to move in the x direction 792 y_shift (`int`; optional): amount to move in the y direction 793 """ 794 shape_ids = _a_canvas.find_withtag(shape) 795 for id in shape_ids 796 _a_canvas.move(id, x_shift, y_shift) 797 798 799def move_to(tag, to, anchor="center"): 800 """ 801 Move the given tagged item to a particular `point` maintaining some `anchor`. 802 Note: this is NOT the same as the `move` function which moves an object by a specific amount. 803 804 Args: 805 tag (Shape or `str`): the shape (or shapes) to move 806 to (`tuple`): the `(x, y)` coordinate to which you wish to move the tagged object 807 anchor (`str`): which point on the shape do you want to move toward the given tuple. You can 808 use either `"center"` (default), `"top_left"`, `"top_right"`, `"bottom_left"`, or `"bottom_right"`. 809 """ 810 anchor_options = ["center", "top_left", "top_right", "bottom_left", "bottom_right"] 811 if anchor not in anchor_options 812 raise ValueError( 813 "The anchor input must be one of " 814 + (anchor_options) 815 + " but instead we found " 816 + (anchor) 817 ) 818 819 outline = _get_outline(tag) 820 delta_x = 0 821 delta_y = 0 822 823 if anchor == "top_left" 824 delta_x = to[0] - outline["left"] 825 delta_y = to[1] - outline["top"] 826 elif anchor == "top_right" 827 delta_x = to[0] - outline["right"] 828 delta_y = to[1] - outline["top"] 829 elif anchor == "bottom_right" 830 delta_x = to[0] - outline["right"] 831 delta_y = to[1] - outline["bottom"] 832 elif anchor == "bottom_left" 833 delta_x = to[0] - outline["left"] 834 delta_y = to[1] - outline["bottom"] 835 elif anchor == "center" 836 delta_x = to[0] - outline["center"][0] 837 delta_y = to[1] - outline["center"][1] 838 839 _a_canvas.move(tag, delta_x, delta_y) 840 841 842def overlay(shape1, shape2, offset_x=0, offset_y=0): 843 """ 844 A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center 845 to shape 2"s center, and then applying any specified offset. 846 Args: 847 shape1 (`Shape` or Tag): The first shape to use. 848 shape2 (`Shape` or Tag): The second shape to use. 849 offset_x (`int`): How much to shift shape 2 in the x-direction after centering it. 850 offset_y (`int`): How much to shift shape 2 in the x-direction after centering it. 851 852 Returns: 853 `Shape`: The modified shape1. 854 """ 855 center1 = get_center(shape1) 856 center2 = get_center(shape2) 857 _a_canvas.move( 858 shape1, 859 (center2[0] - center1[0]) + offset_x, 860 (center2[1] - center1[1]) + offset_y, 861 ) 862 _a_canvas.tag_raise(shape1, shape2) 863 return shape1 864 865 866def portion(shape, start=0, end=0.5): 867 """ 868 Purpose: Take a slice or portion of some already created shape. 869 870 Args: 871 shape (`Shape` or Tag): The shape to take a portion of 872 start (`float`): A number between 0 and 1 representing where to start the slice. 873 end (`float`): A number between 0 and 1 representing where to end the slice. 874 875 For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle. 876 877 Note: this function is experimental. It might produce unexpected results! 878 """ 879 all_shapes = _a_canvas.find_withtag(shape) 880 881 for a_shape in all_shapes 882 coords = _a_canvas.coords(a_shape) 883 884 start_coord = floor(start * len(coords)) 885 if start_coord % 2 == 1 886 start_coord = start_coord - 1 # need to start with an x,y pair 887 end_coord = floor(end * len(coords)) 888 if end_coord % 2 == 1 889 end_coord = end_coord - 1 # need to end with an x,y pair 890 891 # slice is up to not including so get the last x,y pair 892 new_coords = coords[start_coord end_coord + 2] 893 894 # loop shape back in on itself 895 new_coords.append(new_coords[0]) 896 new_coords.append(new_coords[1]) 897 898 # set the coordinates: 899 _a_canvas.coords(a_shape, new_coords) 900 901 902def put_in_back(shape): 903 """ 904 A function that "lowers" a shape to the "bottom" of the screen." 905 906 Args: 907 shape (`Shape` or Tag): The shape in question. 908 """ 909 _a_canvas.tag_lower(shape) 910 911 912def put_in_front(shape): 913 """ 914 A function that "raises" a shape to the "top" of the screen." 915 916 Args: 917 shape (`Shape` or Tag): The shape in question. 918 """ 919 _a_canvas.tag_raise(shape) 920 921 922def rotate(shape, degrees=5, origin=None): 923 """ 924 A reporter function that takes a shape and rotates it by a specified amount around a specified point. 925 It does this by interpolating a polygon around the shape and calculating the shifts of individual 926 points on the edge of the polygon. 927 928 Args: 929 shape (`Shape` or Tag): The shape to rotate. 930 degrees (`int`): The number of degrees to rotate the shape. 931 origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center 932 of the given shape. 933 934 Returns: 935 `Shape`: The modified shape. 936 """ 937 if origin is None 938 origin = get_center(shape) 939 940 theta = radians(degrees) 941 ox, oy = origin 942 943 all_shapes = _a_canvas.find_withtag(shape) 944 945 for a_shape in all_shapes 946 coords = _a_canvas.coords(a_shape) 947 # update coordinates: 948 for i in range(0, len(coords), 2): 949 px, py = coords[i], coords[i + 1] 950 qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox 951 qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy 952 coords[i] = qx 953 coords[i + 1] = qy 954 # set the coordinates: 955 _a_canvas.coords(a_shape, coords) 956 957 return shape 958 959 960def scale(shape, x_scale=1.0, y_scale=1.0): 961 """ 962 A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis. 963 964 The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause 965 the shape to grow along that access. Values less than 1.0 will cause the shape to shrink. 966 967 Args: 968 shape (`Shape` or Tag): The shape or tag to re-fill. 969 x_scale (`float`): How much to scale in the x-axis. 970 y_scale (`float`): How much to scale in the y-axis. 971 """ 972 ids = _a_canvas.find_withtag(shape) 973 974 coord = get_center(shape) 975 976 for i in ids 977 _a_canvas.scale(i, coord[0], coord[1], x_scale, y_scale) 978 979 980def underlay(shape1, shape2, offset_x=0, offset_y=0): 981 """ 982 A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center 983 to shape 2"s center, and then applying any specified offset. 984 Args: 985 shape1 (`Shape` or Tag): The first shape to use. 986 shape2 (`Shape` or Tag): The second shape to use. 987 offset_x (`int`): How much to shift shape 2 in the x-direction after centering it. 988 offset_y (`int`): How much to shift shape 2 in the x-direction after centering it. 989 990 Returns: 991 `Shape`: The modified shape1. 992 """ 993 center1 = get_center(shape1) 994 center2 = get_center(shape2) 995 _a_canvas.move( 996 shape1, 997 (center2[0] - center1[0]) + offset_x, 998 (center2[1] - center1[1]) + offset_y, 999 ) 1000 _a_canvas.tag_lower(shape1, shape2) 1001 return shape1 1002 1003 1004Utility_Functions = "" 1005 1006 1007def clear_window(keep_grid=True): 1008 """ 1009 A function that deletes everything from the window. 1010 1011 Args: 1012 keep_grid (`bool`): Whether or not to keep the grid. 1013 """ 1014 all_shapes = _a_canvas.find_all() 1015 1016 for shape in all_shapes 1017 tags = _a_canvas.gettags(shape) 1018 if "grid" in tags and keep_grid 1019 continue 1020 _a_canvas.delete(shape) 1021 1022 global _resize_enabled 1023 _resize_enabled = True 1024 1025 1026def distance(point1, point2): 1027 """ 1028 A reporter function calculates the distance between two `(x, y)` coordinates. 1029 1030 Args: 1031 point1 (`tuple`): The first `(x, y)` coordinate. 1032 point2 (`tuple`): The second `(x, y)` coordinate. 1033 1034 Returns: 1035 A `float` representing the distance between the two points. 1036 """ 1037 return sqrt(((point1[0] - point2[0]) 2) + ((point1[1] - point2[1]) 2)) 1038 1039 1040def does_tag_exist(tag): 1041 """ 1042 Returns `True` if a given tag exists otherwise returns `False`. 1043 1044 Args: 1045 `tag` (`str`): [Required] The tag of the object to lookup. 1046 1047 """ 1048 result = _a_canvas.find_withtag(tag) 1049 1050 if result 1051 return True 1052 else 1053 return False 1054 1055 1056def get_bottom(shape): 1057 """ 1058 A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped). 1059 1060 Args: 1061 shape (`Shape` or Tag): The shape in question. 1062 1063 Returns: 1064 A `int` representing the maximum y-coordinate of the shape. 1065 """ 1066 bbox = _safe_bbox(shape) 1067 return bbox[3] 1068 1069 1070def get_center(shape): 1071 """ 1072 A reporter function calculates the a coordinate at the center of some shape. 1073 1074 Args: 1075 shape (`Shape` or Tag): The shape in question. 1076 1077 Returns: 1078 A `tuple` representing center of the given shape. 1079 """ 1080 bbox = _safe_bbox(shape) 1081 1082 if bbox is None 1083 raise Exception( 1084 f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!" 1085 ) 1086 1087 return (((bbox[2] + bbox[0]) / 2), ((bbox[1] + bbox[3]) / 2)) 1088 1089 1090def get_colors(shape_or_shapes): 1091 """ 1092 A reporter function that returns all the colors associated with a tag or list of tags. 1093 1094 Args: 1095 shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of 1096 1097 Returns: 1098 A `List` containing all unique colors associated with that tag(s) 1099 """ 1100 all_shapes = [] 1101 if not isinstance(shape_or_shapes, ): 1102 shape_or_shapes = [shape_or_shapes] 1103 for shape in shape_or_shapes 1104 all_shapes += _a_canvas.find_withtag(shape) 1105 1106 all_colors = [] 1107 for shape in all_shapes 1108 color = _a_canvas.itemcget(shape, "fill") 1109 if color not in all_colors 1110 all_colors.append(color) 1111 1112 return all_colors 1113 1114 1115def get_height(shape): 1116 """ 1117 A reporter function calculates the height of some given shape. 1118 1119 Args: 1120 shape (`Shape` or Tag): The shape in question. 1121 1122 Returns: 1123 A `int` representing the height of the shape. 1124 """ 1125 bbox = _safe_bbox(shape) 1126 return bbox[3] - bbox[1] - 1 1127 1128 1129def get_left(shape): 1130 """ 1131 A reporter function calculates the minimum x-value of a given shape. 1132 1133 Args: 1134 shape (`Shape` or Tag): The shape in question. 1135 1136 Returns: 1137 A `int` representing the minimum x-coordinate of the shape. 1138 """ 1139 bbox = _safe_bbox(shape) 1140 return bbox[0] 1141 1142 1143def get_right(shape): 1144 """ 1145 A reporter function calculates the maximum x-value of a given shape. 1146 1147 Args: 1148 shape (`Shape` or Tag): The shape in question. 1149 1150 Returns: 1151 A `int` representing the maximum x-coordinate of the shape. 1152 """ 1153 bbox = _safe_bbox(shape) 1154 return bbox[2] 1155 1156 1157def get_tag_from_event(event, precision=25): 1158 """ 1159 Tries to return a tag of an object at a given mouse-event. 1160 1161 Args: 1162 event (`Event`): Must be a mouse event otherwise we"ll give back an error. 1163 precision (`int`): How precise in number of pixels does a user have be in order to "select" an object 1164 1165 Returns a blank string `""` if no shapes are found closer than `precision`. 1166 """ 1167 1168 if (event.type) not in [4, 6]: 1169 raise Exception(f"Received an event that isn"t a mouse event: {event}") 1170 1171 try 1172 x = event.x 1173 y = event.y 1174 shape_id = _a_canvas.find_closest(x, y) # get the top shape 1175 if shape_id and distance(get_center(shape_id), (x, y)) < precision 1176 tags = _a_canvas.gettags(shape_id) 1177 if len(tags) > 0 1178 return tags[0] 1179 return "" 1180 1181 except 1182 raise Exception( 1183 "No tag found! Maybe you passed us an event that isn"t a mouse event?" 1184 ) 1185 1186 1187def get_top(shape): 1188 """ 1189 A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped). 1190 1191 Args: 1192 shape (`Shape` or Tag): The shape in question. 1193 1194 Returns: 1195 A `int` representing the minimum y-coordinate of the shape. 1196 """ 1197 bbox = _safe_bbox(shape) 1198 return bbox[1] 1199 1200 1201def get_width(shape): 1202 """ 1203 A reporter function calculates the width of some given shape. 1204 1205 Args: 1206 shape (`Shape` or Tag): The shape in question. 1207 1208 Returns: 1209 An `int` representing width of the shape. 1210 """ 1211 bbox = _safe_bbox(shape) 1212 return bbox[2] - bbox[0] - 1 1213 1214 1215def get_window_height(): 1216 """ 1217 A reporter function that returns the current height of the window. 1218 1219 Returns: 1220 An `int` representing height of the window. 1221 """ 1222 return _a_canvas.winfo_height() 1223 1224 1225def get_window_width(): 1226 """ 1227 A reporter function that returns the current width of the window. 1228 1229 Returns: 1230 An `int` representing width of the window. 1231 """ 1232 return _a_canvas.winfo_width() 1233 1234 1235def interpolate_colors(color1, color2, frac): 1236 """ 1237 A reporter function that generates a new color between two given colors. 1238 Args: 1239 color1 (`str`): The path of the file to wrap 1240 color2 (`str`): The path of the file to wrap 1241 frac (`float`): What fraction of each color to take. An input of 0 returns 1242 color1, an input of 1 returns color2, an input of 0.5 returns a color 1243 perfectly between the two. 1244 1245 Returns: 1246 A color (as a hex `str`) to be used elsewhere 1247 """ 1248 if "#" not in color1 1249 color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1))) 1250 else 1251 color1 = _tupelize_color(color1) 1252 if "#" not in color2 1253 color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2))) 1254 else 1255 color2 = _tupelize_color(color2) 1256 return _interpolate_tuple(color1, color2, frac) 1257 1258 1259def random_color(): 1260 """ 1261 Returns a random color as a `string` to be used. 1262 It does not accept any inputs. 1263 """ 1264 r = lambda randint(0, 255) 1265 return "#%02X%02X%02X" % (r(), r(), r()) 1266 1267 1268def listen_for(event_str, handler_function, override=False): 1269 """ 1270 Sets up a listener for a given event on our window. 1271 1272 Args: 1273 event_str (`str`): The magic string that represents this event in the window 1274 handler_function (`func`): The name (not a string though) of the function you want called when the event his heard 1275 override (`bool`): Only use this if you speak to Prof. Bain and he recommends it. 1276 1277 The supported events are: 1278 * `"LEFT-CLICK"`: Left mouse click 1279 * `"RIGHT-CLICK"`: Right mouse click 1280 * `"ALT-CLICK"`: If you"re using a PC, this event might instead work for Right Click 1281 * `"LEFT-DRAG"`: Left mouse clicked and dragged on the screen 1282 * `"RIGHT-DRAG"`: Right mouse clicked and dragged on the screen 1283 * `"ALT-DRAG"`: For PCs, this event might instead work for RIGHT-DRAG 1284 * `"DOUBLE-LEFT"`: Left mouse double click 1285 * `"DOUBLE-RIGHT"`: Right mouse double click 1286 * `"DOUBLE-ALT"`: For PCs, this event might instead work for DOUBLE-RIGHT 1287 * `"KEY"`: The catch-all event for Keyboard presses 1288 """ 1289 1290 event_translator = { 1291 "LEFT-CLICK" "<Button-1>", 1292 "RIGHT-CLICK" "<Button-2>", 1293 "ALT-CLICK" "<Button-3>", 1294 "LEFT-DRAG" "<B1-Motion>", 1295 "RIGHT-DRAG" "<B2-Motion>", 1296 "ALT-DRAG" "<B3-Motion>", 1297 "DOUBLE-LEFT" "<Double-Button-1>", 1298 "DOUBLE-RIGHT" "<Double-Button-2>", 1299 "DOUBLE-ALT" "<Double-Button-3>", 1300 "KEY" "<Key>", 1301 } 1302 1303 if event_str not in event_translator and not override 1304 raise ( 1305 TypeError( 1306 f"The event you entered, {event_str}, isn"t supported. Here are the supported events: {[i for i in event_translator]}" 1307 ) 1308 ) 1309 1310 event = event_translator[event_str] 1311 1312 listen_for.tracker.add(event_str) 1313 1314 _a_canvas.bind(event, handler_function) 1315 1316 1317listen_for.tracker = set() 1318 1319def setup_shapes(title, background="white", include_grid=True, width=600, height=600): 1320 """ 1321 A static function that sets up the pop-up window. You can specify the size of the window here. 1322 1323 However, you should NOT add any calls to this function unless Prof. Bain specifically tells you to! 1324 1325 Args: 1326 title (`str`): The title of the pop-up window. 1327 background (`str`): A valid color as a string to be used as the background color. 1328 include_grid (`bool`): Whether or not to draw the grid. 1329 width (`int` or `str`): How wide the window should appear (advanced: use the string "FULLWIDTH" to maximize the width) 1330 height (`int` or `str`): How wide the window should appear (advanced: use the string "FULLHEIGHT" to maximize the width) 1331 """ 1332 1333 global _a_canvas 1334 gui = Tk() 1335 gui.title(title) 1336 1337 if width == "FULLWIDTH" 1338 width = gui.winfo_screenwidth() 1339 1340 if height == "FULLHEIGHT" 1341 height = gui.winfo_screenheight() 1342 1343 _a_canvas = Canvas(gui, background=background, width=width, height=height) 1344 _a_canvas.pack() 1345 if include_grid 1346 grid(width, height) 1347 1348 _a_canvas.focus_set() 1349 return _a_canvas 1350 1351 1352def update(): 1353 """ 1354 A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION unless Prof. Bain explicitly says to use it. 1355 """ 1356 _a_canvas.update() 1357 1358 1359def _safe_color(color ): 1360 color = color.strip() 1361 # Could also do some other verifications here... 1362 return color 1363 1364 1365def _tupelize_color(color): 1366 R = (color[13], 16) 1367 G = (color[35], 16) 1368 B = (color[57], 16) 1369 return R, G, B 1370 1371 1372def _interpolate_tuple(startcolor, goalcolor, frac): 1373 R = startcolor[0] 1374 G = startcolor[1] 1375 B = startcolor[2] 1376 1377 targetR = goalcolor[0] 1378 targetG = goalcolor[1] 1379 targetB = goalcolor[2] 1380 1381 DiffR = targetR - R 1382 DiffG = targetG - G 1383 DiffB = targetB - B 1384 1385 iR = (R + (DiffR * frac)) 1386 iG = (G + (DiffG * frac)) 1387 iB = (B + (DiffB * frac)) 1388 1389 hR = hex(iR).replace("0x", "") 1390 hG = hex(iG).replace("0x", "") 1391 hB = hex(iB).replace("0x", "") 1392 1393 if len(hR) == 1 1394 hR = "0" + hR 1395 if len(hB) == 1 1396 hB = "0" + hB 1397 if len(hG) == 1 1398 hG = "0" + hG 1399 1400 color = ("#" + hR + hG + hB).upper() 1401 1402 return color 1403 1404 1405def _polar_to_cartesian(r, theta): 1406 return (r * cos(theta)), (r * sin(theta)) 1407 1408 1409def _get_outline(shape): 1410 """ 1411 A reporter function that takes in a shape and calls the various helper functions to generate 1412 a sort of "summary" of that particular shape and returns it in the form of a dictionary. 1413 1414 Args: 1415 shape (`Shape` or Tag): The shape in question. 1416 1417 Returns: 1418 a `Dictionary` with the various properties of the shape 1419 """ 1420 1421 return { 1422 "center" get_center(shape), 1423 "left" get_left(shape), 1424 "right" get_right(shape), 1425 "top" get_top(shape), 1426 "bottom" get_bottom(shape), 1427 } 1428 1429 1430def _draw_row(row, top_left, colors, pixel=25, tag=""): 1431 """ 1432 Draws a single row of some pixel art. 1433 1434 Args: 1435 row (sequence): the row of artwork to draw 1436 top_left (`tuple`): the top left coordinate of the pixel art 1437 color (sequence): the colors to use for each square 1438 pixel (`int`, optional): how big each individual pixel should be 1439 tag (`str`, optional): the tag to assign to every square in the row 1440 """ 1441 x = top_left[0] 1442 y = top_left[1] 1443 for cell in row 1444 if cell != 0 1445 square((x, y), pixel, color=colors[cell], tag=tag) 1446 x += pixel 1447 1448 1449def _safe_bbox(shape): 1450 try 1451 bbox = _a_canvas.bbox(shape) 1452 if bbox is None 1453 Exception( 1454 f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!" 1455 ) 1456 return bbox 1457 except 1458 raise Exception( 1459 f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!" 1460 )
32def arc(points=[], width=5, color="hot pink", line_steps=15, tag="", ): 33 """ 34 A reporter function that draws an arc ("curve") given a list of points. 35 Args: 36 points (`list`): The points outlining the curve; this should be a list of tuples (coordinates). 37 Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line! 38 color (`str`): What color to make the shape. 39 tag (`str`): The tag to assign to the shape. 40 41 Returns: 42 `Shape`: The arc that was created. 43 """ 44 return _a_canvas.create_line( 45 points, 46 width=width, 47 fill=color, 48 splinesteps=line_steps, 49 smooth=True, 50 tags=tag, 51 , 52 )
A reporter function that draws an arc ("curve") given a list of points.
Arguments:
- points (
list): The points outlining the curve; this should be a list of tuples (coordinates). Make sure to give it at least 3 (x,y) coordinates that aren't a straight line! - color (
str): What color to make the shape. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The arc that was created.
55def car(top_left=(0, 0), size=100, body_color="#3D9970", wheel_color="black", tag=""): 56 """ 57 Draws a cool car. 58 59 Args: 60 top_left (`tuple`): A coordinate at which to draw the car. 61 body_color (`str`): Color to make the body of the car. 62 wheel_color (`str`): Color to make the wheel of the car. 63 tag (`str`): The tag to assign to the shape. 64 """ 65 x, y = top_left 66 rectangle((x + 5 * size / 10, y), size, size / 10 * 4, color=body_color, tag=tag) 67 rectangle( 68 (x, y + size - 7 * size / 10), 69 size * 2, 70 size / 10 * 4.5, 71 color=body_color, 72 tag=tag, 73 ) 74 circle( 75 (x + 5 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag 76 ) 77 circle( 78 (x + 15 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag 79 )
Draws a cool car.
Arguments:
- top_left (
tuple): A coordinate at which to draw the car. - body_color (
str): Color to make the body of the car. - wheel_color (
str): Color to make the wheel of the car. - tag (
str): The tag to assign to the shape.
82def circle(center=(0, 0), radius=25, color="hot pink", outline="", tag="", ): 83 """ 84 A reporter function that draws a circle. 85 Args: 86 center (`tuple`): A coordinate representing the center of the shape. 87 radius (`int`): Specifies the circle"s radius. 88 color (`str`): What color to draw the shape. 89 outline (`str`): What color should the border of the shape be. 90 tag (`str`): The tag to assign to the shape. 91 92 Returns: 93 `Shape`: The circle that was created. 94 """ 95 return oval( 96 center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 97 )
A reporter function that draws a circle.
Arguments:
- center (
tuple): A coordinate representing the center of the shape. - radius (
int): Specifies the circle's radius. - color (
str): What color to draw the shape. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The circle that was created.
100def cloud(center=(0, 0), size=30, color="white", tag=""): 101 """ 102 Reporter function that draws a cloud to the screen. 103 Args: 104 center (`tuple`): the point on which to center the cloud 105 size (`int`): how big (roughly) the cloud is drawn 106 color (`str`): which determines the color of the cloud 107 tag (`str`): to give the cloud a name 108 109 Returns: 110 `Shape`: The cloud that was created. 111 """ 112 for i in range(10): 113 x_offset = randint((-1 * size * 1.333), (size * 1.333)) 114 y_offset = randint(0, (size * 0.667)) 115 circle( 116 center=(center[0] + x_offset, center[1] + y_offset), 117 radius=randint((size * 0.667), (size * 1.667)), 118 color=color, 119 tag=tag, 120 ) 121 return tag
Reporter function that draws a cloud to the screen.
Arguments:
- center (
tuple): the point on which to center the cloud - size (
int): how big (roughly) the cloud is drawn - color (
str): which determines the color of the cloud - tag (
str): to give the cloud a name
Returns:
Shape: The cloud that was created.
124def diamond( 125 center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 126): 127 """ 128 A reporter function that draws a rectangle. 129 Args: 130 center (`tuple`): A coordinate representing the center of the shape. 131 width (`int`): How wide to draw the shape. 132 height (`int`): How tall to draw the shape. 133 color (`str`): What color to draw the shape. 134 outline (`str`): What color should the border of the shape be. 135 tag (`str`): The tag to assign to the shape. 136 137 Returns: 138 `Shape`: The shape that was created. 139 """ 140 point_0 = (center[0] - width / 2, center[1]) 141 point_1 = (center[0], center[1] - height / 2) 142 point_2 = (center[0] + width / 2, center[1]) 143 point_3 = (center[0], center[1] + height / 2) 144 return _a_canvas.create_polygon( 145 point_0, 146 point_1, 147 point_2, 148 point_3, 149 fill=_safe_color(color), 150 tags=tag, 151 outline=outline, 152 , 153 )
A reporter function that draws a rectangle.
Arguments:
- center (
tuple): A coordinate representing the center of the shape. - width (
int): How wide to draw the shape. - height (
int): How tall to draw the shape. - color (
str): What color to draw the shape. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The shape that was created.
156def grid(width=None, height=None, interval=100, show_labels=True): 157 """ 158 Draws a grid on a screen with intervals of 100. 159 160 Args: 161 width (`int`): The width of the grid to draw (defaults to the whole window) 162 height (`int`): The height of the grid to draw (defaults to the whole window) 163 interval (`int`): The interval to draw the grid on. 164 show_labels (`bool`): Whether or not to show coordinate labels. 165 166 """ 167 168 if width is None 169 width = get_window_width() 170 171 if height is None 172 height = get_window_height() 173 174 # Creates all vertical lines at intervals of 100 175 for i in range(0, width, interval): 176 _a_canvas.create_line(i, 0, i, height, tag="grid", fill="black") 177 # Creates all horizontal lines at intervals of 100 178 for i in range(0, height, interval): 179 _a_canvas.create_line(0, i, width, i, tag="grid", fill="black") 180 181 if show_labels 182 # Creates axis labels 183 offset = 2 184 for y in range(0, height, interval): 185 for x in range(0, width, interval): 186 _a_canvas.create_oval( 187 x - offset, 188 y - offset, 189 x + offset, 190 y + offset, 191 fill="black", 192 tag="grid", 193 ) 194 _a_canvas.create_text( 195 x + offset, 196 y + offset, 197 text="({0}, {1})".format(x, y), 198 anchor="nw", 199 font=("Purisa", 8), 200 fill="black", 201 tag="grid", 202 )
Draws a grid on a screen with intervals of 100.
Arguments:
- width (
int): The width of the grid to draw (defaults to the whole window) - height (
int): The height of the grid to draw (defaults to the whole window) - interval (
int): The interval to draw the grid on. - show_labels (
bool): Whether or not to show coordinate labels.
208def image(image_path, position=(200, 200), rotation=None, scale=None, tag="", ): 209 """ 210 Draws a given image on the screen. NOTE: Requires the `pillow` package to be installed - contact 211 Prof. Bain or post on edSTEM if you"d like more details! 212 213 Args: 214 image_path (`str`): Location of the image file on your computer. 215 position (`tuple`): A coordinate at which to render the image. 216 rotation (`int`): A number of degrees to rotate the given image. 217 scale (`int`): A scaling factor to multiply the image size by. 218 tag (`str`): A string representing the "name" fo this shape. 219 """ 220 # import PIL libraries 221 from PIL import Image, ImageTk 222 223 anchor = "nw" 224 225 import os 226 227 # 1. create PIL image and apply any image transformations: 228 dir_path = os.path.dirname(os.path.realpath(__file__)) 229 image_path = os.path.join(dir_path, image_path) 230 pil_image = Image.open(image_path) 231 if scale 232 size = (round(pil_image.size[0] * scale), round(pil_image.size[1] * scale)) 233 pil_image = pil_image.resize(size) 234 if rotation 235 pil_image = pil_image.rotate(rotation) # note: returns a copy 236 237 # 2. convert to tkinter-compatible image format: 238 tkinter_image = ImageTk.PhotoImage(pil_image) 239 _cache.append( 240 tkinter_image 241 ) # workaround for known tkinter bug: http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm 242 243 # 3. draw image on canvas: 244 _a_canvas.create_image( 245 *position, image=tkinter_image, anchor=anchor, tags=tag, 246 )
Draws a given image on the screen. NOTE: Requires the pillow package to be installed - contact
Prof. Bain or post on edSTEM if you'd like more details!
Arguments:
- image_path (
str): Location of the image file on your computer. - position (
tuple): A coordinate at which to render the image. - rotation (
int): A number of degrees to rotate the given image. - scale (
int): A scaling factor to multiply the image size by. - tag (
str): A string representing the "name" fo this shape.
249def line(points=[], curvy=False, color="hot pink", tag="", ): 250 """ 251 A reporter function that draws a line given a list of points. 252 Args: 253 points (`list`): The points that define the line; this should be a list of tuples (coordinates). 254 curvy (`bool`): Makes a curvy line instead. 255 color (`str`): What color to make the shape. 256 tag (`str`): The tag to assign to the shape. 257 258 Returns: 259 `Shape`: The line that was created. 260 """ 261 return _a_canvas.create_line(points, fill=color, smooth=curvy, tags=tag, )
A reporter function that draws a line given a list of points.
Arguments:
- points (
list): The points that define the line; this should be a list of tuples (coordinates). - curvy (
bool): Makes a curvy line instead. - color (
str): What color to make the shape. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The line that was created.
264def oval( 265 center=(0, 0), 266 radius_x=25, 267 radius_y=50, 268 color="hot pink", 269 outline="", 270 tag="", 271 , 272): 273 """ 274 A reporter function that draws an oval. 275 Args: 276 center (`tuple`): A coordinate representing the center of the shape. 277 radius_x (`int`): Specifies the oval"s radius on the x-axis. 278 radius_y (`int`): Specifies the oval"s radius on the y-axis. 279 color (`str`): What color to draw the shape. 280 outline (`str`): What color should the border of the shape be. 281 tag (`str`): The tag to assign to the shape. 282 283 Returns: 284 `Shape`: The oval that was created. 285 """ 286 x = center[0] 287 y = center[1] 288 x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y) 289 steps = 100 290 # major and minor axes 291 a = (x1 - x0) / 2.0 292 b = (y1 - y0) / 2.0 293 # center 294 xc = x0 + a 295 yc = y0 + b 296 point_list = [] 297 # create the oval as a list of points 298 for i in range(steps): 299 # Calculate the angle for this step 300 theta = (pi * 2) * (float(i) / steps) 301 x = a * cos(theta) 302 y = b * sin(theta) 303 point_list.append(round(x + xc)) 304 point_list.append(round(y + yc)) 305 306 return _a_canvas.create_polygon( 307 point_list, fill=_safe_color(color), tags=tag, 308 )
A reporter function that draws an oval.
Arguments:
- center (
tuple): A coordinate representing the center of the shape. - radius_x (
int): Specifies the oval's radius on the x-axis. - radius_y (
int): Specifies the oval's radius on the y-axis. - color (
str): What color to draw the shape. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The oval that was created.
311def pixel_art(top_left, artwork, palette, pixel=10, tag=""): 312 """ 313 Draws a pixel art design! 314 315 Args: 316 top_left (`tuple`): the top left coordinate of the pixel art 317 artwork (sequence of sequences): the art to draw 318 palette (sequence): the palette of colors to use for each different square 319 pixel (`int`, optional): how big each individual pixel should be 320 tag (`str`, optional): the tag to assign to every square in the row 321 322 Note: this doesn"t return anything so make sure to use a tag if you want to animate / modify. 323 """ 324 x = top_left[0] 325 y = top_left[1] 326 for row in artwork 327 # draw each row at the specified (x, y) position: 328 _draw_row(row, (x, y), colors=palette, pixel=pixel, tag=tag) 329 # ...and don"t forget to shift the y-value down by the proper 330 # amount so that the next row won"t draw on top of the first one: 331 y += pixel
Draws a pixel art design!
Arguments:
- top_left (
tuple): the top left coordinate of the pixel art - artwork (sequence of sequences): the art to draw
- palette (sequence): the palette of colors to use for each different square
- pixel (
int, optional): how big each individual pixel should be - tag (
str, optional): the tag to assign to every square in the row
Note: this doesn't return anything so make sure to use a tag if you want to animate / modify.
334def polygon(points=[], color="hot pink", outline="", tag="", ): 335 """ 336 A reporter function that draws a polygon given a list of points. 337 Args: 338 points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates). 339 defaults to an empty list. 340 outline (`str`): What color should the border of the shape be. 341 color (`str`): What color to make the shape. 342 343 Returns: 344 `Shape`: The polygon that was created. 345 """ 346 return _a_canvas.create_polygon(points, fill=_safe_color(color), tags=tag, )
A reporter function that draws a polygon given a list of points.
Arguments:
- points (
list): The points outlining the polygon; this should be a list of tuples (coordinates). defaults to an empty list. - outline (
str): What color should the border of the shape be. - color (
str): What color to make the shape.
Returns:
Shape: The polygon that was created.
349def rectangle( 350 top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 351): 352 """ 353 A reporter function that draws a rectangle. 354 Args: 355 top_left (`tuple`): A coordinate representing the top left-hand corner of the shape. 356 width (`int`): How wide to draw the shape. 357 height (`int`): How tall to draw the shape. 358 color (`str`): What color to draw the shape. 359 outline (`str`): What color should the border of the shape be. 360 tag (`str`): The tag to assign to the shape. 361 362 Returns: 363 `Shape`: The rectangle that was created. 364 """ 365 point_0 = top_left 366 point_1 = (top_left[0] + width, top_left[1]) 367 point_2 = (top_left[0] + width, top_left[1] + height) 368 point_3 = (top_left[0], top_left[1] + height) 369 return _a_canvas.create_polygon( 370 point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 371 )
A reporter function that draws a rectangle.
Arguments:
- top_left (
tuple): A coordinate representing the top left-hand corner of the shape. - width (
int): How wide to draw the shape. - height (
int): How tall to draw the shape. - color (
str): What color to draw the shape. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The rectangle that was created.
374def spiral( 375 center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 376): 377 """ 378 A reporter function that draws a spiral. 379 Args: 380 center (`tuple`): A coordinate representing the center of the shape. 381 width (`int`): Specifies the total width of the spiral. 382 roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y) 383 start (`int`): Where on the spiral to start drawing. 384 spirals (`int`): How many loops to draw. 385 line_width (`int`): How wide for the line to be drawn. 386 tag (`str`): The tag to assign to the shape. 387 388 Returns: 389 `Shape`: The spiral that was created. 390 """ 391 theta = 0.0 392 r = start 393 all_points = [] 394 prev_pos = _polar_to_cartesian(r, theta) 395 distance = width / 4 / pi / spirals 396 all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1])) 397 while theta < 2 * spirals * pi 398 theta += roughness 399 r = start + distance * theta 400 pos = _polar_to_cartesian(r, theta) 401 all_points.append((pos[0] + center[0], pos[1] + center[1])) 402 403 return arc(points=all_points, width=line_width, )
A reporter function that draws a spiral.
Arguments:
- center (
tuple): A coordinate representing the center of the shape. - width (
int): Specifies the total width of the spiral. - roughness (
float): Controls how spiral-y the shape is (lower is less spiral-y) - start (
int): Where on the spiral to start drawing. - spirals (
int): How many loops to draw. - line_width (
int): How wide for the line to be drawn. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The spiral that was created.
406def square(top_left=(0, 0), size=25, color="hot pink", outline="", tag="", ): 407 """ 408 A reporter function that draws a square. 409 Args: 410 top_left (`tuple`): A coordinate representing the top left-hand corner of the shape. 411 size (`int`): How big to draw the shape. 412 color (`str`): What color to draw the shape. 413 outline (`str`): What color should the border of the shape be. 414 tag (`str`): The tag to assign to the shape. 415 416 Returns: 417 `Shape`: The square that was created. 418 """ 419 return rectangle( 420 top_left=top_left, width=size, height=size, color=color, tag=tag, 421 )
A reporter function that draws a square.
Arguments:
- top_left (
tuple): A coordinate representing the top left-hand corner of the shape. - size (
int): How big to draw the shape. - color (
str): What color to draw the shape. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The square that was created.
424def star( 425 center=(0, 0), 426 radius=50, 427 color="hot pink", 428 outer_radius=75, 429 points=5, 430 outline="", 431 tag="", 432 , 433): 434 """ 435 A reporter function that draws a star. 436 Args: 437 center (`tuple`): A coordinate representing the center of the shape. 438 radius (`int`): Specifies the radius of the inside part of the star. 439 color (`str`): Specifies the color of the star. 440 outer_radius (`int`): Specifies the radius of the outside part of the star. 441 points (`int`): Specifies the number of points for the star. 442 outline (`str`): What color should the border of the shape be. 443 tag (`str`): The tag to assign to the shape. 444 445 Returns: 446 `Shape`: The star that was created. 447 """ 448 arc_segment = 360 / points 449 vertices = [] 450 for i in range(points): 451 inner_point = ( 452 radius * cos(radians(arc_segment * i)) + center[0], 453 -1 * radius * sin(radians(arc_segment * i)) + center[1], 454 ) 455 vertices.append(inner_point) 456 outer_point = ( 457 outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0], 458 -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2)) 459 + center[1], 460 ) 461 vertices.append(outer_point) 462 return polygon(vertices, color=color, tag=tag, )
A reporter function that draws a star.
Arguments:
- center (
tuple): A coordinate representing the center of the shape. - radius (
int): Specifies the radius of the inside part of the star. - color (
str): Specifies the color of the star. - outer_radius (
int): Specifies the radius of the outside part of the star. - points (
int): Specifies the number of points for the star. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The star that was created.
465def text( 466 top_left=(0, 0), text="", font=("Purisa", 32), color="black", tag="", 467): 468 """ 469 A reporter function that draws text to the screen 470 Args: 471 top_left (`tuple`): coordinate pair to specify the location. 472 text (`str`): What text to draw. 473 font (`tuple`): A tuple where the first element is a string for the font name and the second is an 474 int with the font size. 475 color (`str`): What color should the text be. 476 tag (`str`): The name to tag this thing with. 477 478 Returns: 479 `Shape`: The text that was created. 480 """ 481 return _a_canvas.create_text( 482 top_left, text=text, font=font, fill=color, tags=tag, 483 )
A reporter function that draws text to the screen
Arguments:
- top_left (
tuple): coordinate pair to specify the location. - text (
str): What text to draw. - font (
tuple): A tuple where the first element is a string for the font name and the second is an int with the font size. - color (
str): What color should the text be. - tag (
str): The name to tag this thing with.
Returns:
Shape: The text that was created.
486def triangle( 487 bottom_center=(0, 0), 488 width=25, 489 top_shift=0, 490 height=0, 491 color="hot pink", 492 outline="", 493 tag="", 494 , 495): 496 """ 497 A reporter function that draws a triangle. 498 Args: 499 bottom_center (`tuple`): A coordinate representing the bottom center of the shape. 500 width (`int`): Specifies the width of the base of the triangle. 501 top_shift (`int`): Specifies the how far to the left or right to shift the top of 502 the triangle from the bottom center. 503 height (`int`): Specifies the triangle"s height. 504 color (`str`): What color to draw the shape. 505 outline (`str`): What color should the border of the shape be. 506 tag (`str`): The tag to assign to the shape. 507 508 Returns: 509 `Shape`: The triangle that was created. 510 """ 511 if height == 0 512 height = width * sqrt(3) / 2 513 point_0 = (bottom_center[0] - width / 2, bottom_center[1]) 514 point_1 = (bottom_center[0] + width / 2, bottom_center[1]) 515 point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height) 516 517 return _a_canvas.create_polygon( 518 point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 519 )
A reporter function that draws a triangle.
Arguments:
- bottom_center (
tuple): A coordinate representing the bottom center of the shape. - width (
int): Specifies the width of the base of the triangle. - top_shift (
int): Specifies the how far to the left or right to shift the top of the triangle from the bottom center. - height (
int): Specifies the triangle's height. - color (
str): What color to draw the shape. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The triangle that was created.
522def wedge( 523 center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="", 524): 525 """ 526 A reporter function that draws a circle. 527 Args: 528 center (`tuple`): A coordinate representing the center of the shape. 529 radius (`int`): Specifies the circle"s radius. 530 angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw. 531 color (`str`): What color to draw the shape. 532 outline (`str`): What color should the border of the shape be. 533 tag (`str`): The tag to assign to the shape. 534 535 Returns: 536 `Shape`: The wedge that was created. 537 """ 538 point_list = [center[0], center[1]] 539 for i in range(0, 0 + angle): 540 x1 = center[0] + radius * cos(radians(i)) 541 point_list.append(x1) 542 y1 = center[1] + radius * sin(radians(i)) 543 point_list.append(y1) 544 545 point_list.append(center[0]) 546 point_list.append(center[1]) 547 548 return _a_canvas.create_polygon( 549 point_list, fill=_safe_color(color), outline=outline, tags=tag, 550 )
A reporter function that draws a circle.
Arguments:
- center (
tuple): A coordinate representing the center of the shape. - radius (
int): Specifies the circle's radius. - angle (
int): A number between 0 and 360 that specifies how much of the circle to draw. - color (
str): What color to draw the shape. - outline (
str): What color should the border of the shape be. - tag (
str): The tag to assign to the shape.
Returns:
Shape: The wedge that was created.
556def above(shape1, shape2, offset_x=0, offset_y=0): 557 """ 558 A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center 559 to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any 560 specified offset. 561 562 Args: 563 shape1 (`Shape` or Tag): The first shape to use. 564 shape2 (`Shape` or Tag): The second shape to use. 565 offset_x (`int`): How much to shift shape 2 in the x-direction after moving it. 566 offset_y (`int`): How much to shift shape 2 in the x-direction after moving it. 567 568 Returns: 569 `Shape`: The modified shape1. 570 """ 571 overlay(shape1, shape2) 572 _a_canvas.move( 573 shape1, 574 0 + offset_x, 575 -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y, 576 ) 577 return shape1
A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any specified offset.
Arguments:
- shape1 (
Shapeor Tag): The first shape to use. - shape2 (
Shapeor Tag): The second shape to use. - offset_x (
int): How much to shift shape 2 in the x-direction after moving it. - offset_y (
int): How much to shift shape 2 in the x-direction after moving it.
Returns:
Shape: The modified shape1.
580def align(shape1, shape2, via="middle", offset_x=0, offset_y=0): 581 """ 582 A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with 583 whatever property of `shape2` is selected with the `via` input. 584 585 Args: 586 shape1 (`Shape` or Tag): The first shape to use. 587 shape2 (`Shape` or Tag): The second shape to use. 588 via (`str`): Has to be one of, the following options: `"center"` (horizontal center), 589 `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"` 590 offset_x (`int`): How much to shift in the x-axis after alignment 591 offset_y (`int`): How much to shift in the y-axis after alignment 592 593 Returns: 594 `Shape`: The modified shape1. 595 """ 596 via_options = ["center", "middle", "top", "bottom", "left", "right"] 597 if via not in via_options 598 raise ValueError( 599 "The via input must be one of " 600 + (via_options) 601 + " but instead we found " 602 + (via) 603 ) 604 605 outline1 = _get_outline(shape1) 606 outline2 = _get_outline(shape2) 607 608 if via == "center" 609 _a_canvas.move( 610 shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y 611 ) 612 613 elif via == "middle" 614 _a_canvas.move( 615 shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y 616 ) 617 618 elif via == "top" 619 _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y) 620 621 elif via == "bottom" 622 _a_canvas.move( 623 shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y 624 ) 625 626 elif via == "left" 627 _a_canvas.move( 628 shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y 629 ) 630 631 elif via == "right" 632 _a_canvas.move( 633 shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y 634 ) 635 636 return shape1
A reporter function that aligns shape1 with shape2. It does this by moving shape1 to align with
whatever property of shape2 is selected with the via input.
Arguments:
- shape1 (
Shapeor Tag): The first shape to use. - shape2 (
Shapeor Tag): The second shape to use. - via (
str): Has to be one of, the following options:"center"(horizontal center),"middle"(vertical center),"top","bottom","left", or"right" - offset_x (
int): How much to shift in the x-axis after alignment - offset_y (
int): How much to shift in the y-axis after alignment
Returns:
Shape: The modified shape1.
639def beside(shape1, shape2, offset_x=0, offset_y=0): 640 """ 641 A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center 642 to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any 643 specified offset. 644 645 Args: 646 shape1 (`Shape` or Tag): The first shape to use. 647 shape2 (`Shape` or Tag): The second shape to use. 648 offset_x (`int`): How much to shift shape 2 in the x-direction after moving it. 649 offset_y (`int`): How much to shift shape 2 in the x-direction after moving it. 650 651 Returns: 652 `Shape`: The modified shape1. 653 """ 654 overlay(shape1, shape2) 655 _a_canvas.move( 656 shape1, 657 (get_width(shape2) + get_width(shape1)) / 2 + offset_x, 658 0 + offset_y, 659 ) 660 return shape1
A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any specified offset.
Arguments:
- shape1 (
Shapeor Tag): The first shape to use. - shape2 (
Shapeor Tag): The second shape to use. - offset_x (
int): How much to shift shape 2 in the x-direction after moving it. - offset_y (
int): How much to shift shape 2 in the x-direction after moving it.
Returns:
Shape: The modified shape1.
663def below(shape1, shape2, offset_x=0, offset_y=0): 664 """ 665 A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center 666 to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any 667 specified offset. 668 669 Args: 670 shape1 (`Shape` or Tag): The first shape to use. 671 shape2 (`Shape` or Tag): The second shape to use. 672 offset_x (`int`): How much to shift shape 2 in the x-direction after moving it. 673 offset_y (`int`): How much to shift shape 2 in the x-direction after moving it. 674 675 Returns: 676 `Shape`: The modified shape1. 677 """ 678 overlay(shape1, shape2) 679 _a_canvas.move( 680 shape1, 681 0 + offset_x, 682 (get_height(shape2) + get_height(shape1)) / 2 + offset_y, 683 ) 684 return shape1
A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any specified offset.
Arguments:
- shape1 (
Shapeor Tag): The first shape to use. - shape2 (
Shapeor Tag): The second shape to use. - offset_x (
int): How much to shift shape 2 in the x-direction after moving it. - offset_y (
int): How much to shift shape 2 in the x-direction after moving it.
Returns:
Shape: The modified shape1.
687def change_color(shape, color): 688 """ 689 Change the fill color of a tagged object. 690 691 Args: 692 shape (`Shape` or Tag): The shape or tag to re-fill. 693 color (`str`): A color name or hex code to re-fill with. 694 """ 695 ids = _a_canvas.find_withtag(shape) 696 for id in ids 697 _a_canvas.itemconfig(id, fill=color)
Change the fill color of a tagged object.
Arguments:
- shape (
Shapeor Tag): The shape or tag to re-fill. - color (
str): A color name or hex code to re-fill with.
700def delete(shape): 701 """ 702 A function that deletes a shape from our screen. 703 704 Args: 705 shape (`Shape` or Tag): The shape to delete. 706 """ 707 _a_canvas.delete(shape)
A function that deletes a shape from our screen.
Arguments:
- shape (
Shapeor Tag): The shape to delete.
710def assign_tag(shape, tag): 711 """ 712 A function that assigns a `Shape` or other tagged object a new tag. This will 713 overwrite any existing tag that matches the provided `tag` argument. This means that if you have 714 a shape with multiple tags, _this function will only overwrite that one tag_. You would need to run 715 the function multiple times to rewrite the remaining tags. 716 717 Args: 718 shape (`Shape` or Tag): The shape to which you"d like to assign a new tag 719 tag (`str`): A new valid tag for this shape. 720 721 """ 722 ids = _a_canvas.find_withtag(shape) 723 for id in ids 724 the_tags = (_a_canvas.gettags(id)) 725 if shape in the_tags # if it has a tag replace it 726 index = the_tags.index(shape) 727 the_tags[index] = tag 728 else # otherwise it didn"t have a tag 729 the_tags.append(tag) 730 _a_canvas.itemconfig(id, tags=the_tags)
A function that assigns a Shape or other tagged object a new tag. This will
overwrite any existing tag that matches the provided tag argument. This means that if you have
a shape with multiple tags, _this function will only overwrite that one tag_. You would need to run
the function multiple times to rewrite the remaining tags.
Arguments:
- shape (
Shapeor Tag): The shape to which you'd like to assign a new tag - tag (
str): A new valid tag for this shape.
733def duplicate(shape, color=None): 734 """ 735 A reporter function that perfectly copies a shape and returns that copy. 736 737 Args: 738 shape (`Shape` or Tag): The shape to duplicate. 739 color (`str`): A new color to use with the duplicated shape. 740 741 Returns: 742 `Shape`: The new duplicated shape. 743 """ 744 shape_type = _a_canvas.type(shape) 745 shape_config = _a_canvas.itemconfig(shape) 746 shape_coords = _a_canvas.coords(shape) 747 the_copy = None 748 if shape_type == "polygon" 749 new_config = {key shape_config[key][-1] for key in shape_config.keys()} 750 if color != None 751 new_config["fill"] = color 752 the_copy = _a_canvas.create_polygon(shape_coords, new_config) 753 return the_copy
A reporter function that perfectly copies a shape and returns that copy.
Arguments:
- shape (
Shapeor Tag): The shape to duplicate. - color (
str): A new color to use with the duplicated shape.
Returns:
Shape: The new duplicated shape.
756def mirror(shape): 757 """ 758 A function that takes a shape and flips it across its vertical 759 axis, returning the modified shape. 760 761 Args: 762 shape (`Shape` or Tag): The shape in question. 763 764 """ 765 center = get_center(shape)[0] 766 shape_ids = _a_canvas.find_withtag(shape) 767 for shape_id in shape_ids 768 flipped_coordinates = [] 769 shape_coords = _a_canvas.coords(shape_id) 770 counter = 0 771 for num in shape_coords 772 if counter % 2 == 0 773 if num < center 774 flipped_coordinates.append(num + 2 * (center - num)) 775 elif num > center 776 flipped_coordinates.append(num - 2 * (num - center)) 777 else 778 flipped_coordinates.append(num) 779 else 780 flipped_coordinates.append(num) 781 counter += 1 782 _a_canvas.coords(shape_id, flipped_coordinates)
A function that takes a shape and flips it across its vertical axis, returning the modified shape.
Arguments:
- shape (
Shapeor Tag): The shape in question.
785def move(shape, x_shift=0, y_shift=0): 786 """ 787 Purpose: Move the x and y position of all shapes that have been tagged 788 with the tag argument 789 790 Args: 791 shape (`Shape` or Tag): The shape in question. 792 x_shift (`int`; optional): amount to move in the x direction 793 y_shift (`int`; optional): amount to move in the y direction 794 """ 795 shape_ids = _a_canvas.find_withtag(shape) 796 for id in shape_ids 797 _a_canvas.move(id, x_shift, y_shift)
Purpose: Move the x and y position of all shapes that have been tagged with the tag argument
Arguments:
- shape (
Shapeor Tag): The shape in question. - x_shift (
int; optional): amount to move in the x direction - y_shift (
int; optional): amount to move in the y direction
800def move_to(tag, to, anchor="center"): 801 """ 802 Move the given tagged item to a particular `point` maintaining some `anchor`. 803 Note: this is NOT the same as the `move` function which moves an object by a specific amount. 804 805 Args: 806 tag (Shape or `str`): the shape (or shapes) to move 807 to (`tuple`): the `(x, y)` coordinate to which you wish to move the tagged object 808 anchor (`str`): which point on the shape do you want to move toward the given tuple. You can 809 use either `"center"` (default), `"top_left"`, `"top_right"`, `"bottom_left"`, or `"bottom_right"`. 810 """ 811 anchor_options = ["center", "top_left", "top_right", "bottom_left", "bottom_right"] 812 if anchor not in anchor_options 813 raise ValueError( 814 "The anchor input must be one of " 815 + (anchor_options) 816 + " but instead we found " 817 + (anchor) 818 ) 819 820 outline = _get_outline(tag) 821 delta_x = 0 822 delta_y = 0 823 824 if anchor == "top_left" 825 delta_x = to[0] - outline["left"] 826 delta_y = to[1] - outline["top"] 827 elif anchor == "top_right" 828 delta_x = to[0] - outline["right"] 829 delta_y = to[1] - outline["top"] 830 elif anchor == "bottom_right" 831 delta_x = to[0] - outline["right"] 832 delta_y = to[1] - outline["bottom"] 833 elif anchor == "bottom_left" 834 delta_x = to[0] - outline["left"] 835 delta_y = to[1] - outline["bottom"] 836 elif anchor == "center" 837 delta_x = to[0] - outline["center"][0] 838 delta_y = to[1] - outline["center"][1] 839 840 _a_canvas.move(tag, delta_x, delta_y)
Move the given tagged item to a particular point maintaining some anchor.
Note: this is NOT the same as the move function which moves an object by a specific amount.
Arguments:
- tag (Shape or
str): the shape (or shapes) to move - to (
tuple): the(x, y)coordinate to which you wish to move the tagged object - anchor (
str): which point on the shape do you want to move toward the given tuple. You can use either"center"(default),"top_left","top_right","bottom_left", or"bottom_right".
843def overlay(shape1, shape2, offset_x=0, offset_y=0): 844 """ 845 A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center 846 to shape 2"s center, and then applying any specified offset. 847 Args: 848 shape1 (`Shape` or Tag): The first shape to use. 849 shape2 (`Shape` or Tag): The second shape to use. 850 offset_x (`int`): How much to shift shape 2 in the x-direction after centering it. 851 offset_y (`int`): How much to shift shape 2 in the x-direction after centering it. 852 853 Returns: 854 `Shape`: The modified shape1. 855 """ 856 center1 = get_center(shape1) 857 center2 = get_center(shape2) 858 _a_canvas.move( 859 shape1, 860 (center2[0] - center1[0]) + offset_x, 861 (center2[1] - center1[1]) + offset_y, 862 ) 863 _a_canvas.tag_raise(shape1, shape2) 864 return shape1
A reporter function that overlays shape1 onto shape2. It does this by moving shape 1's center to shape 2's center, and then applying any specified offset.
Arguments:
- shape1 (
Shapeor Tag): The first shape to use. - shape2 (
Shapeor Tag): The second shape to use. - offset_x (
int): How much to shift shape 2 in the x-direction after centering it. - offset_y (
int): How much to shift shape 2 in the x-direction after centering it.
Returns:
Shape: The modified shape1.
867def portion(shape, start=0, end=0.5): 868 """ 869 Purpose: Take a slice or portion of some already created shape. 870 871 Args: 872 shape (`Shape` or Tag): The shape to take a portion of 873 start (`float`): A number between 0 and 1 representing where to start the slice. 874 end (`float`): A number between 0 and 1 representing where to end the slice. 875 876 For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle. 877 878 Note: this function is experimental. It might produce unexpected results! 879 """ 880 all_shapes = _a_canvas.find_withtag(shape) 881 882 for a_shape in all_shapes 883 coords = _a_canvas.coords(a_shape) 884 885 start_coord = floor(start * len(coords)) 886 if start_coord % 2 == 1 887 start_coord = start_coord - 1 # need to start with an x,y pair 888 end_coord = floor(end * len(coords)) 889 if end_coord % 2 == 1 890 end_coord = end_coord - 1 # need to end with an x,y pair 891 892 # slice is up to not including so get the last x,y pair 893 new_coords = coords[start_coord end_coord + 2] 894 895 # loop shape back in on itself 896 new_coords.append(new_coords[0]) 897 new_coords.append(new_coords[1]) 898 899 # set the coordinates: 900 _a_canvas.coords(a_shape, new_coords)
Purpose: Take a slice or portion of some already created shape.
Arguments:
- shape (
Shapeor Tag): The shape to take a portion of - start (
float): A number between 0 and 1 representing where to start the slice. - end (
float): A number between 0 and 1 representing where to end the slice.
For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.
Note: this function is experimental. It might produce unexpected results!
903def put_in_back(shape): 904 """ 905 A function that "lowers" a shape to the "bottom" of the screen." 906 907 Args: 908 shape (`Shape` or Tag): The shape in question. 909 """ 910 _a_canvas.tag_lower(shape)
A function that "lowers" a shape to the "bottom" of the screen."
Arguments:
- shape (
Shapeor Tag): The shape in question.
913def put_in_front(shape): 914 """ 915 A function that "raises" a shape to the "top" of the screen." 916 917 Args: 918 shape (`Shape` or Tag): The shape in question. 919 """ 920 _a_canvas.tag_raise(shape)
A function that "raises" a shape to the "top" of the screen."
Arguments:
- shape (
Shapeor Tag): The shape in question.
923def rotate(shape, degrees=5, origin=None): 924 """ 925 A reporter function that takes a shape and rotates it by a specified amount around a specified point. 926 It does this by interpolating a polygon around the shape and calculating the shifts of individual 927 points on the edge of the polygon. 928 929 Args: 930 shape (`Shape` or Tag): The shape to rotate. 931 degrees (`int`): The number of degrees to rotate the shape. 932 origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center 933 of the given shape. 934 935 Returns: 936 `Shape`: The modified shape. 937 """ 938 if origin is None 939 origin = get_center(shape) 940 941 theta = radians(degrees) 942 ox, oy = origin 943 944 all_shapes = _a_canvas.find_withtag(shape) 945 946 for a_shape in all_shapes 947 coords = _a_canvas.coords(a_shape) 948 # update coordinates: 949 for i in range(0, len(coords), 2): 950 px, py = coords[i], coords[i + 1] 951 qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox 952 qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy 953 coords[i] = qx 954 coords[i + 1] = qy 955 # set the coordinates: 956 _a_canvas.coords(a_shape, coords) 957 958 return shape
A reporter function that takes a shape and rotates it by a specified amount around a specified point. It does this by interpolating a polygon around the shape and calculating the shifts of individual points on the edge of the polygon.
Arguments:
- shape (
Shapeor Tag): The shape to rotate. - degrees (
int): The number of degrees to rotate the shape. - origin (
tuple): An(x,y)coordinate about which to perform the rotation. Defaults to the center of the given shape.
Returns:
Shape: The modified shape.
961def scale(shape, x_scale=1.0, y_scale=1.0): 962 """ 963 A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis. 964 965 The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause 966 the shape to grow along that access. Values less than 1.0 will cause the shape to shrink. 967 968 Args: 969 shape (`Shape` or Tag): The shape or tag to re-fill. 970 x_scale (`float`): How much to scale in the x-axis. 971 y_scale (`float`): How much to scale in the y-axis. 972 """ 973 ids = _a_canvas.find_withtag(shape) 974 975 coord = get_center(shape) 976 977 for i in ids 978 _a_canvas.scale(i, coord[0], coord[1], x_scale, y_scale)
A function that takes a given Shape or tag and scales it on either/both the x and y-axis.
The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.
Arguments:
- shape (
Shapeor Tag): The shape or tag to re-fill. - x_scale (
float): How much to scale in the x-axis. - y_scale (
float): How much to scale in the y-axis.
981def underlay(shape1, shape2, offset_x=0, offset_y=0): 982 """ 983 A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center 984 to shape 2"s center, and then applying any specified offset. 985 Args: 986 shape1 (`Shape` or Tag): The first shape to use. 987 shape2 (`Shape` or Tag): The second shape to use. 988 offset_x (`int`): How much to shift shape 2 in the x-direction after centering it. 989 offset_y (`int`): How much to shift shape 2 in the x-direction after centering it. 990 991 Returns: 992 `Shape`: The modified shape1. 993 """ 994 center1 = get_center(shape1) 995 center2 = get_center(shape2) 996 _a_canvas.move( 997 shape1, 998 (center2[0] - center1[0]) + offset_x, 999 (center2[1] - center1[1]) + offset_y, 1000 ) 1001 _a_canvas.tag_lower(shape1, shape2) 1002 return shape1
A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1's center to shape 2's center, and then applying any specified offset.
Arguments:
- shape1 (
Shapeor Tag): The first shape to use. - shape2 (
Shapeor Tag): The second shape to use. - offset_x (
int): How much to shift shape 2 in the x-direction after centering it. - offset_y (
int): How much to shift shape 2 in the x-direction after centering it.
Returns:
Shape: The modified shape1.
1008def clear_window(keep_grid=True): 1009 """ 1010 A function that deletes everything from the window. 1011 1012 Args: 1013 keep_grid (`bool`): Whether or not to keep the grid. 1014 """ 1015 all_shapes = _a_canvas.find_all() 1016 1017 for shape in all_shapes 1018 tags = _a_canvas.gettags(shape) 1019 if "grid" in tags and keep_grid 1020 continue 1021 _a_canvas.delete(shape) 1022 1023 global _resize_enabled 1024 _resize_enabled = True
A function that deletes everything from the window.
Arguments:
- keep_grid (
bool): Whether or not to keep the grid.
1027def distance(point1, point2): 1028 """ 1029 A reporter function calculates the distance between two `(x, y)` coordinates. 1030 1031 Args: 1032 point1 (`tuple`): The first `(x, y)` coordinate. 1033 point2 (`tuple`): The second `(x, y)` coordinate. 1034 1035 Returns: 1036 A `float` representing the distance between the two points. 1037 """ 1038 return sqrt(((point1[0] - point2[0]) 2) + ((point1[1] - point2[1]) 2))
A reporter function calculates the distance between two (x, y) coordinates.
Arguments:
- point1 (
tuple): The first(x, y)coordinate. - point2 (
tuple): The second(x, y)coordinate.
Returns:
A
floatrepresenting the distance between the two points.
1041def does_tag_exist(tag): 1042 """ 1043 Returns `True` if a given tag exists otherwise returns `False`. 1044 1045 Args: 1046 `tag` (`str`): [Required] The tag of the object to lookup. 1047 1048 """ 1049 result = _a_canvas.find_withtag(tag) 1050 1051 if result 1052 return True 1053 else 1054 return False
Returns True if a given tag exists otherwise returns False.
Arguments:
tag(str): [Required] The tag of the object to lookup.
1057def get_bottom(shape): 1058 """ 1059 A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped). 1060 1061 Args: 1062 shape (`Shape` or Tag): The shape in question. 1063 1064 Returns: 1065 A `int` representing the maximum y-coordinate of the shape. 1066 """ 1067 bbox = _safe_bbox(shape) 1068 return bbox[3]
A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).
Arguments:
- shape (
Shapeor Tag): The shape in question.
Returns:
A
intrepresenting the maximum y-coordinate of the shape.
1071def get_center(shape): 1072 """ 1073 A reporter function calculates the a coordinate at the center of some shape. 1074 1075 Args: 1076 shape (`Shape` or Tag): The shape in question. 1077 1078 Returns: 1079 A `tuple` representing center of the given shape. 1080 """ 1081 bbox = _safe_bbox(shape) 1082 1083 if bbox is None 1084 raise Exception( 1085 f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!" 1086 ) 1087 1088 return (((bbox[2] + bbox[0]) / 2), ((bbox[1] + bbox[3]) / 2))
A reporter function calculates the a coordinate at the center of some shape.
Arguments:
- shape (
Shapeor Tag): The shape in question.
Returns:
A
tuplerepresenting center of the given shape.
1091def get_colors(shape_or_shapes): 1092 """ 1093 A reporter function that returns all the colors associated with a tag or list of tags. 1094 1095 Args: 1096 shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of 1097 1098 Returns: 1099 A `List` containing all unique colors associated with that tag(s) 1100 """ 1101 all_shapes = [] 1102 if not isinstance(shape_or_shapes, ): 1103 shape_or_shapes = [shape_or_shapes] 1104 for shape in shape_or_shapes 1105 all_shapes += _a_canvas.find_withtag(shape) 1106 1107 all_colors = [] 1108 for shape in all_shapes 1109 color = _a_canvas.itemcget(shape, "fill") 1110 if color not in all_colors 1111 all_colors.append(color) 1112 1113 return all_colors
A reporter function that returns all the colors associated with a tag or list of tags.
Arguments:
- shape_or_shapes (
str/ShapeorList): the shape/tag or list of shapes/tags you'd like to find the colors of
Returns:
A
Listcontaining all unique colors associated with that tag(s)
1116def get_height(shape): 1117 """ 1118 A reporter function calculates the height of some given shape. 1119 1120 Args: 1121 shape (`Shape` or Tag): The shape in question. 1122 1123 Returns: 1124 A `int` representing the height of the shape. 1125 """ 1126 bbox = _safe_bbox(shape) 1127 return bbox[3] - bbox[1] - 1
A reporter function calculates the height of some given shape.
Arguments:
- shape (
Shapeor Tag): The shape in question.
Returns:
A
intrepresenting the height of the shape.
1130def get_left(shape): 1131 """ 1132 A reporter function calculates the minimum x-value of a given shape. 1133 1134 Args: 1135 shape (`Shape` or Tag): The shape in question. 1136 1137 Returns: 1138 A `int` representing the minimum x-coordinate of the shape. 1139 """ 1140 bbox = _safe_bbox(shape) 1141 return bbox[0]
A reporter function calculates the minimum x-value of a given shape.
Arguments:
- shape (
Shapeor Tag): The shape in question.
Returns:
A
intrepresenting the minimum x-coordinate of the shape.
1144def get_right(shape): 1145 """ 1146 A reporter function calculates the maximum x-value of a given shape. 1147 1148 Args: 1149 shape (`Shape` or Tag): The shape in question. 1150 1151 Returns: 1152 A `int` representing the maximum x-coordinate of the shape. 1153 """ 1154 bbox = _safe_bbox(shape) 1155 return bbox[2]
A reporter function calculates the maximum x-value of a given shape.
Arguments:
- shape (
Shapeor Tag): The shape in question.
Returns:
A
intrepresenting the maximum x-coordinate of the shape.
1158def get_tag_from_event(event, precision=25): 1159 """ 1160 Tries to return a tag of an object at a given mouse-event. 1161 1162 Args: 1163 event (`Event`): Must be a mouse event otherwise we"ll give back an error. 1164 precision (`int`): How precise in number of pixels does a user have be in order to "select" an object 1165 1166 Returns a blank string `""` if no shapes are found closer than `precision`. 1167 """ 1168 1169 if (event.type) not in [4, 6]: 1170 raise Exception(f"Received an event that isn"t a mouse event: {event}") 1171 1172 try 1173 x = event.x 1174 y = event.y 1175 shape_id = _a_canvas.find_closest(x, y) # get the top shape 1176 if shape_id and distance(get_center(shape_id), (x, y)) < precision 1177 tags = _a_canvas.gettags(shape_id) 1178 if len(tags) > 0 1179 return tags[0] 1180 return "" 1181 1182 except 1183 raise Exception( 1184 "No tag found! Maybe you passed us an event that isn"t a mouse event?" 1185 )
Tries to return a tag of an object at a given mouse-event.
Arguments:
- event (
Event): Must be a mouse event otherwise we'll give back an error. - precision (
int): How precise in number of pixels does a user have be in order to "select" an object
Returns a blank string "" if no shapes are found closer than precision.
1188def get_top(shape): 1189 """ 1190 A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped). 1191 1192 Args: 1193 shape (`Shape` or Tag): The shape in question. 1194 1195 Returns: 1196 A `int` representing the minimum y-coordinate of the shape. 1197 """ 1198 bbox = _safe_bbox(shape) 1199 return bbox[1]
A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).
Arguments:
- shape (
Shapeor Tag): The shape in question.
Returns:
A
intrepresenting the minimum y-coordinate of the shape.
1202def get_width(shape): 1203 """ 1204 A reporter function calculates the width of some given shape. 1205 1206 Args: 1207 shape (`Shape` or Tag): The shape in question. 1208 1209 Returns: 1210 An `int` representing width of the shape. 1211 """ 1212 bbox = _safe_bbox(shape) 1213 return bbox[2] - bbox[0] - 1
A reporter function calculates the width of some given shape.
Arguments:
- shape (
Shapeor Tag): The shape in question.
Returns:
An
intrepresenting width of the shape.
1216def get_window_height(): 1217 """ 1218 A reporter function that returns the current height of the window. 1219 1220 Returns: 1221 An `int` representing height of the window. 1222 """ 1223 return _a_canvas.winfo_height()
A reporter function that returns the current height of the window.
Returns:
An
intrepresenting height of the window.
1226def get_window_width(): 1227 """ 1228 A reporter function that returns the current width of the window. 1229 1230 Returns: 1231 An `int` representing width of the window. 1232 """ 1233 return _a_canvas.winfo_width()
A reporter function that returns the current width of the window.
Returns:
An
intrepresenting width of the window.
1236def interpolate_colors(color1, color2, frac): 1237 """ 1238 A reporter function that generates a new color between two given colors. 1239 Args: 1240 color1 (`str`): The path of the file to wrap 1241 color2 (`str`): The path of the file to wrap 1242 frac (`float`): What fraction of each color to take. An input of 0 returns 1243 color1, an input of 1 returns color2, an input of 0.5 returns a color 1244 perfectly between the two. 1245 1246 Returns: 1247 A color (as a hex `str`) to be used elsewhere 1248 """ 1249 if "#" not in color1 1250 color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1))) 1251 else 1252 color1 = _tupelize_color(color1) 1253 if "#" not in color2 1254 color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2))) 1255 else 1256 color2 = _tupelize_color(color2) 1257 return _interpolate_tuple(color1, color2, frac)
A reporter function that generates a new color between two given colors.
Arguments:
- color1 (
str): The path of the file to wrap - color2 (
str): The path of the file to wrap - frac (
float): What fraction of each color to take. An input of 0 returns color1, an input of 1 returns color2, an input of 0.5 returns a color perfectly between the two.
Returns:
A color (as a hex
str) to be used elsewhere
1260def random_color(): 1261 """ 1262 Returns a random color as a `string` to be used. 1263 It does not accept any inputs. 1264 """ 1265 r = lambda randint(0, 255) 1266 return "#%02X%02X%02X" % (r(), r(), r())
Returns a random color as a string to be used.
It does not accept any inputs.
1269def listen_for(event_str, handler_function, override=False): 1270 """ 1271 Sets up a listener for a given event on our window. 1272 1273 Args: 1274 event_str (`str`): The magic string that represents this event in the window 1275 handler_function (`func`): The name (not a string though) of the function you want called when the event his heard 1276 override (`bool`): Only use this if you speak to Prof. Bain and he recommends it. 1277 1278 The supported events are: 1279 * `"LEFT-CLICK"`: Left mouse click 1280 * `"RIGHT-CLICK"`: Right mouse click 1281 * `"ALT-CLICK"`: If you"re using a PC, this event might instead work for Right Click 1282 * `"LEFT-DRAG"`: Left mouse clicked and dragged on the screen 1283 * `"RIGHT-DRAG"`: Right mouse clicked and dragged on the screen 1284 * `"ALT-DRAG"`: For PCs, this event might instead work for RIGHT-DRAG 1285 * `"DOUBLE-LEFT"`: Left mouse double click 1286 * `"DOUBLE-RIGHT"`: Right mouse double click 1287 * `"DOUBLE-ALT"`: For PCs, this event might instead work for DOUBLE-RIGHT 1288 * `"KEY"`: The catch-all event for Keyboard presses 1289 """ 1290 1291 event_translator = { 1292 "LEFT-CLICK" "<Button-1>", 1293 "RIGHT-CLICK" "<Button-2>", 1294 "ALT-CLICK" "<Button-3>", 1295 "LEFT-DRAG" "<B1-Motion>", 1296 "RIGHT-DRAG" "<B2-Motion>", 1297 "ALT-DRAG" "<B3-Motion>", 1298 "DOUBLE-LEFT" "<Double-Button-1>", 1299 "DOUBLE-RIGHT" "<Double-Button-2>", 1300 "DOUBLE-ALT" "<Double-Button-3>", 1301 "KEY" "<Key>", 1302 } 1303 1304 if event_str not in event_translator and not override 1305 raise ( 1306 TypeError( 1307 f"The event you entered, {event_str}, isn"t supported. Here are the supported events: {[i for i in event_translator]}" 1308 ) 1309 ) 1310 1311 event = event_translator[event_str] 1312 1313 listen_for.tracker.add(event_str) 1314 1315 _a_canvas.bind(event, handler_function)
Sets up a listener for a given event on our window.
Arguments:
- event_str (
str): The magic string that represents this event in the window - handler_function (
func): The name (not a string though) of the function you want called when the event his heard - override (
bool): Only use this if you speak to Prof. Bain and he recommends it.
The supported events are:
"LEFT-CLICK": Left mouse click"RIGHT-CLICK": Right mouse click"ALT-CLICK": If you're using a PC, this event might instead work for Right Click"LEFT-DRAG": Left mouse clicked and dragged on the screen"RIGHT-DRAG": Right mouse clicked and dragged on the screen"ALT-DRAG": For PCs, this event might instead work for RIGHT-DRAG"DOUBLE-LEFT": Left mouse double click"DOUBLE-RIGHT": Right mouse double click"DOUBLE-ALT": For PCs, this event might instead work for DOUBLE-RIGHT"KEY": The catch-all event for Keyboard presses
1320def setup_shapes(title, background="white", include_grid=True, width=600, height=600): 1321 """ 1322 A static function that sets up the pop-up window. You can specify the size of the window here. 1323 1324 However, you should NOT add any calls to this function unless Prof. Bain specifically tells you to! 1325 1326 Args: 1327 title (`str`): The title of the pop-up window. 1328 background (`str`): A valid color as a string to be used as the background color. 1329 include_grid (`bool`): Whether or not to draw the grid. 1330 width (`int` or `str`): How wide the window should appear (advanced: use the string "FULLWIDTH" to maximize the width) 1331 height (`int` or `str`): How wide the window should appear (advanced: use the string "FULLHEIGHT" to maximize the width) 1332 """ 1333 1334 global _a_canvas 1335 gui = Tk() 1336 gui.title(title) 1337 1338 if width == "FULLWIDTH" 1339 width = gui.winfo_screenwidth() 1340 1341 if height == "FULLHEIGHT" 1342 height = gui.winfo_screenheight() 1343 1344 _a_canvas = Canvas(gui, background=background, width=width, height=height) 1345 _a_canvas.pack() 1346 if include_grid 1347 grid(width, height) 1348 1349 _a_canvas.focus_set() 1350 return _a_canvas
A static function that sets up the pop-up window. You can specify the size of the window here.
However, you should NOT add any calls to this function unless Prof. Bain specifically tells you to!
Arguments:
- title (
str): The title of the pop-up window. - background (
str): A valid color as a string to be used as the background color. - include_grid (
bool): Whether or not to draw the grid. - width (
intorstr): How wide the window should appear (advanced: use the string "FULLWIDTH" to maximize the width) - height (
intorstr): How wide the window should appear (advanced: use the string "FULLHEIGHT" to maximize the width)
1353def update(): 1354 """ 1355 A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION unless Prof. Bain explicitly says to use it. 1356 """ 1357 _a_canvas.update()
A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION unless Prof. Bain explicitly says to use it.