Perl (124) - Gtk2 - události a čas
S událostmi a časem již máme z předchozích grafických toolkitů nějaké zkušenosti. Jak k této oblasti ale přistupuje Gtk2?
5.1.2011 00:00 |
Jiří Václavík
| Články autora
| přečteno 3233×
Události
Představme si, že program právě vykonává Gtk2::main a čeká na události. Jakmile nastane událost (událostí se rozumí například stisk klávesy, pohyb myší do nějakého daného prostoru atd.), emituje se signál. Tyto signály mohou být emitovány různými widgety a existuje jich řada druhů, podle toho, jak byly vyvolány. S nejběžnějšími se v seriálu postupně seznámíme.
Signály budeme odchytávat. Pokud signál neodchytneme, nic se nestane. Událost nezpůsobí žádnou akci. To se děje velmi často, neboť to prostě nemusí být potřeba. Pro uvědomění si zkuste například teď v internetovém prohlížeči stisknout klávesu ESC. Ve většině prohlížečů na tuto událost není definována reakce, tudíž se vůbec nic nestane. Navíc signálů se i v jednoduché aplikaci emituje obrovské množství.
Pokud ale uživatel například klikne na tlačítko nebo provede jinou událost, od které je nějaká návazná činnost očekávána, měli bychom se postarat o to, aby byla příslušná akce provedena. To je případ, který nás zajímá.
Signály se obvykle odchytávají voláním nějaké funkce, která se nám o to postará. Musíme jí však sdělit několik věcí, aby věděla, co přesně po ní chceme.
- určit widget, který emitoval signál
- určit signál, na který chceme reagovat
- jak chceme reagovat (tj. odkaz na nějakou funkci [tzv. callback funkci], která se provede)
- případně něco dalšího - přepínače, parametry atd.
Callback funkce je obyčejný podprogram. Může být buď anonymní nebo pojmenovaný.
Ten pojmenovaný obvykle jako parametry dostane objekt reprezentující widget, který vyvolal signál, a případné parametry. Vypadá nějak takto.
sub akce {
my($self, $parametr) = @_;
#provedení akce
}
Signál obvykle propojujeme s akcí příkazem signal_connect, který dodržuje tuto strukturu.
$widget->signal_connect(typ_signalu => \&akce, $parametry);
Akce lze samozřejmě také modifikovat. Pro zrušení spojení signálu a akce lze použít metodu signal_handler_disconnect.
Příklad události - kliknutí na tlačítko
Upravíme náš program s tlačítkem tak, aby získalo funkcionalitu. Budeme chtít, aby se po stisknutí ukončila aplikace. Jinými slovy chceme, aby se po stisku tlačítka provedl podprogram konec, který vypadá takto.
sub konec {
my($widget) = @_;
Gtk2->main_quit;
}
Poznamenejme, že příkaz Gtk2->main_quit končí smyčku událostí a tedy v našem případě i celý program (ale kdybychom dále opět volali Gtk2->main, celá smyčka by se rozběhla nanovo).
Propojme tedy emitovaný signál s naším podprogramem. Použijme metodu signal_connect zavolanou nad tlačítkem. Po stisku tlačítka se vždy emituje signál clicked.
$tlacitko->signal_connect(clicked => \&konec);
Upravili jsme tedy celý program do následující podoby.
use Gtk2;
Gtk2->init;
sub konec {
my($widget) = @_;
Gtk2->main_quit;
}
$okno = Gtk2::Window->new("toplevel");
$okno->set_border_width(20);
$tlacitko = Gtk2::Button->new("Konec");
$tlacitko->signal_connect(clicked => \&konec);
$okno->add($tlacitko);
$tlacitko->show;
$okno->show;
Gtk2->main;
Proč se při zavření okna neukončí aplikace?
Gtk2 má tu vlastnost, že, zavřeme-li hlavní okno, aplikace běží dál. Na tom není nic špatného, ale ve většině případů budeme chtít aplikaci v takové situaci tak jako tak ukončit. Nyní to je třeba udělat například posláním SIGTERM, což není příliš elegantní řešení. Jak docílíme nápravy?
Existuje signál delete_event. Ten se emituje v reakci na událost zavření hlavního okna. Jednoduchým trikem zajistíme, aby se při emitaci delete_event celá aplikace ukončila.
$okno->signal_connect(delete_event => sub{Gtk2->main_quit});
Příklad - detekce stisknuté klávesy
Pomocí signálu key-press-event lze zachytávat klávesy z klávesnice. Zkusme tedy vytvořit akci, která proběhne po stisku libovolné klávesy. Budeme chtít vypsat nějakou informaci o stisknuté klávese.
$okno->signal_connect("key-press-event" => \&info);
Informaci budeme vypisovat pomocí popisku, který vytvoříme následovně.
$label = Gtk2::Label->new();
Jeho text pak nastavujeme pomocí set_markup.
$label->set_markup("Ahoj");
Podprogram info dostane jako parametr událost. Z ní můžeme získat id klávesy (metodou keyval). Máme k dispozici také hash %Gtk2::Gdk::Keysyms, který každé klávese přiřazuje nějaké id. Podívejme se pro zajímavost na část dat z tohoto hashe.
...
"downarrow" => 2302,
"Greek_chi" => 2039,
"ISO_Level2_Latch" => 65026,
"doubledagger" => 2802,
"guillemotleft" => 171,
"w" => 119,
"Pointer_Drag_Dflt" => 65268,
"threequarters" => 190,
"Hangul_Hanja" => 65332,
"cedilla" => 184,
"Armenian_e" => 16778599,
"MouseKeys_Enable" => 65142,
...
Z něj můžeme získat název stisknuté klávesy.
Podívejme se tedy na program, který nás informuje o událostech z klávesnice.
use Gtk2::Gdk::Keysyms;
use Gtk2 "-init";
sub info {
my($widget, $udalost)= @_;
my $id = $udalost->keyval;
for $k (keys %Gtk2::Gdk::Keysyms){
$label->set_markup("Stisknuto $k ($id)") if $Gtk2::Gdk::Keysyms{$k} == $id);
}
return 0;
}
$okno = Gtk2::Window->new("toplevel");
$okno->signal_connect("key-press-event" => \&info);
$label = Gtk2::Label->new();
$okno->add($label);
$okno->show_all;
Gtk2->main;
Uděláme ještě drobnou úpravu ve zdrojovém kódu, abychom se vyhnuli používání globálních proměnných. Při reakci na signál si necháme jako parametr předat label, který budeme modifikovat.
use Gtk2::Gdk::Keysyms;
use Gtk2 "-init";
sub info {
my($widget, $udalost, $label)= @_;
my $id = $udalost->keyval;
for $k (keys %Gtk2::Gdk::Keysyms){
$label->set_markup("Stisknuto $k ($id)") if $Gtk2::Gdk::Keysyms{$k} == $id);
}
return 0;
}
$okno = Gtk2::Window->new("toplevel");
$label = Gtk2::Label->new();
$okno->signal_connect("key-press-event" => \&info, $label);
$okno->add($label);
$okno->show_all;
Gtk2->main;
Výsledek vidíme na obrázku.
Po stisku w *** po stisku caps lock
Řekněme na tomto místě ne úplně související poznámku. Všimněme si závěru programu. Abychom nemuseli volat metodu show nad každým widgetem, lze použít místo všech těchto volání metodu show_all.
Příklad - tlačítka myši
Druhou důležitou skupinou signálů jsou ty, které byly emitovány událostmi myši. Signál button-release-event se vyvolá po kliknutí na daný widget.
Vytvořme si tlačítko, na které bude uživatel klikat. My budeme pro informaci vypisovat, které tlačítko myši uživatel stiskl.
Všechny potřebné věci již umíme a tak se podívejme na zdrojový kód této aplikace. Dodejme jen, že nad objektem události (ten dostaneme v callback funkci jako parametr) voláme metodu button, která nám vrací id tlačítka myši.
use Gtk2 "-init";
$okno = Gtk2::Window->new ("toplevel");
$vbox = Gtk2::VBox->new(0, 5);
$tlacitko = Gtk2::Button->new("Klikni");
$label = Gtk2::Label->new();
$tlacitko->signal_connect("button-release-event" => sub {
$label->set_markup("stisknuto ".$_[1]->button().". tlacitko mysi");
});
$vbox->pack_start($tlacitko, 1, 1, 0);
$vbox->pack_start($label, 1, 1, 0);
$okno->add($vbox);
$okno->show_all;
Gtk2->main;
Klikáme-li na tlačítko, můžeme pozorovat následující akce.
Po stisku 2. tlačítka myši *** po stisku 3. tlačítka myši
Čas
Pomocí Glib::Timeout lze nastavovat akce, které se budou periodicky vykonávat. Metodou add přidáváme úlohu. Uvádíme zde interval opakování v milisekundách, podprogram, který se má provést, a případně parametr a prioritu. Dokud podprogram nevrátí false, bude se jeho vykonávání opakovat.
Glib::Timeout->add(1000, \&akce, $parametr);
Verze pro tisk
| |
|
Nejsou žádné diskuzní příspěvky u dané položky.
Příspívat do diskuze mohou pouze registrovaní uživatelé.
|
|

