přihlásit 5358/805876

Hello World! [koncept]

Na začátek předvedu vytvoření minimální GUI aplikace Hello World, na které lze objasnit základní koncepty GUI programování a PyGTK. Zadání je jednoduché. Vytvořit program s jedním tlačítkem, které po stisknutí vypíše na konzoli text "Hello World!". Výsledek bude vypadat tedy nějak takto:

screenshot

Nejprve je nutno aplikaci navrhnout. Jestliže jste ještě nečetli článek o tvorbě GUI obecně, bylo by dobré si ho přečíst, je v něm vysvětlena terminologie.Pro GUI aplikace je velmi výhodné používání objektově orientovaný návrh a proto se ho přidržím. Vzhledem k extrémní jednoduchosti programu a pro větší přehlednost si vystačím s jedním objektem/třídou, do které nacpu všechno. Vy si ale pamatujte, že správný návrh aplikace by měl mít aplikační logiku a prezentační vrstvu oddělenu. V našem případě je aplikační logika (tedy výkonný kód programu) výpis textu na obrazovku a prezentační vrstva je GUI.

Náš program tedy uvaříme v jedné třídě a přísady z kterých ho uvaříme jsou:

Dále budeme muset spustit smyčku pro čekání na událost, která je typická pro všechny GUI programy. GUI sestavíme v inicializační metodě třídy, každý handler bude metoda třídy a smyčku pustíme mimo třídu. Návrh aplikace je hotov a mohu se pustit do realizace.

 1 import gtk
 2 
 3 class HelloWorld(object):
 4 
 5     def __init__(self):
 6         # vytvoreni widgetu okna
 7         window = gtk.Window()
 8         window.connect("destroy", self.destroy)
 9         window.set_border_width(10)
10 
11         # vytvoreni widgetu tlacitka
12         button = gtk.Button("Hello World!")
13         button.connect("clicked", self.hello)
14 
15         # seskladani widgetu a jejich zobrazeni
16         window.add(button)
17         window.show_all()
18 
19     def hello(self, widget):
20         print "Hello World!"
21 
22     def destroy(self, widget):
23         gtk.main_quit()
24 
25 app = HelloWorld()
26 gtk.main()

ukázka č. 1

Tak a je to. Teď ještě musím vysvětlit, jak to celé funguje. Program je zapouzdřen do třídy HelloWorld, která má inicializační metodu v níž vytváříme GUI aplikace a dvě metody hello() a destroy(), které slouží jako handlery pro obsluhu událostí.

Vyčkávací smyčka

Po spuštění programu na řádku 25 nejprve vytvořím instanci třídy HelloWorld (čímž se fyzicky vytvoří GUI) a pak funkcí main() v modulu gtk spustím na řádku 26 vyčkávací smyčku. Program následně čeká na události a běží dokud není vyčkávací smyčka ukončena funkcí main_quit(), kterou spouštím při události zavření okna v handleru destroy() na řádku 23.

Pozor: kdybych tuto událost ignoroval nebo smyčku neukončil, tak se okno zavře, ale program poběží dál bez možnosti ovládání. Něco takového bychom sice mohli chtít i schválně, ale obvykle je to chyba programu.

Tvorba GUI

Pro tvorbu GUI si vystačíme s modulem gtk, který obsahuje všechny widgety i funkci pro spuštění a ukončení vyčkávací smyčky. Každý widget má svou třídu a widget vytvoříme jednoduše vytvořením instance příslušné třídy. V ukázce se vytváří widgety window (okno) a button (tlačítko) na řádku 7 a 12.

Pro vytvoření okna aplikace slouží widget gtk.Window [1]. U okno může vzniknout řada událostí a pro jednu z nich, zavření okna, připojuji na řádku 8 handler destroy(). Podrobněji viz dále. Dále oknu na řádku 9 nastavuji okraj na 10 pixelů, aby program trochu lépe vypadal.

Pro vytvoření tlačítka slouží widget gtk.Button [1]. I u tlačítko může vzniknout řada událostí a k události kliknutí na tlačítko, připojuji handler hello(). Podrobněji viz dále.

