K bezproblémovému běhu každé aplikace, která má něco smysluplného umět, je potřeba, abychom uměli vyvolávat a zpracovávat události.
15.10.2010 00:00 | Jiří Václavík | přečteno 11974×
Pro odložené nebo opakované vykonávání nějaké akce máme v Tk zabudované metody after a repeat. Metodou after vytvoříme jednorázový příkaz, který bude vykonán za určený čas. Toto je v jistém smyslu analogie s unixovým nástrojem at.
Podobně funguje metoda repeat, která vytváří trvalý příkaz. Zde se akce periodicky opakuje.
Vyzkoušíme si to a napíšeme si jednoduchou hru. Ta bude spočívat v tom, že uživatel musí co nejdéle bez přestávky klikat na tlačítko. Jakmile jednou nestihne kliknout včas, hra skončí a oznámíme mu, kolikkrát se mu podařilo kliknout. V programu využijeme ještě metodu cancel, která jednorázový příkaz ruší.
use Tk;
use strict;
my $m = MainWindow->new();
my $pocetkliku = 0;
my $casovac;
$m->Label(-text=>"Ukolem hry je klikat na tlacitko co nejdele.")->pack();
$m->Button(-text=>"Aktivita!", -command=>\&klik)->pack();
$m->Button(-text=>"Konec", -command=>sub{exit})->pack();
MainLoop();
sub klik {
$pocetkliku++;
$casovac->cancel if $pocetkliku!=1;
$casovac=$m->after(200, \&konec);
}
sub konec {
$m->messageBox(-message => "Klikl jsi ${pocetkliku}krat.", -type => "ok");
$pocetkliku = 0;
}
S některými událostmi jsme se setkali již dříve. Šlo například o stisk tlačítka. Teorii událostí nyní podstatně rozvineme.
S událostmi lze manipulovat pomocí metody bind, kterou lze volat nad libovolným widgetem. Předáváme jí typ události a akci, která se má vykonat. Metoda bind nám umožňuje zachytávat takové události jako je například stisky a uvolnění kláves nebo tlačítek na myši, pohyb kurzorem myši.
Událost se zapisuje jako nějaký řetězec uzavřený mezi symboly <>. Přesněji řečeno má každá událost následující tvar.
<klávesa1-klávesa2-...-klávesan-typ-symbolické_jméno_klávesy>
Přitom klávesy můžeme dosadit například pro události z myši Button1, Button2, Double, Triple a pro události z klávesnice Control, Alt, Shift. Any zastupuje libovolnou klávesu.
Typ události nabývá jedné z následujících hodnot:
Poslední položka, symbolické_jméno_klávesy, nabývá obvykle pro tisknutelné znaky tohoto znaku. Pro jiné klávesy existují speciální řetězce jako například Enter, BackSpace, F7 apod. Kompletní seznam možností je na tcl.activestate.com/man/tcl8.4/TkCmd/keysyms.htm.
Často používané události lze různými způsoby zkracovat zkracovat, takže můžeme vynechávat KeyPress a ButtonPress. Uveďme několik příkladů zápisu události.
Již bylo řečeno, že příkaz bind sváže událost a akci. bind přijímá jako parametr buď událost nebo posloupnost událostí. Posloupnost se zapisuje jako několik událostí oddělených mezerou.
Již jsme zmínili, že událost <Any-KeyPress> znamená stisk libovolné klávesy. Otázkou však je, jak potom zjistíme, která klávesa vlastně byla stisknuta. Řešení nalezneme ve volání funkce Ev, která nám je schopna poskytnout libovolnou informaci o nastálé události. Tato funkce přijímá parametr ve formě řetězce, podle kterého vrací požadovanou informaci. Možné parametry jsou například následující.
parametr | Význam |
x | x-souřadnice myši |
y | y-souřadnice myši |
k | název klávesy |
t | čas události |
use Tk;
$m = MainWindow->new;
$m->configure(-width=>400, -height=>400);
$p = $m->Canvas(-cursor=>"crosshair", -width=>400, -height=>400, -background=>"white")->pack;
for($i=10; $i<200; $i+=10){
$h=255/400*$i;
$p->createRectangle($i, $i, 400-$i, 400-$i, -outline=>sprintf("#%02x%02x%02x", $h, $h, $h));
}
$status=$m->Label(-text=>"Klikni nekam do okna.")->pack();
$p->Tk::bind( "<Button-1>", [sub{$status->configure(
-text=>"Klikl jsi na pozici [$_[1], $_[2]]")}, Ev("x"), Ev("y")]);
MainLoop;
Zajímavý je pro nás předposlední řádek. Jakmile klikneme levým tlačítkem někam do okna, vyvolá se událost <Button-1>. Protože jsme pomocí bind vytvořili k této události vazbu, dojde k provedení příslušné akce. Připomeňme, že, chceme-li akci předat parametry, musíme je vložit společně s odkazem na podprogram do pole.
Předchozí program vytvoří následující okno.
Zachycení události (kliknutí do prostoru okna) a výpis souřadnic kurzoru myši
Podívejme se nyní na situaci, kdy uživatel vykonal dvojité kliknutí myši. Nastaly dvě události: <Button-1> a <Double-Button-1>. V takovém případě má přednost méně obecná událost, tedy v našem případě <Double-Button1>. To znamená, že po prvním kliknutí je okamžitě vyvolána událost <Button-1> a po druhém kliknutí už pouze <Double-Button-1>.