Materjalid koostas ja kursuse viib läbi
Tartu Ülikooli arvutiteaduse instituudi programmeerimise õpetamise töörühm
| < eelmine | 4. nädala sisukord | järgmine > | 
4.3 Kasutajaliides Tkinteriga
Eelmises osas tegelesime piltidega. Nüüd vaatame graafilise kasutajaliidesega programmide tegemist mooduli tkinter baasil. Alustuseks toome ära ühe lihtsa tkinter-i programmi:
# impordi tk vidinad ja konstandid
from tkinter import * # tkinteri põhivahendid
from tkinter import ttk # platvormi ühise stiili saamiseks
from tkinter import messagebox
# see funktsioon käivitatakse nupule klõpsamisel
def tervita():
    tervitus = 'Tere, ' + nimi.get()
    messagebox.showinfo(message=tervitus)
# loome akna
raam = Tk()
raam.title("Tervitaja")
raam.geometry("300x100")
# loome tekstikasti jaoks sildi
silt = ttk.Label(raam, text="Nimi")
silt.place(x=5, y=5)
# loome tekstikasti
nimi = ttk.Entry(raam)
nimi.place(x=70, y=5, width=150)
# loome nupu
nupp = ttk.Button(raam, text="Tervita!", command=tervita)
nupp.place(x=70, y=40, width=150)
# ilmutame akna ekraanile
raam.mainloop()
Seda programmi käivitades peaksid saama ühe väikese akna, milles on tekstikast nime sisestamiseks ning nupp, mida vajutades saad nimelise tervituse.
Funktsioon tervita on mõeldud käivitamiseks nupule klikkimise korral. Funktsiooni kehas küsitakse allpool defineeritud tekstikasti sisu (nimi.get()), moodustatakse selle põhjal tervitusega sõne ning näidatakse seda kasutajale väikses lisaaknas. (Selles funktsioonis oleme kasutanud ühte globaalset muutujat – nimi pole ei funktsiooni argument ega lokaalne muutuja, vaid funktsioonist väljaspool defineeritud muutuja.)
Programmis kasutatakse 3 kasutajaliidese komponenti e vidinat (ingl widget):
Funktsioon ttk.Label loob ühe sildi (s.o vidina teksti näitamiseks). Funktsiooni esimese argumendiga näitasime, et me soovime seda silti kasutada eespool loodud aknas. Kasutades nimelist argumenti text, andsime sellele sildile ka soovitud teksti. Käsk silt.place(...) paigutas loodud sildi soovitud koordinaatidele (ühikuteks on pikslid, punkt (0,0) paikneb akna sisuosa ülemises vasakus nurgas ning koordinaadid kasvavad paremale/alla liikudes).

Järgmises plokis lõime ja seadsime paika tekstisisestuskasti (ttk.Entry). Selle paigutamisel näitasime ära ka soovitud laiuse.
Nupu (ttk.Button) loomisel määrasime argumendiga command ära, mida tuleb teha nupule klikkimise korral. Paneme tähele, et argumendi väärtuseks on ainult funktsiooni nimi, mitte funktsiooni väljakutse (see oleks olnud koos tühjade sulgudega). Põhjus on selles, et me ei taha seda funktsiooni käivitada mitte nupu loomise ajal, vaid siis, kui nuppu klikitakse.
Lisaks on programmis read, mis olid juba eelmise osa näidetes ja on üldjuhul olemas igaks tkinteri programmis. Programmi sisuline olemus sõltub sellest, milliseid vidinaid aknasse paigutatakse ning kuidas kasutaja tegevustele reageeritakse. Võimalike vidinate valimiseks võib uurida alustuseks lehekülge aadressil http://www.tkdocs.com/tutorial/widgets.html. Kasutaja tegevustele reageerimisel saab rakendada kogu oma programmeerimisvõtete arsenali.
PAREM VIIS VIDINATE PAIGUTAMISEKS
Eelmist näiteprogrammi käivitades ei pruugita olla rahul olla vidinate paigutusega. Paigutust saab muuta korrigeerides etteantud koordinaate ja mõõtmeid. Paraku on selline pikselhaaval timmimine üsna tänamatu töö, kuna mõnes teises operatsioonisüsteemis (või ka teiste seadetega arvutis) ei pruugi seatud paigutus sobida.
Vidinate paigutust on võimalik muuta ka natuke üldisemalt kui pikslite tasemel, lubades sellega Tk-l valida vastavalt olukorrale kõige parem konkreetne paigutus. Järgnevas programmis on vidinate paigutamiseks kasutatud  meetodi place asemel meetodit grid, mis jagab kasutajaliidese mõtteliselt ruudustikuks ning paigutab iga vidina soovitud lahtrisse vastavalt argumentidele column ja row.
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
def tervita():
    tervitus = 'Tere, ' + nimi.get()
    messagebox.showinfo(message=tervitus)
