23 Lisalugemine. Funktsiooni graafik, liikuvad pildid

See peatükk on mõeldud huvilistele, kes tahavad kasutada Tkinterit funktsioonide graafikute joonistamiseks ning piltide liikumise loomiseks.

Funktsiooni graafik

Koostame programmi, mis joonistab mõne meie valitud (matemaatilise) funktsiooni (nt y=x3) graafiku.

Kuigi Tkinter sobib hästi graafikute joonistamiseks, tekitab mõningast ebamugavust teistmoodi koordinaatide süsteem – matemaatikas oleme harjunud, et y kasvab ülespoole, mitte alla ning koordinaatide alguspunkt on harjumuspäraselt olnud pigem joonise keskel. Võtame abiks klassi Canvas funktsiooni move, mis võimaldab tahvlil olevaid objekte horisontaalset ja vertikaalset telge mööda ümber tõsta. Seega paigutame kõik objektid harilikku koordinaadistikku, seejärel rakendame funktsiooni move. Peegelduse x-telje suhtes korraldame sellega, et funktsiooni väärtuste kogumisel kogume y asemel -y. Näiteprogramm joonistab funktsiooni y=x graafiku:

Näiteprogramm. y=x graafik

from tkinter import *
raam = Tk()
# tahvli laius
w = 500
# tahvli pikkus
h = 500
tahvel = Canvas(raam, width=w, height=h, bg="white")
 
# vertikaalne telg
tahvel.create_line(0, h/2, 0, -h/2, arrow=LAST)
# horisontaalne telg
tahvel.create_line(-w/2, 0, w/2, 0, arrow=LAST)
 
# joonistame lõigud (x1,f(x1)) - (x2,f(x2))
x1 = -w//2
while x1 < w//2:
    x2 = x1+1
    # olgu alguseks lineaarne funktsioon
    y1 = x1
    y2 = x2
    # -y on selleks, et peegeldada x-telje suhtes
    tahvel.create_line(x1, -y1, x2, -y2)
    x1 += 1
 
# nihutame kõik objektid 250px võrra paremale ja alla
tahvel.move(ALL, w/2, h/2)
 
tahvel.pack()
 
raam.mainloop()

Katseta programmi ka teiste funktsioonidega (5x, x**3 jne).

Liikuvad kujutised

Proovime joonistada osutitega kella, mis ennast aja jooksul värskendaks. Võrreldes eelmiste ülesannetega, kus tegemist oli sisuliselt staatiliste kujutistega, on nüüd tarvis muuta graafikaobjektide olekuid rakenduse töö ajal.

Graafikaobjektide loomisel saab neile anda unikaalseid nimesid, mille järgi saab need hiljem tahvlil üles leida, nt

id = tahvel.create_line(x0,y0,...,xn,yn)

Kasutades nime saab objekti näiteks kustutada, nihutada või muuta tema argumente. Objektidega manipuleerimiseks kasutame klassis Canvas defineeritud meetodeid.

# kustutamine
tahvel.delete(id)
 
# nihutamine
tahvel.move(id, x, y)
 
# objekti argumentide tagastamine
tahvel.itemcget(id, "width")
 
# koordinaatide uuendamine
tahvel.coords(id, x0,y0,...,xn,yn )

Selles ülesandes huvitab meid viimane meetod, mille abil me saame osutite positsiooni uuendada. Tekitame uue raami ja tahvli. Kella keskpunkt olgu tahvli keskel.

from tkinter import *
raam = Tk()
raam.title("Kell")
# tahvli laius
w = 500
# tahvli pikkus
h = 500
 
tahvel = Canvas(raam, width=w, height=h, bg="white")
 
# kella raam
tahvel.create_oval(10,10,w-10,h-10)
# kella keskpunkt
tahvel.create_oval(w/2-5,h/2-5,w/2+5,h/2+5,fill="black")

Joonistame sekundiosuti (mis on sirgjoon) ja salvestame tema andmed muutujasse sek_id:

