rozdział 3: ZDARZENIA ostatnia modyfiaaja: 09.03.18
Zdarzenia: zajśaie pewnego zdarzenia może sprowoiować zarządaę zdarzeń to automatyaznego wywołania waześniej wsiazanej funiaji (callback) związanie taiiej funiaji z ioniretnym widżetem może nastąpić: w ahwili tworzenia obieitu widżetu (o ile jego ionstruitor ma stosowny parametr: aommand) gdy obieit już istnieje (jeśli obieit ma metodę bind())
Posłużymy się metodą showinfo() z ilasy messagebox messagebox.showinfo(tytuł,info)
Najpierw poiażemy, jai przypisać callback do widżetu, itórego ionstruitor ma parametr aommand: import tkinter as tk import messagebox from tkinter przypisanie przypisanieobsługi obsługizdarzenia zdarzenia def klik(): tk.messagebox.showinfo("klik!","uwielbiam kliknięcia!") o = tk.tk() tk.label(o,text="etykietka:").pack() tk.button(o,text="przycisk",command=klik).pack(fill=tk.x) tk.frame(o, height=30, width=100, bg="blue").pack(); o.mainloop() 03_01.py
Wiele widżetów (szazególnie te, itóre ao do zasady nie są klikalne) nie ma ionstruitora z parametrem aommand, ale za to ma metodę bind(): widżet.bind(zdarzenie,callback)
Zdarzenia: w TiInter zdarzenia identyfiowane są zestandaryzowanymi napisami podamy najprzydatniejsze z niah
nazwa nazwazdarzenia zdarzenia <Button-1> <Button-1> pojedynaze pojedynazeiliinięae iliinięaelewym lewymprzyaisiiem przyaisiiemmyszy myszy <Button-2> <Button-2> pojedynaze pojedynazeiliinięaie iliinięaieśrodiowym środiowymprzyaisiiem przyaisiiemmyszy myszy(o(oile ilejest jestdostępny) dostępny) <Button-3> <Button-3> pojedynaze pojedynazeiliinięaie iliinięaieprawym prawymprzyaisiiem przyaisiiemmyszy myszy(o(oile ilejest jestdostępny) dostępny) <B1-Motion> <B1-Motion> przesuwanie przesuwaniemyszy myszyzznaaiśniętym naaiśniętymlewym lewymprzyaisiiem przyaisiiemmyszy myszy (istnieją (istniejąrównież równieżzdarzenia zdarzenia<b2-motion> <B2-Motion>i i<b3-motion>) <B3-Motion>) <ButtonRelease-1> <ButtonRelease-1> zwolnienie zwolnienielewego lewegoprzyaisiu przyaisiumyszy myszy (istnieją również zdarzenia <ButtonRelease-2> (istnieją również zdarzenia <ButtonRelease-2>i i<buttonrelease-3>) <ButtonRelease-3>) <DoubleButton-1> <DoubleButton-1> podwójne podwójneiliinięaie iliinięaielewego lewegoprzyaisiu przyaisiumyszy myszy (istnieją również zdarzenia <DoubleButton-2> i <DoubleButton-3>) (istnieją również zdarzenia <DoubleButton-2> i <DoubleButton-3>) Uwaga! Uwaga!Jeśli Jeśliprzypisałeś przypisałeśaallbaai aallbaaido do<button-1>, <Button-1>,totoon ontakże takżezostanie zostaniewywołany! wywołany!
nazwa nazwazdarzenia zdarzenia <Enter> <Enter> iursor iursormyszy myszypojawił pojawiłsię sięnad nadwidżetem widżetem <Leave> <Leave> iursor iursormyszy myszyopuśaił opuśaiłobszar obszarwidżetu widżetu <Focus-In> <Focus-In> widżet widżet(albo (albojego jegodzieaio) dzieaio)przejął przejąłsiupienie siupienie <Focus-Out> <Focus-Out> widżet widżet(albo (albojego jegodzieaio) dzieaio)straaił straaiłsiupienie siupienie <Return> <Return> użytiownii użytiowniinaaisnął naaisnął Enter Enter (o(onazwaah nazwaahpozostałyah pozostałyahy ypowiemy powiemyjuż jużza zaahwilę) ahwilę) <Key> <Key> użytiownii użytiowniinaaisnął naaisnąłjakiś jakiś <Configure> <Configure> widżet widżetzmienił zmieniłrozmiar rozmiari ipołożenie położenie
nazwa nazwaklawisza klawisza xx użytiownii użytiowniinaaisnął naaisnął 'x''x'(x(xnie niemoże możebyć byćspaają spaająani aniznaiiem znaiiem'<'!) '<'!) <space> <space> spaaja spaaja <less> <less> znai znai'<''<' <Cancel> <Cancel> przerywająay przerywająaypraaę praaęprogramu programu(np. (np.ctrl-c Ctrl-Calbo alboctrl-breai) Ctrl-Breai) <BackSpace> <BackSpace> baaispaae baaispaae <Tab> <Tab> tabulatora tabulatora
nazwa nazwaklawisza klawisza <Shift_L> <Shift_L> dowolny dowolny shift shift <Control_L> <Control_L> dowolny dowolny aontrol aontrol <Alt_L> <Alt_L> dowolny dowolny alt alt <Pause> <Pause> pause pause <Caps_Lock> <Caps_Lock> aaps aapsloai loai <Escape> <Escape> Esa Esa
nazwa nazwaklawisza klawisza <Prior> <Prior> Page PageUp Up <Next> <Next> Page PageDown Down <End> <End> End End <Home> <Home> Home Home <Left> <Left> strzałia strzałiawwlewo lewo <Up> <Up> strzałia strzałiawwgórę górę
nazwa nazwaklawisza klawisza <Right> <Right> strzałia strzałiawwprawo prawo <Down> <Down> strzałia strzałiawwdół dół <Insert> <Insert> insert insert <Delete> <Delete> del del <Fx> <Fx> (F1,F2,etc) (F1,F2,etc) e efuniayjne funiayjne(f1..f12) (F1..F12) <Num_Lock> <Num_Lock> num numloai loai <Scroll_Lock> <Scroll_Lock> saroll sarollloai loai
nazwa nazwaklawisza klawisza <Shift-x> <Shift-x> naaiśnięto naaiśnięto xxwwazasie, azasie,gdy gdyjuż jużbył byłnaaiśnięty naaiśnięty Shift Shift <Alt-x> <Alt-x> j.w. j.w.ale alealt Alt <Control-x> <Control-x> j.w. j.w.ale alecontrol Control
Uwaga: aallbaai dla parametru aommand powinien być funkcją bezparametrową aallbaai dla metody bind() powinien być funkcją z jednym parametrem (jaio argument podstawia się obiekt ująay szczegóły przeahwyaonego zdarzenia) w programie, itóry poiażemy za ahwilę, ominiemy ten problem w sposób eliminująay ionieazność pisania dwóah oddzielnyah funiaji
Teraz przypiszemy callback do ramii i etyiiety import tkinter as tk from tkinter import messagebox omijamy omijamyproblem... problem... def klik(zdarz=none): tk.messagebox.showinfo("klik!","uwielbiam kliknięcia!") przypisanie obsługi zdarzenia dla etyiiety przypisanie obsługi zdarzenia dla etyiiety o = tk.tk() l = tk.label(o,text="etykietka:") l.bind("<button-1>",klik) l.pack() tk.button(o,text="przycisk",command=klik).pack(fill=tk.x) f = tk.frame(o, height=30, width=100, bg="blue") f.bind("<button-1>",klik) f.pack(); o.mainloop() przypisanie przypisanieobsługi obsługizdarzenia zdarzeniadla dlaramii ramii 03_02.py
Anatomia zdarzenia: zdarzenie jest obiektem, itórego własności ują szazegółowo oioliaznośai mu towarzysząae nie wszystkie własnośai mają sens dla iażdego zdarzenia
własność własnośćzdarzenia zdarzenia widget widget obieit obieit(nie (nienazwa!) nazwa!)widżetu, widżetu,itóry itóryjest jestadresatem adresatemzdarzenia zdarzenia x,y x,y pozyaja pozyajaiursora iursoramyszy myszywwahwili ahwiliodebrania odebraniazdarzenia zdarzenia(względem (względemwidżetu) widżetu) x_root, x_root, y_root y_root pozyaja pozyajaiursora iursoramyszy myszywwahwili ahwiliodebrania odebraniazdarzenia zdarzenia(względem (względemeiranu) eiranu) char char iod iodznaiu znaiunaaiśniętego naaiśniętegoa a(tylio (tyliozdarzenia zdarzenia ilawiaturowe ) ilawiaturowe ) keysym keysym symbol symbolnaaiśniętego naaiśniętegoa a(tylio (tyliozdarzenia zdarzenia ilawiaturowe ) ilawiaturowe ) keycode keycode iod iodnaaiśniętego naaiśniętegoa a(tylio (tyliozdarzenia zdarzenia ilawiaturowe ) ilawiaturowe ) num num numer numeriliiniętego iliiniętegoprzyaisiu przyaisiumyszy myszy(tylio (tyliozdarzenia zdarzenia myszowe ) myszowe )
własność własnośćzdarzenia zdarzenia width, width, height height rozmiar rozmiarwidżetu widżetupo pozdarzeniu zdarzeniu<confgure> <Confgure> type type typ typzdarzenia zdarzenia
Teraz zmodyfiujemy nasz program tai, aby dowiedzieć się azegoś o zdarzeniu, itóre do nas dotarło...
import tkinter as tk from tkinter import messagebox def klik(z=none): if z==none: tk.messagebox.showinfo("klik!","uwielbiam kliknięcia!") else: s = "x="+str(z.x)+",y="+str(z.y)+ \ ",num="+str(z.num)+",type="+(z.type) tk.messagebox.showinfo("klik!",s) wypisujemy nieitóre dane zdarzenia wypisujemy nieitóre dane zdarzenia o = tk.tk() l = tk.label(o,text="etykietka:") l.bind("<button-1>",klik) l.pack() tk.button(o,text="przycisk",command=klik).pack(fill=tk.x) f = tk.frame(o, height=30, width=100, bg="blue") f.bind("<button-1>",klik) f.pack(); o.mainloop() 03_03.py
obsługę zdarzenia można nie tylio dowiązać (bind) można ją również odwiązać (unbind) w przypadiu widżetów iliialnyah ten sam efeit osiąga się przez zmianę własnośai aommand odwiązanie zdarzenie od widżetu powoduje, że widżet przestaje na to zdarzenie reagować przywróaenie status quo ante wymaga ponownego związania najpierw poiażemy, jai to można zrobić ze zdarzeniem przypisanym parametrem aommand
from tkinter import * from tkinter import messagebox def włwył(): global b2, włącznik print(włącznik) if włącznik: b2.config(command=0) b2.config(text="buuu") else: b2.config(command=aqq) b2.config(text="a kuku") włącznik = not włącznik def aqq(): messagebox.showinfo("","a KUKU!") włącznik=true o = Tk( ) b1 = Button(o,text="Włącz/Wyłącz",command=włwył) b1.pack() b2 = Button(o,text="A kuku",command=aqq) b2.pack() o.mainloop() taiie taiieprzypisanie przypisaniejest jestwwzasadzie zasadzie nadużyciem, ale nie martwimy nadużyciem, ale nie martwimysię siętym tym waale; przypisanie azegoiolwiei, ao waale; przypisanie azegoiolwiei, aonie nie jest aallbaaiiem, wyłąaza obsługę jest aallbaaiiem, wyłąaza obsługę zdarzenia zdarzeniai ioototonam namahodzi! ahodzi! 03_04.py
A teraz to samo, ale dla zdarzenia dowiązanego metodą bind():
from tkinter import * def włwył(): global b2, włącznik if włącznik: l.unbind("<button-1>") else: l.bind("<button-1>", loko) włącznik = not włącznik def loko(z): global l,słowo,słowa słowo += 1 l.config(text=słowa[słowo % 4]) włącznik=true słowa = ["Stoi", "na", "stacji", "lokomotywa"] słowo = 0 o = Tk( ) b1 = Button(o,text="Włącz/Wyłącz",command=włwył) b1.pack() l = Label(o, text=słowa[słowo]); l.bind("<button-1>", loko) l.pack() o.mainloop() 03_05.py
Istnieje również metoda okna głównego o nazwie bind_all(), itóra dowiązuje obsługę zdarzenia do wszystkich widżetów istniejąayah w oinie:
from tkinter import * from tkinter import messagebox No Noi imamy mamyproblem problem :(:( def hej(z): messagebox.showinfo("","hej!") o = Tk( ) b=button(o,text="włącz/wyłącz").pack() Label(o, text="etykietka").pack() Frame(o,bg="yellow",width=100,height=20).pack() o.bind_all("<button-1>", hej) o.mainloop() 03_06.py
Rozwiążemy ten problem używająa metody unbind_all(), itóra odwiązuje obsługę zdarzenia od wszystkich widżetów istniejąayah w oinie:
from tkinter import * from tkinter import messagebox def hej(z): global o o.unbind_all("<button-1>") messagebox.showinfo("","hej!") o.bind_all("<button-1>", hej) o = Tk( ) b=button(o,text="włącz/wyłącz").pack() Label(o, text="etykietka").pack() Frame(o,bg="yellow",width=100,height=20).pack() o.bind_all("<button-1>", hej) o.mainloop() 03_07.py