Vyhledávání software

Vyhledávání článků
24.5.2013 6:42 /MaReK Olšavský V rodině Arduina je nový přírůstek, Arduino Yún („Yún“ je čínsky „mrak“). Nové Arduino je nejen první s GNU/Linuxem, ale nabízí i WiFi konektivitu.
Přidat komentář
24.5.2013 6:42 /MaReK Olšavský Na stránkách OMG! Ubuntu! vyšel krátký rozhovor s Markem Shuttleworthem. Tématy jsou Mir, Unity 8, budoucnost Ubuntu Touch, ale neunikl ani otázce na Windows 8.
Přidat komentář
23.5.2013 6:20 /MaReK Olšavský Lektoři, kteří používají e-learning, se již nejspíše setkali s platformou Moodle, jejíž vývojáři vydali verzi 2.5 populární platformy. Vedle několika stovek drobných vylepšení přibyly i novinky v mobilním přístupu, podpora twitterovského Bootstrapu pro témata, nebo instalace pluginů přes administrátorskou část webového rozhraní.
Přidat komentář
23.5.2013 6:20 /MaReK Olšavský Nová distribuce Pidora by měla zajímat Fedoristy, kteří mají Raspberry-Pi, jelikož je optimalizovaným spinem právě pro tuto platformu. Novinky Pidory shrnul Rick Lehrbaum .
Přidat komentář
23.5.2013 6:20 /MaReK Olšavský Krátce po vydání Debianu 7 vyšel i Debian GNU/Hurd 2013. Jádro GNU/Hurd se vyvíjí delší dobu, než Linux, ale zatím je spíše zajímavostí, protože jádro Linux se etablovalo u velkých společností a změna kurzu je více než nepravděpodobná.
Přidat komentář
22.5.2013 6:46 /MaReK Olšavský Svobodný software ve státní sféře nejsou jen vítězství, ale i mýty a pověry, které jej vylučují z výběru. 5 nejčastějších hloupostí o F/L/OSS zkritizoval Adam Firestone na stránkách OpenSource.com. Nesetkáváme se s podobnými argumenty i při snaze prosadit svobodný software ve firmách a u soukromých osob?
Přidat komentář
22.5.2013 6:46 /MaReK Olšavský Embedovatelná databáze SQLite byla vydána ve verzi 3.7.17, která nabízí větší rychlost (v některých úlohách až dvojnásobnou), opravy několika chyb, nebo vylepšení možností nahrávání rozšíření. O SQLite se píše výrazně méně, než o konkurenci, ale velmi pravděpodobně jde o nejčastěji nasazené řešení, díky mnoha aplikacím.
Přidat komentář
22.5.2013 6:45 /MaReK Olšavský 14. května 2013 IBM oznámila konec vývoje Lotus SmartSuite , Lotus Organizer a Lotus 1-2-3, balíků aplikací, jež byly považovány za špičku v oboru. Krátký nekrolog za legendární Lotus 1-2-3, který byl vyvíjen 30 let, sepsal Steven J. Vaughan-Nichols.
Přidat komentář
Více ...
Přidat zprávičku
 Poslední diskuze
18.5.2013 17:55 /
Martin Kumst Re: zaheslování bash scriptu nebo složky
18.5.2013 7:44 /
--- Re: Prosím o pomoc či radu
15.5.2013 19:21 /
Filip Vaněček Cesty k souborům při používání coolurl
13.5.2013 6:50 /
Radim Kolář Zabbix
8.5.2013 6:07 /
MaReK Olšavský Web Upd8
Více ...
|