sek_id = tahvel.create_line(w/2,h/2,w/2,20,fill="red")

Kuna osuti üks ots on fikseeritud kella keskel, siis huvitavad meid ainult liikuva otsa koordinaadid mingil ajahetkel t. Kui on antud sekundite arv sekundid, siis on võimalik arvutada vastavad punkti koordinaadid x ja y:

from math import *
 
# osuti liikuva tipu koordinaadid
# arvutame sekundiosuti pikkuse
r = min(w/2,h/2)-20
 
# arvutame x koordinaadi
x = r*cos(pi/2-sekundid/60.0*2*pi)
 
# arvutame y koordinaadi
y = -r*sin(pi/2-sekundid/60.0*2*pi)

Järgmise sammuna loome funktsiooni, mis loeb jooksvalt aega ja uuendab sekundiosuti positsiooni. Uus funktsioon luuakse võtmesõna def abil, funktsiooni sisu on taandatud. Täpsemalt käsitleme seda hilisemates peatükkides.

import time
 
def uuenda():
    # loeme jooksva sekundi
    sekundid = time.localtime().tm_sec
 
    # osuti liikuva tipu koordinaadid
    # arvutame sekundiosuti pikkuse
    r = min(w/2,h/2)-20
 
    # arvutame x koordinaadi
    x = r*cos(pi/2-sekundid/60.0*2*pi)
 
    # arvutame y koordinaadi
    y = -r*sin(pi/2-sekundid/60.0*2*pi)
 
 
    # uuendame osuti positsiooni
    tahvel.coords(sek_id, 0, 0, x, y)
 
    # nihutame keskele
    tahvel.move(sek_id, w/2, h/2)
 
    # ootame 1 sekundi ja siis uuendame kellaaega uuesti
    raam.after(1000, uuenda)

Kutsume funktsiooni uuenda välja enne Tkinteri põhitsüklisse sisenemist:

uuenda()
tahvel.pack()
raam.mainloop()

Kokkupandud kood on järgmine:

Näiteprogramm. Osutitega kell

from tkinter import *
from math import *
import time
raam = Tk()
raam.title("Kell")
# tahvli laius
w = 500
# tahvli pikkus
h = 500
 
tahvel = Canvas(raam, width=w, height=h, bg="white")
 
# kella raam
tahvel.create_oval(10,10,w-10,h-10)
# kella keskpunkt
tahvel.create_oval(w/2-5,h/2-5,w/2+5,h/2+5,fill="black")
sek_id = tahvel.create_line(w/2,h/2,w/2,20,fill="red")
 
def uuenda(): 
    # loeme jooksva sekundi
    sekundid = time.localtime().tm_sec
 
    # osuti liikuva tipu koordinaadid
    # arvutame sekundiosuti pikkuse
    r = min(w/2,h/2)-20
 
    # arvutame x koordinaadi
    x = r*cos(pi/2-sekundid/60.0*2*pi)
 
    # arvutame y koordinaadi
    y = -r*sin(pi/2-sekundid/60.0*2*pi)
 
    # uuendame osuti positsiooni
    tahvel.coords(sek_id, 0, 0, x, y)
 
    # nihutame keskele
    tahvel.move(sek_id, w/2, h/2)
 
    #ootame 1 sekundi ja siis uuendame kellaaega uuesti
    raam.after(1000, uuenda)
 
uuenda()
tahvel.pack()
raam.mainloop()

Täienda kella. Lisa minuti- ja tunniosuti, mis samuti muudaksid aja jooksul oma positsiooni.

Palun kommenteeri seda materjali Google’i küsimustikus.

Litsents

Icon for the Creative Commons Attribution 4.0 International License

Programmeerimine on loodud Eno Tõnisson, Tauno Palts, Merilin Säde, Kaarel Tõnisson jt poolt Creative Commons Attribution 4.0 International License litsentsi alusel, kui pole teisiti märgitud.

Jaga seda raamatut