Teď mám vytvořeny a nastaveny widgety a musím je ještě poskládat dohromady. V této ukázce je to jednoduché, tlačítko do okna vložím pomocí metody add() okna window a jako parametr ji předám tlačítko button.

Všechny uvedené kroky se provádějí jen někde v paměti počítače vyhrazené naší aplikaci. Proto se widgety ještě nezobrazují na obrazovce. Aby se widget zobrazil, musí být splněny dvě podmínky:

Přímo připojený widget je tlačítko připojené k oknu metodou add(). Na tomto tlačítku je nápis "Hello World!", který je realizován automaticky vytvořeným widgetem gtk.Label. Nápis je připojen přímo k tlačítku a tak nepřímo k oknu.

Zobrazení widgetu na obrazovce znamená, že aplikace (přesněji GTK+) začne komunikovat s grafickým systémem (třeba na Linuxu je to X Server) a pošle mu příkazy, pro vytvoření a zobrazení widgetu na obrazovce.

Volání metody show() je možno si ulehčit automatickým zavoláním metody show_all() u kořenového widgetu. Tato metoda projde rekurzivně všechny widgety a zavolá na nich metodu show(). To používá má ukázka na řadku 17.

Události, signály a handlery

Událost je například kliknutí myší na tlačítko, která se dá popsat jako uživatel najede na tlačítko kurzorem myši a následně stiskne a pustí levé tlačítko (u praváků).

Tato událost vyvolá řadu signálů, které můžeme zachytit a tak na událost zareagovat. Namátkou se vyvolají signály pressed (tlačítko stisknuto), released (tlačítko puštěno), clicked (na tlačítko bylo kliknuto), enter (nad tlačítkem se objevil kurzor) a řada dalších.

Signály se pošlou všem widgetům, kterých se týkají, tedy i několika widgetům současně. To je například případ signálu motion-notify-event, který se opakovaně vyvolává při pohybu kurzoru nad widgetem. A když se kurzor pohybuje nad tlačítkem, tak se zároveň pohybuje nad oknem a pošle se oboum widgetům.

Pokud chceme na signál reagovat, musíme k němu připojit handler. Děje se tak metodou connect(), kde jako první parametr předáváme název signálu, jako druhý odkaz na handler a dál následují volitelné uživatelské data.

K signálu lze připojit i několik handlerů současně. Využívá toho i samotné GTK+, kdy například při najetí kurzoru nad tlačítko může toto automaticky zvýraznit (záleží na použitém skinu) a přitom sami můžeme k této události připojit vlastní handler a reagovat ještě (navíc) jinak, třeba zobrazením nápovědy k tlačítku.

Také k signálu nemusíme připojit žádný handler, pak se zdánlivě nic neděje, ale signály se posílají dál, což může významně zatížit systém. Je potřeba si uvědomit, že tyto signály posílá grafický systém našemu programu. Na linuxu grafický systém představuje X Server a jak známo, ten umožňuje mít spouštět aplikace vzdáleně. Tedy uživatel sedí u počítače s X Serverem a aplikace může běžet na jiném počítači, klidně třeba u protinožců. Všechny signály se pak posílají mezi X Serverem a aplikací po síti a velké množství signálu může síť přetížit.

To se týká především signálů, které se vyvolávají často a pro hodně widgetů. Typický případ je signál motion-notify-event. Ten se vyvolává rychle za sebou při pohybu kurzoru myši nad widgetem, takže počet signálů jde do desítek za vteřinu na jeden widget a jeden signál. Pokud takový signál nepotřebujeme, je to plýtvání výkonem. Naštěstí existuje možnost grafickému systému říct které signály nás u kterého widgetu zajímají a ty nezajímavé se pak neposílají.

V GTK+ se to nastavuje maskou signálů a každý widget má nastavenu nějakou masku, takže widgetu se posílají jen pro něj typicky zajímavé signály. Náročné signály jako motion-notify-event jsou defaultně vypnuty. Tuto defaultní maska signálů může programátor změnit a nastavit jinou. Tato změna musí proběhnout před tím, než je widget zobrazen (to jest před tím, než je vytvořen v grafickém systému).

 [1]
Seznam URL na stránce:
[1]

Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in /web/htdocs2/wraithcz/home/www/python/data/sessions/sessions1.php on line 2