furas.pl
# prywatne notatki - Python, Linux, Machine Learning, etc.

Rysowanie w Turtle - Płótno (Canvas) i funkcje Tkinter

WERSJA ROBOCZA WPISU

Moduł turtle jest zbudowane w oparciu o moduł tkinter i wykorzystuje jego obiekt Canvas (Płótno) do wyświetlania rysowanych elementów.

turtle pozwala nawet na bezpośredni dostęp do płótna - dzięki turtle.getcanvas() - co pozwala na wykorzystanie funkcji udostępnianych przez płótno w tkinter.

create_rectangle - kwadrat i prostokąt

Składnia:

canvas.create_rectangle(x1, y1, x2, y2, opcje)

Obowiązkowe są x1, y1, x2, y2. Opcje nie są obowiązkowe ale wymagają podania jako nazwa=wartość. Więcej o opcjach poniżej.

Zamiast wysokości i szerokości podaje się przeciwległe wierzchołki zajmowanego obszaru. Jeśli szerokość (czyli x2 - x1) jest różne od wysokości (czyli y2 - y1) to powstaje prostokąt.

import turtle

canvas = turtle.getcanvas()

# kwadrat (szerokość 100-0=100, wysokość 100-0=100)
canvas.create_rectangle(0, 0, 100, 100)

# prostokąt (szerokość 300-200=100, wysokość 75-25=50)
canvas.create_rectangle(200, 25, 300, 75)

turtle.mainloop()
rysowanie w turtle - canvas - przykład

create_oval - okrąg i elipsa

Składnia

canvas.create_oval(x1, y1, x2, y2, opcje)

Obowiązkowe są x1, y1, x2, y2. Opcje nie są obowiązkowe ale wymagają podania jako nazwa=wartość. Więcej o opcjach poniżej.

Zamiast środka okręgu/elipsy oraz jednego lub dwóch promieni podaje się przeciwległe wierzchołki zajmowanego obszaru. Jeśli szerokość (czyli x2 - x1) jest różne od wysokości (czyli y2 - y1) to zamiast okręgu powstaje elipsa.

import turtle

canvas = turtle.getcanvas()

# okrąg (szerokość 100-0=100, wysokość 100-0=100)
canvas.create_oval(0, 0, 100, 100)

# elipsa (szerokość 300-200=100, wysokość 75-25=50)
canvas.create_oval(200, 25, 300, 75)

turtle.mainloop()
rysowanie w turtle - canvas - przykład

Rysowanie okręgu podając środek (x,y) i promień (r)

def cirlce(canvas, x, y, r):
   return canvas.create_oval(x-r, y-r, x+r, y+r)

Rysowanie elipsy podając środek (x,y) i dwa promienie (r1, r2)

def elipse(canvas, x, y, r1, r2):
   return canvas.create_oval(x-r1, y-r2, x+r1, y+r2)

Przykłady

import turtle

def circle(canvas, x, y, r):
   return canvas.create_oval(x-r, y-r, x+r, y+r)

canvas = turtle.getcanvas()

for promien in range(10, 301, 20):
    circle(canvas, 0, 0, promien)

turtle.mainloop()
rysowanie w turtle - canvas - przykład
import turtle

def elipse(canvas, x, y, r1, r2):
   return canvas.create_oval(x-r1, y-r2, x+r1, y+r2)

canvas = turtle.getcanvas()

for promien in range(10, 151, 20):
#    elipse(canvas, 0, 0, 150-promien, 150+promien)
#    elipse(canvas, 0, 0, promien, 150+promien)
    elipse(canvas, 0, 0, promien, 160-promien)

turtle.mainloop()
rysowanie w turtle - canvas - przykład
import turtle

def elipse(canvas, x, y, r1, r2):
   return canvas.create_oval(x-r1, y-r2, x+r1, y+r2)

def earth(canvas, x=0, y=0, r=100):
    for promien in range(0, r+1, 20):
        elipse(canvas, x, y, r-promien, r)
        elipse(canvas, x, y, r, r-promien)

def earth1(canvas, x=0, y=0, r=100):
    for promien in range(0, r+1, 20):
        elipse(canvas, x, y, r-promien, r)

def earth2(canvas, x=0, y=0, r=100):
    for promien in range(0, r+1, 20):
        elipse(canvas, x, y, r, r-promien)


canvas = turtle.getcanvas()