raam = Tk()
raam.title("Tervitaja")
# raam.geometry("300x100") # akna algne suurus määratakse vastavalt sisule
# paigutame sildi ruudustiku ülemisse vasakusse lahtrisse (column ja row)
# soovime, et sildi ümber jääks igas suunas 5 pikslit vaba ruumi (padx ja pady)
# soovime, et silt "kleepuks" oma lahtris ülemisse vasakusse nurka (sticky)
# N - north, W - west
silt = ttk.Label(raam, text="Nimi")
silt.grid(column=0, row=0, padx=5, pady=5, sticky=(N, W))
# tekstikasti puhul soovime, et ta kleepuks nii ida- kui lääneserva külge
# st ta peab venima vastavalt akna suurusele
nimi = ttk.Entry(raam)
nimi.grid(column=1, row=0, padx=5, pady=5, sticky=(N, W, E))
# soovime, et nupp veniks nii laiuses kui ka kõrguses
nupp = ttk.Button(raam, text="Tervita!", command=tervita)
nupp.grid(column=1, row=1, padx=5, pady=5, sticky=(N, S, W, E))
# soovime, et akna suuruse muutmisel muudetakse veeru 1 ja rea 1 mõõtmeid
# (st. veerg 0 ja rida 0 jäävad sama laiaks/kõrgeks)
raam.columnconfigure(1, weight=1)
raam.rowconfigure(1, weight=1)
# kuvame akna ekraanile
raam.mainloop()
Lisaks meetoditele place ja grid võib kohata veel paigutusmeetodit pack, mida kasutasime tahvli puhul eelmises osas. Rohkem infot saab siit: http://www.tkdocs.com/tutorial/concepts.html#geometry.
PILDID TAHVLILE
Kuigi tahvliga tegutsesime juba eelmises osas, toome tahvlile pildi lisamise siin. Tahvlile saab panna .gif, .pgm, või .ppm formaadis pilte. Järgmise näite proovimiseks salvesta programmiga samasse kausta järgmised failid: kuusk.gif, lill.gif.
from tkinter import *
raam = Tk()
raam.title("Tahvel")
tahvel = Canvas(raam, width=400, height=400, background="white")
tahvel.grid()
# pildi kuvamisel on vaja kõigepealt laadida pilt ja panna see siis tahvlile
kuusk = PhotoImage(file="kuusk.gif")
img = tahvel.create_image(250, 80, image=kuusk)
# activeimage määrab pildi, mida näidatakse, kui hiirekursor on pildi kohal
# anchor näitab, mille järgi pilt paigutatakse (antud juhul ülemise-vasaku nurga järgi)
lill = PhotoImage(file="lill.gif")
img = tahvel.create_image(50, 200, image=kuusk, activeimage=lill, anchor=NW)
raam.mainloop()
NÄIDE
Järgmine programm kõlbaks kontrollülesande 4.2c lahenduseks, aga nüüd peate midagi muud välja mõtlema või antud programmi oluliselt muutma.
#Impordime kõik vajalikud teegid
from tkinter import *
from tkinter import ttk
#Loome raami ja paneme raamile pealkirja
raam = Tk()
raam.title("Fonolukk")
#Fonoluku ekraani osa
kood = ttk.Entry(raam).grid(row = 0, column = 0, columnspan = 3, rowspan = 1, sticky = (N, W, E), padx=5, pady=5)
#Lisame fonolukule numbrid
rida = 1
veerg = 0
arv_nupul = 1
while arv_nupul < 10:
    #Lisame nupu
    ttk.Button(raam, text = str(arv_nupul)).grid(row = rida, column = veerg, padx = 5, pady = 5)
    #Kui arv_nupul jagub 3-ga, siis paneme järgmise arvu uude ritta ja nullime veeru väärtuse
    if arv_nupul % 3 == 0: 
        rida += 1
        veerg = 0
    #Kui arv_nupul ei jagu 3-ga, siis suurendame veeru väärtust.
    else:
        veerg += 1
    #Suurendame arvu väärtust
    arv_nupul += 1
#Lisame ka teised fonolukul esinevad sümbolid
ttk.Button(raam, text = "*").grid(row = 4, column = 0, padx = 5, pady = 5)
ttk.Button(raam, text = "0").grid(row = 4, column = 1, padx = 5, pady = 5)
ttk.Button(raam, text = "#").grid(row = 4, column = 2, padx = 5, pady = 5)
#Kuvame ekraanile
raam.mainloop()
| < eelmine | 4. nädala sisukord | järgmine > |