Vsak malo bolj resen grafični program predvideva interakcijo uporabnika s pomočjo miške oziroma tipkovnice.
Spomnimo se, da pri VPythonu potrebujemo desni mišji gumb za vrtenje našega pogleda na sceno, kolešček pa za približevanje ali
oddaljevanje scene. Za kakšno drugo interakcijo preostane levi mišji gumb. In seveda tipkovnica.
Oglejmo si preprost primer: Vidimo sceno s kroglo. Program v neskončni zanki čaka na klik z levim mišjim gumbom, kar dosežemo s
stavkom scene.pause('Za nadaljevanje klikni z miško').
Program nas obvesti, da čaka. Po kliku z levim mišjim gumbom pa izpiše trenutni položaj miške:
GlowScript 3.0 VPython
sphere() while True:
ev = scene.pause('Za nadaljevanje klikni z miško')
print("Položaj miške:"+ ev.pos) # Izpis polozaja miške
Sicer pa lahko prestrezamo tudi druge dogodke. Imamo naslednje možnosti:
scene.waitfor('click') # čakamo na klik z miško
scene.waitfor('mousedown') # Čakamo na pritisk na mišji gumb
scene.waitfor('mouseup') # Čakamo na sprostitev mišjega gumba
scene.waitfor('mousemove') # Čakamo na premik miške
scene.waitfor('mouseenter') # Čakamo na vstop miške v sceno (na takoimenovano platno)
scene.waitfor('mouseleave') # čakamo, da z miško zapistimo sceno (platno)
scene.waitfor('keydown') # čakamo na pritisk tipke na tipkovnici
scene.waitfor('keyup') # čakamo na sprostitev tipke na tipkovnici
Program pa običajno ne čaka na nek dogodek, saj bi bil v tem primeru
neodziven na druge dogodke, (primer, čakamo na klik z miško in
se tako ne moremo odzivati na tipke s tipkovnice) Uporabiti moramo
drugačen način interakcije.
Prestrezanje dogodkov
Imamo dva načina prestrezanja dogodkov z miško oziroma tipkovnico: izpraševanje (polling) in odzivne funkcije (callback).
Pri izpraševanju stalno preverjamo, ali kakšen dogodek čaka na obdelavo.
Taki dogodki se po kronološkem zaporedju nabirajo v čakalni vrsti in z ukazom tipa
scene.mouse.getevent() #dobimo naslednji dogodek in ga obdelamo.
Pri načinu z odzivnimi funkcijami pa definiramo funkcijo, ki naj se izvede ob
nastopu določenega dogodka. Tak način je najbolj primeren za obravnavo dogodkov z miško ali tipkovnico.
Preprost primer:
GlowScript 3.0 VPython
s = sphere(color=color.cyan)
def SpremeniBarvo():
if s.color.equals(color.cyan):
s.color = color.red
else:
s.color = color.cyan
scene.bind('click', SpremeniBarvo)
V tem zgledu smo definirali funkcijo SpremeniBarvo. Nato to funkcijo
povežemo (bind)s klikanjem na našo sceno. Kadarkoli
bomo kliknili na sceno, bo program poklical funkcijo SpremeniBarvo in v
njej spremenil barvo krogle.
Tako bi lahko povezali z ustreznimi funkcijami tudi druge tipe dogodkov:
V našem primeru nastopa tudi spremenljivka ev (lahko bi imela tudo
kakšno drugo ime). Ta spremenljivka vsebuje podrobnosti o dogodku, ki
jih lahko uporabimo. Tako lahko na trenutni položaj miške postavimo nov
objekt, na primer tako:
box(pos=ev.pos) # na trenutni položaj miške postavimo nek objekt (na primer kocko)
V spodnjem primeru imamo eno funkcijo, ki se sproži, ko kliknemo z miško. Druga funkcija pa se sproži, ko pritisnemo na tipko
tipkovnice:
GlowScript 3.0 VPython def premakniObroc(ev): # odzivna funkcija, ki reagira na tipke kodaTipke= ev.which print(ev.event, " koda tipke =" + kodaTipke) if kodaTipke == 39: #puščica v desno obroc.pos.x = obroc.pos.x + 0.1 else if kodaTipke == 37: #puščica v levo obroc.pos.x = obroc.pos.x - 0.1 else if kodaTipke == 38: #puščica gor obroc.pos.y = obroc.pos.y + 0.1 else if kodaTipke == 40: #puščica gor obroc.pos.y = obroc.pos.y - 0.1 else if kodaTipke ==189: #+ približa obroč obroc.pos.z = obroc.pos.z + 0.1 else if kodaTipke ==187: #- oddalji obroč obroc.pos.z = obroc.pos.z -0.1
def dodajKroglo(ev): # odzivna funkcija, ki reagira na klik miške sphere(pos=ev.pos, radius = 0.1)
scene.bind('keydown', premakniObroc ) # povezava pritiskanja tipk in odzivne funkcije scene.bind('click', dodajKroglo) # povezava klikanja z miško in odzivne funkcije obroc = ring( axis=vector(0,0,1), radius=0.5, thickness=0.1, color=color.green) scene.autoscale = False # da se scena ne bo avtomatsko manjšala ali večala
Sicer pa lahko z odzivnimi funkcijami navezujemo naslednje dogodke:
Dogodka 'mousedown' oziroma 'mouseup' nastopita pri pritisku ali
sprostitvi levega mišjega gumba. Dogodek 'mousemove' nastopi pri
premikanju
miške.Dogodek 'redraw' nastopi tik pred osvežitvijo 3D scene na
zaslonu, dogodek 'draw_complete' pa takoj po tej osvežitvi.(ta dva
dogodka imata bolj tehnično uporabo, ker lahko tako osveževanje terja
nekaj časa).
Lahko pa eno odzivno funkcijo povežemo z več dogodki. V spodnjem
primeru sprožita isto odzivno funkcijo tako pritisk kot sprostitev
mišjega
gumba:
scene.bind('mouseup mousedown', spremeniNekaj)
Podrobnosti o dogodku
Podrobnosti o dogodku lahko dobimo z odzivno funkcijo, ki ji kot
argument podamo
ime dogodka (v spodnjem primeru smo za to uporabili spremenljivko z
imenom evt). Naslednji primer ponazoruje definicijo in uporabo take
funkcije:
Vrednost evt.eventbo "keydown", če smo pritisnili na neko tipko tipkovnice.
Vrednost evt.which pa poda numerično kodo tipke ali indikator gumba (če
smo kliknili z miško). Tako je na primer evt.whichenak 65 za črko 'A'. Če smo pri tem tiščali tipko shift, bo spremenljivka scene.mouse.shiftenaka true.
Analogno velja za spremenljivki scene.mouse.ctrloziroma scene.mouse.alt.
Razvezanje odzivnih funkcij (Unbinding)
Predpostavimo, da smo pravkar izvedli scene.bind('mousedown mousemove', Povleci), a ne želimo več pošiljati dogodkov 'mousemove' funkciji Povleci. To dosežemo s stavkom :
scene.unbind('mousemove', Povleci)
Isto dosežemo tudi tako, da odzivno funkcijo začasno ustavimo ali jo spet omogočimo:
evt = scene.bind('mousemove', Povleci) ..... evt.stop() # začasno prekini proženje funkcije Povleci s premikanjem miške ..... evt.start() # začni proženje funkcije Povleci s premikanjem miške
S preverjanjemevt.enabled lahko ugotovimo, ali je odzivna funkcija trenutno ustavljena ali onemogočena.
Izbiranje teles z miško
Za konec si oglejmo še primer, kako lahko z miško izbiramo predmete na
sceni in z njimi nato nekaj naredimo. Uporabimo spremenljivko
scene.mouse.pick, ki kaže na izbrani objekt. Če pa smo kliknini v prazno, je ta spremenljivka enaka None.
Spodnji primer je interaktiven in si lahko ogledamo, kako tak zgled vključimo na svojo spletno stran:
GlowScript 3.0 VPython
selected= None oldPos = vector(0,0,0)
def izberiPredmet(): global selected, oldPos obroc.color= color.blue # privzeta barva obroča kvader.color=color.red # privzeta barva kvadra if scene.mouse.pick!= None: #Kateri predmet smo izbrali selected =scene.mouse.pick oldPos = scene.mouse.pos selected.color = color.yellow
def opraviNalogo(): global selected if selected==kvader: kvader.pos = scene.mouse.pos