#for promien in range(10, 151, 20):
#    elipse(canvas, 0, 0, 160-promien, 160+promien)
#    elipse(canvas, 0, 0, promien, 160+promien)
#    elipse(canvas, 0, 0, promien, 160-promien)

earth(canvas)
earth1(canvas, 250)
earth2(canvas, -250)

turtle.mainloop()

create_arc - łuk (wycinek okręgu lub elipsy)

Składnia

canvas.create_arc(x1, y1, x2, y2, opcje)

Obowiązkowe są x1, y1, x2, y2. Opcje nie są obowiązkowe ale wymagają podania jako nazwa=wartość. Więcej o opcjach poniżej.

  • style - style=tk.PIESLICE , style=tk.ARC , style=tk.CHORD.
  • start - kąt początku
  • extent - kąt wycinka

Opcje

Oprócz pozycji figury mogą zawierać także dodatkowe parametry, które trzeba podawać z nazwą (tzw. nazwane parametry)

  • fill - kolor wypełnienia. Brak domyślnego koloru. Może być nazwa np. "red" lub RGB np. "#0f0", "#00ff00", "#000fff000"
  • outline - kolor obwódki. Domyślnie jest czarna. Może być nazwa np. "red" lub RGB np. "#0f0", "#00ff00", "#000fff000"
  • width - grubość obwódki. Domyślnie jest 1. Wartość 0 usuwa obwódkę.
  • dash - obwódka przerywana. Lista/krotka opisująca na przemian ilość pikseli wyświetlanych i ilość pikseli pomijanych np. (2,2) lub (7,3,1,3)
  • dashoffset - przesunięcie początku rysowanego obwódki przerywanej. Pozwala to lepiej ją dopasować - zwłaszcza na rogach figur.
canvas.create_rectangle(240, 0, 340, 100, fill='red', width=0, activefill='green')

canvas.create_rectangle(0, 0, 100, 100, fill='red', outline='blue', width=3, dash=(50,50), dashoffset=25)

Ustawienia dla obiektu "aktywnego" (czyli po najechaniu myszką)

Porócz "normalnych" ustawień są też ustawienia obiketu "aktywnego" czyli najechanego myszką. Nazwy opcji zaczynają się od "active" i są takie jak dla normalnego obiektu.

import turtle

canvas = turtle.getcanvas()

# stworzenie czerwonego kwadratu z niebieską obwódką
canvas.create_rectangle(0, 0, 100, 100, fill='red', outline='green', activefill='green', activeoutline='red', width=3)

turtle.mainloop()

Identyfikator obiektu

Funkcje create_... zwracają liczbę, która jest identyfikatorem narysowanego obiektu. Indentyfikator pozwala na późniejsze zmienianie ustawień obiektu (canvas.itemconfigure), przesuwanie obiektu (canvas.move) jak i usuwanie obiektu (canvas.delete).

import turtle
import random

def move_kwadrat():
    # przesuń obiekt o losowy krok)
    canvas.move(kwadrat_1, random.randint(-10, 10), random.randint(-10, 10))
    # wykonaj ponownie za 100ms (0.1 sekundy)
    turtle.ontimer(move_kwadrat, 100)

canvas = turtle.getcanvas()

# stworzenie czerwonego kwadratu z niebieską obwódką
kwadrat_1 = canvas.create_rectangle(0, 0, 200, 200, fill='red', outline='blue', width=3)

print('kwadrat_1:', kwadrat_1)

# zmiana obwódki na zieloną (jeszcze przed wyświetleniem)
canvas.itemconfigure(kwadrat_1, outline='green')

# stworzenie niebieskiego kwadratu z żółtą obwódką
kwadrat_2 = canvas.create_rectangle(0, 0, -200, -200, fill='blue', outline='yellow', width=3)

print('kwadrat_2:', kwadrat_2)

# zmiana obwódki na zieloną (jeszcze przed wyświetleniem)
canvas.delete(kwadrat_2)

move_kwadrat()

turtle.mainloop()

Przesuwanie kwadratu

import turtle
import random

def przesun_kwadrat():
    # przesuń obiekt o losowy krok
    canvas.move(kwadrat_id, random.randint(-10, 10), random.randint(-10, 10))

    # wykonaj ponownie za 100ms (0.1 sekundy)
    turtle.ontimer(przesun_kwadrat, 100)

canvas = turtle.getcanvas()

kwadrat_id = canvas.create_rectangle(0, 0, 100, 100)

przesun_kwadrat()

