Riešené úlohy k 9. cvičeniu¶
Program počas ťahania myši zabezpečí kreslenie žltých krúžkov, prvý s polomerom
1
, každý ďalší je o0.1
väčší. Tlačidlom'Zmaž'
sa obrazovka zmaže a nastaví sa kreslenie od najmenšieho krúžku (s polomerom1
). V programe zabezpeč zviazanie ovládača a tlačidla:canvas.bind('<B1-Motion>', kresli) tkinter.Button(...
Po spustení a ťahaní môžeš dostať, napríklad:
Teraz pridaj ďalšie tlačidlo (napríklad s textom
'Zmeň farbu'
), ktorým sa zmení farba krúžkov na nejakú náhodnú - od tohto momentu budú všetky nasledovné krúžky zafarbené touto novou farbou.Riešenie:
import tkinter import random r = 1 farba = 'yellow' def kresli(event): global r x, y = event.x, event.y canvas.create_oval(x - r, y - r, x + r, y + r, fill=farba) r += .1 def zmaz(event): global r r = 1 canvas.delete('all') def zmen_farbu(): global farba farba = f'#{random.randrange(256**3):06x}' canvas = tkinter.Canvas() canvas.pack() canvas.bind('<B1-Motion>', kresli) canvas.bind('<ButtonPress-3>', zmaz) tkinter.Button(text='Zmeň farbu', command=zmen_farbu).pack() tkinter.mainloop()
Program zabezpečí klikanie myšou: prvé kliknutie si zapamätá súradnice, druhé kliknutie nakreslí obdĺžnik (
create_rectangle
), v ktorom jeden vrchol je zapamätaný a druhý vrchol je práve kliknutý. Obdĺžnik je zafarbený náhodnou farbou. Toto sa opakuje pri ďalších klikaniach.canvas.bind('<ButtonPress-1>', klik)
Napríklad:
Riešenie:
import tkinter import random zoznam = [] def klik(event): zoznam.append((event.x, event.y)) if len(zoznam) == 2: fill = f'#{random.randrange(256**3):06x}' canvas.create_rectangle(zoznam, fill=fill) zoznam.clear() canvas = tkinter.Canvas() canvas.pack() canvas.bind('<ButtonPress-1>', klik) tkinter.mainloop()
Podobne ako v (3) úlohe: pri každom kliknutí sa na danej pozícii nakreslí
'+'
(create_text
), pritom pri prvých dvoch kliknutiach sa tieto body zapamätajú. Tretie z týchto troch kliknutí nakreslí náhodne zafarbený trojuholník (create_polygon
). Zoznam zapamätaných bodov má momentálne 3 vrcholy. Teraz sa z tohto zapamätaného zoznamu vyhodí prvý prvok a pokračuje sa ďalej s dvomi vrcholmi: ďalšie kliknutie pridá do zoznamu 3. vrchol, nakreslí trojuholník a prvý vrchol sa opäť vyhodí. Môžeš dostať, napríklad:Riešenie:
import tkinter import random zoznam = [] def klik(event): xy = event.x, event.y zoznam.append(xy) canvas.create_text(xy, text='+') if len(zoznam) == 3: fill = f'#{random.randrange(256**3):06x}' canvas.create_polygon(zoznam, fill=fill) zoznam.pop(0) canvas = tkinter.Canvas() canvas.pack() canvas.bind('<ButtonPress-1>', klik) tkinter.mainloop()
Podobne ako v (3) úlohe: klikanie do plochy kreslí
'+'
a zapamätáva tieto body. Ak mám aspoň 3 zapamätané body a pritom prvý a posledný majú vzdialenosť menšiu ako 5, ukončí sa zapamätávanie bodov, nakreslí sa z nich náhodne zafarbený polygón a všetko sa začne od začiatku. Môžeš dostať, napríklad:Riešenie:
import tkinter import random zoznam = [] def klik(event): x, y = event.x, event.y zoznam.append((x, y)) canvas.create_text(x, y, text='+') x0, y0 = zoznam[0] if len(zoznam) > 2 and (x - x0) ** 2 + (y - y0) ** 2 < 25: fill = f'#{random.randrange(256**3):06x}' canvas.create_polygon(zoznam, fill=fill) zoznam.clear() canvas = tkinter.Canvas() canvas.pack() canvas.bind('<ButtonPress-1>', klik) tkinter.mainloop()
Vylepši riešenie (4) úlohy: pri kreslení polygónu sa automaticky všetky
'+'
z plochy vymažú (canvas.delete(...)
). Každému nakreslenému'+'
môžeš pridať rovnakýtag
a potom ich naraz zrušíš. Pozri, napríklad 3. prednášku.Okrem vymazávania značiek
'+'
pridaj aj tri tlačidlá:s textom
'Zmaž'
zmaže obrazovku, pritom zruší aj zapamätané body doteraz vytváraného polygónus textom
'Zmeň farbu'
zmení farbu naposledy nakresleného polygónu na nejakú inú náhodnús textom
'Späť'
zmaže naposledy nakreslený polygónRiešenie:
import tkinter import random zoznam = [] # momentálne vytvarané vrcholy polygony = [] # všetky nakreslené polygóny def klik(event): x, y = event.x, event.y zoznam.append((x, y)) canvas.create_text(x, y, text='+', tag='+') x0, y0 = zoznam[0] if len(zoznam) > 2 and (x - x0) ** 2 + (y - y0) ** 2 < 25: fill = f'#{random.randrange(256**3):06x}' polygony.append(canvas.create_polygon(zoznam, fill=fill)) zoznam.clear() canvas.delete('+') def zmaz(): canvas.delete('all') zoznam.clear() polygony.clear() def zmen_farbu(): if polygony: fill = f'#{random.randrange(256**3):06x}' canvas.itemconfig(polygony[-1], fill=fill) def spat(): if polygony: canvas.delete(polygony.pop(0)) canvas = tkinter.Canvas() canvas.pack(side='left') canvas.bind('<ButtonPress-1>', klik) tkinter.Button(text='Zmaž', command=zmaz).pack() tkinter.Button(text='Zmeň farbu', command=zmen_farbu).pack() tkinter.Button(text='Späť', command=spat).pack() tkinter.mainloop()
Najprv zadefinuj štyri premenné (napríklad
x1, y1, x2, y2 = 100, 50, 200, 100
) a pomocou nich nakresli farebný obdĺžnik. Potom program pri každom kliknutí, ale len do vnútra obdĺžnika, mu zmení farbu výplne. Každé kliknutie do vnútra obdĺžnika cyklicky strieda jednu zo 4 farieb, napríkladfarby = ['blue', 'red', 'green', 'yellow']
. Nepoužívajglobal
.Riešenie:
import tkinter def klik(event): x, y = event.x, event.y if x1 <= x <= x2 and y1 <= y <= y2: farba = farby.pop(0) farby.append(farba) canvas.itemconfig(obd, fill=farba) canvas = tkinter.Canvas() canvas.pack() x1, y1, x2, y2 = 100, 50, 200, 100 farby = ['blue', 'red', 'green', 'yellow'] obd = canvas.create_rectangle(x1, y1, x2, y2, fill=farby[-1]) canvas.bind('<ButtonPress>', klik) tkinter.mainloop()
alebo pomocou
canvas.tag_bind
, ktorý zviaže udalosť len s daným objektom:import tkinter def klik(event): farba = farby.pop(0) farby.append(farba) canvas.itemconfig(obd, fill=farba) canvas = tkinter.Canvas() canvas.pack() x1, y1, x2, y2 = 100, 50, 200, 100 farby = ['blue', 'red', 'green', 'yellow'] obd = canvas.create_rectangle(x1, y1, x2, y2, fill=farby[-1]) canvas.tag_bind(obd, '<ButtonPress>', klik) # klikanie len do vnútra útvaru tkinter.mainloop()
Predstav si, že celá grafická plocha je štvorcová sieť, ktorej štvorčeky majú veľkosť 50x50. Napíš program, ktorý pri každom kliknutí do grafickej plochy nakreslí náhodne zafarbený príslušný štvorček tejto siete (pomocou
create_rectangle()
). Nepoužívajglobal
. Pravdepodobne na zistenie štvorčeka siete využiješ niečo akox // 50
ay // 50
.Riešenie:
import tkinter import random def klik(event): x = event.x // 50 * 50 y = event.y // 50 * 50 farba = f'#{random.randrange(256**3):06x}' canvas.create_rectangle(x, y, x + 50, y + 50, fill=farba) canvas = tkinter.Canvas() canvas.pack() canvas.bind('<ButtonPress>', klik) tkinter.mainloop()
Napíš program, ktorý bude robiť efekt spreja: ťahanie myšou so zatlačeným ľavým tlačidlom nakreslí 20 farebných bodiek (farba podľa globálnej premennej, napríklad
farba = 'blue'
) na náhodných pozíciách. Tieto náhodné bodky budú mať od kliknutého miesta takúto vzdialenosť: x-ová súradnica bude z intervalu<x-30, x+30>
a y-ová z<y-30, y+30>
. Najlepšie je ich kresliť ako kruhy s polomerom2
bez obrysu (width=0
).Do programu pridaj aj spracovanie tlačidla
'Zmeň farbu'
: vtedy sa nastaví premennáfarba
na náhodnú farbu. Vďaka tomuto každé ďalšie ťahanie myšou bude sprejovať už touto novou farbou. Okrem tlačidla pridaj aj widgetLabel
, ktorý bude zobrazovať aktuálne nastavenú farbu spreja, napríklad v tvare:'farba: #456789'
. Môžeš použiť napríklad:vypis = tkinter.Label(text='farba: blue') vypis.pack()
a pre zmenu textu v tomto widgete:
vypis['text'] = 'novy text'
Riešenie:
import tkinter import random farba = 'blue' def tahaj(event): for i in range(20): x = event.x + random.randint(-30, 30) y = event.y + random.randint(-30, 30) canvas.create_oval(x - 2, y - 2, x + 2, y + 2, fill=farba, width=0) def zmen_farbu(event=None): global farba farba = f'#{random.randrange(256**3):06x}' vypis['text'] = f'farba: {farba}' canvas = tkinter.Canvas() canvas.pack() canvas.bind('<B1-Motion>', tahaj) tkinter.Button(text='Zmeň farbu', command=zmen_farbu).pack() vypis = tkinter.Label(text='farba: blue') vypis.pack() tkinter.mainloop()
Stláčaním malých a veľkých písmen abecedy (bez diakritiky) sa tieto vypisujú nejakým väčším fontom vedľa seba (Napríklad
'arial 30'
). Využi jeden grafický objekt pre text (create_text
) a tomuto budeš pri stláčaní písmen pridávať vypisovaný text (pomocoucanvas.itemconfig()
). Program by mal akceptovať aj stláčanie medzery a Enter (do textu vloží'\n'
alebo'\r'
). Použi metódubind_all('<KeyPress>', ...)
pričom vo viazanej funkcii pracuj s hodnotouevent.char
.Riešenie:
import tkinter text = '' def klaves(event): # event.char: '\r' return, '\b' backspace global text if 'a' <= event.char.lower() <= 'z' or event.char in ' \r': text += event.char canvas.itemconfig(riadky, text=text) elif event.char == '\b': text = text[:-1] canvas.itemconfig(riadky, text=text) canvas = tkinter.Canvas() canvas.pack() riadky = canvas.create_text(190, 130, fill='blue', font='arial 30') canvas.bind_all('<KeyPress>', klaves) tkinter.mainloop()
alebo pomocou
canvas.itemcget(...)
, ktorá vráti momentálnu hodnotu atribútu'text'
v texte:import tkinter def klaves(event): # event.char: '\r' return, '\b' backspace if 'a' <= event.char.lower() <= 'z' or event.char in ' \r': text = canvas.itemcget(riadky, 'text') + event.char canvas.itemconfig(riadky, text=text) elif event.char == '\b': text = canvas.itemcget(riadky, 'text')[:-1] canvas.itemconfig(riadky, text=text) canvas = tkinter.Canvas() canvas.pack() riadky = canvas.create_text(190, 130, fill='blue', font='arial 30') canvas.bind_all('<KeyPress>', klaves) tkinter.mainloop()