turtle.mainloop()

Usuniecie kwadratu po 3 sekundach

import turtle

def usun_kwadrat():
    canvas.delete(kwadrat_id)

canvas = turtle.getcanvas()

kwadrat_id = canvas.create_rectangle(0, 0, 100, 100)

# wykonanie po 3 sekundach
turtle.ontimer(usun_kwadrat, 3000)

# to samo używając `lambda`
#turtle.ontimer(lambda:canvas.delete(kwadrat_id), 3000)

turtle.mainloop()

Zmienia kolor kwadratu co pół sekundy.

import turtle

def zmien_kwadrat():
    kolor = canvas.itemcget(kwadrat_id, 'fill')

    if kolor == 'red':
        canvas.itemconfigure(kwadrat_id, fill='green')
    else:
        canvas.itemconfigure(kwadrat_id, fill='red')

    # wykonaj ponownie za 500ms (0.5 sekundy)
    turtle.ontimer(zmien_kwadrat, 500)


canvas = turtle.getcanvas()

kwadrat_id = canvas.create_rectangle(0, 0, 100, 100, fill='red', width=0)

zmien_kwadrat()

turtle.mainloop()

Kolory

Standardowe nazwy kolorów to "white", "black", "red", "green", "blue", "cyan", "yellow", "magenta". Inne nazwy mogą zależeć od instalacji. Ponieważ tkinter jest zbudowany na tcl/tk więc listę kolorów można zobaczyć w

Tcl 8.6 - Tk - Kolory

Listę (tkColors) można też pobrać z przykładu](http://www.science.smith.edu/dftwiki/index.php/Tk_Color_Names)) dla ([Zelle graphics.py <http://mcsp.wartburg.edu/zelle/python/) - ale ta lista nie jest częścią `graphics.py tylko autor przykładu prawdopodobnie sam ją stworzył (może nawet korzystał z listy w domumentacji Tcl/Tk>`__.

Można też stosować napisy z szesnastkową wartością RGB "#rgb", "#rrggbb" lub "#rrrgggbbb". Przykładowo zielony to "#0f0 lub #00ff00 lub #000fff000

tkinter (a co za tym idzie i turtle) nie przewiduje nadawania przezroczytości obiektom.

---

import turtle

canvas = turtle.getcanvas()

bok = 30

for i in range(16):
    x1 = bok * i
    x2 = x1 + bok
    kolor = f'#{i:x}{i:x}{i:x}'
    #print(kolor)
    canvas.create_rectangle(x1, 0, x2, bok, fill=kolor)

turtle.mainloop()

Odcienie szarości od "#000" (czarny) do "#fff" (biały)

rysowanie w turtle - canvas - przykład
import turtle

canvas = turtle.getcanvas()

bok = 30

# odcienie szarości

y1 = 0 * (bok + 10)
y2 = y1 + bok
for i in range(16):
    x1 = bok * i
    x2 = x1 + bok
    kolor = f'#{i:x}{i:x}{i:x}'
    canvas.create_rectangle(x1, y1, x2, y2, fill=kolor)

y1 = 1 * (bok + 10)
y2 = y1 + bok
for i in range(16):
    x1 = bok * i
    x2 = x1 + bok
    kolor = f'#{i:x}00'
    #print(kolor)
    canvas.create_rectangle(x1, y1, x2, y2, fill=kolor)

y1 = 2 * (bok + 10)
y2 = y1 + bok
for i in range(16):
    x1 = bok * i
    x2 = x1 + bok
    kolor = f'#0{i:x}0'
    #print(kolor)
    canvas.create_rectangle(x1, y1, x2, y2, fill=kolor)

y1 = 3 * (bok + 10)
y2 = y1 + bok
for i in range(16):
    x1 = bok * i
    x2 = x1 + bok
    kolor = f'#00{i:x}'
    #print(kolor)
    canvas.create_rectangle(x1, y1, x2, y2, fill=kolor)

turtle.mainloop()
Książki: python-dla-kazdego-podstawy-programowania python-wprowadzenie python-leksykon-kieszonkowy python-receptury python-programuj-szybko-i-wydajnie python-projekty-do-wykorzystania black-hat-python-jezyk-python-dla-hackerow-i-pentesterow efektywny-python-59-sposobow-na-lepszy-kod tdd-w-praktyce-niezawodny-kod-w-jezyku-python aplikacje-internetowe-z-django-najlepsze-receptury