GTK+ (GIMP ToolKit) jsou knihovny pro vývoj aplikací s grafickým uživatelským rozhraním (GUI). Vznikly původně jako základní stavební kámen aplikace GIMP (GNU Image Manipulation Program) a dnes jsou použity pro vývoj celé řady dalších zajímavých a známých aplikací (Abiword, Dia, Glade, GNOME, GnuCash, ...). Současná implementace podporuje platformy Linux i Windows a je tedy vhodná k psaní multiplatformních aplikací.
Knihovny GTK+ jsou šířeny pod licencí LGPL. Díky tomu mohou být použity k vývoji opensource, freware, ale i placených komerčních aplikací. Jsou napsány v čistém C a pro milovníky C++ existuje nadstavba s názvem GTK--, která zapouzdřuje jednotlivé třídy a procedury ve stylu C++. Existují i vazby na jiné programovací jazyky (Guile, Perl, Python, TOM, Ada95, Objective C, Free Pascal, Eiffel, Java a C#), ale těmi se zde nebudu zabývat.
Hlavními autory GTK+ jsou Peter Mattis, Spencer Kimball a Josh MacDonald. V současné době se o další vývoj stará Owen Taylor a Tim Janik.
Instalace knihoven GTK je pod operačním systémem Windows velice jednoduchá. Na adrese http://gladewin32.sourceforge.net/
jsou zveřejňovány aktuální verze instalačních balíčků.
Lze si vybrat mezi dvěma distribucemi:
Stejným způsobem je distribuována i nadstavba pro C++ nazvaná GTK-- (gtkmm). Ke stažení např. na adrese http://www.pcpm.ucl.ac.be/~gustin/win32_ports/. Existují i zdrojové soubory, které obsahují i makefiles pro různá prostředí Windows, avšak mé první pokusy zkompilovat GTK+ v prostředí CygWin selhaly a o další jsem se už raději ani nepokoušel.
Instalace pod operačním systémem Linux může záviset na použité distribuci. Některé nabízí balíčky s GTK+ knihovnami jako součást instalace. Navíc je třeba uvědomit si, že dynamické knihovny GTK jsou potřeba k běhu celé řady aplikací (předevšim pro desktop manager GNOME a jeho součásti). Pokud potřebujete nejaktuálnější verzi GTK, nebo nejsou developerské balíčky (které kromě dynamických knihoven obsahují i hlavičkové soubory) součástí distribuce, nezbývá než zkompilovat knihovny ze zdojových souborů (ke stažení na adrese ftp://ftp.gtk.org/pub/gtk/v2.6/). S kompilací jsem neměl problémy. Jediným nestandardním krokem bylo určení cílu instalace (v mém případě do adresáře /usr), který je defaultně nastaven na /usr/local.
beš$~/gtk+-2.6.7> ./configure # v mém případě ještě --prefix=/usr beš$~/gtk+-2.6.7> make beš$~/gtk+-2.6.7> make install
Nezbytnou součástí instalace je udržet si přehled o závislostech. Pro instalaci (čti kompilaci) knihoven GTK je třeba mít nainstalované tyto balíčky (v závorce uvádím verze balíčků, které jsem použil pro kompilaci GTK+ 2.6.7):
Knihovna libglade (v mém případě 2.5.1), vyžaduje pro instalaci kromě knihoven GTK také XML parser pro Perl.
Před instalací nadstavby GTK-- nainstalujte:
Knihovna libglademm potřebuje pro kompilaci překvapivě balíčky gtkmm a libglade.
Bývá programátorskou tradicí, že při výkladu nového jazyka, prostředí, apod. se začíná příznačně pojmenovanou aplikací "Hello world". Abych nezklamal, tak tady je:
#include <gtk/gtk.h> // statická metoda, která bude volána po zavření okna static void ondestroy( GtkWidget *widget, gpointer data ) { gtk_main_quit(); // ukončí cyklus zpráv (funkci gtk_main) } int main( int argc, char *argv[] ) { // ukazatel na okno a tlačítko na něm GtkWidget *window, *button; // inicializace knihoven GTK gtk_init(&argc, &argv); // vytvoření nového okna window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // připojení funkce "ondestroy" na signál "destroy" (zavření) okna g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(ondestroy), NULL); // natavení vnitřního odsazení (mezi tlačítkem a okrajem okna) gtk_container_set_border_width(GTK_CONTAINER(window), 16); // vytoření tlačitka button = gtk_button_new_with_label("Hello world"); // umístění tlačítka na okno gtk_container_add(GTK_CONTAINER(window), button); // zviditelnění tlačítka gtk_widget_show(button); // zviditelnění okna gtk_widget_show(window); // hlavní cyklus zpráv knihoven GTK (ukončí se voláním "gtk_main_quit();") gtk_main(); return 0; }
Po kompilaci dostaneme aplikaci, jejiž okno bude vypadat asi takhle:
Aplikace nebude provádět žádnou činnost, pouze se při zavření okna sama ukončí. Pokud bych nenavázal signál na událost "destroy" objektu window,
pak by po zavření okna zůstala aplikace běžet a jediným způsobem, jak ji ukončit by byl přikaz kill (resp. ukončení procesu ve Windows).
Kompilace pro operační systém linux je jednoduchá, jak by zkušneý developer čekal.
gcc -Wall -o appname `pkg-config --cflags --libs gtk+-2.0` main.c
Kompilace pro platformu windows je o trochu komplikovanější, protože nemáme k dispozici pkg-config a interpretování části příkazové řádky (jako zpětné apostrofy). Knihovny GTK (v instalaci developer) obsahují program pkg-config.exe, který se chová obdobně jako pkg-config v linuxu. Je však potřeba si vypsat výstup příkazu
pkg-config.exe --cflags --libs gtk+-2.0
a doplnit jej do příkazového řádku
gcc -Wall -o appname.exe -I"\gtk-2.0" -I" \..\lib\gtk-2.0\include" -I" \atk-1.0" -I" \pango-1.0" -I" \glib-2.0" -I" \..\lib\glib-2.0\include" -lgtk-win32-2.0 -lgdk-win32-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lpangowin32-1.0 -lgdi32 -lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -lglib-2.0 main.c
Aplikaci pkg-config.exe naleznete ve stejném adresáři, kde se nachází knihovny GTK
V některých vývojových prostředích (např. v mém oblíbeném Dev-C++) lze nastavit paramertry kompilátoru a linkeru přímo a jednou pro vždy a není třeba nad nimi dále přemýšlet.
Jak již bylo řečeno, rozhraní GTK+ je napsáno v čistém C. Přesto však zachovává hierarchickou strukturu tříd. Všechny procedury jsou pochopitelně globální a objekt, se kterým pracují, dostanou ukazatelem jako první parametr.
![]() Hierarchie tříd (klikněte pro zvětšení). |
Všechny zobrazitelné objekty jsou potomky třídy GtkWidget (widget = udělátko, nástroj). Každý widget (zobrazitelný objekt) musí být umístěn na nějakém otcovském kontejneru (to je widget, který je potomkem GtkContainer). Každý kontejner obsahuje právě jeden widget. Widget se snaží vyplnit celý svůj kontainer a zároveň mění svoji velikost s kontainerem. Aby bylo možné umístit do okna více widgetů, existují speciální widgety, které zaplní otcovský konteiner a zároveň vytvoří několik konteinerů (tedy rozdělí konteiner na několik částí). Speciálním případem je potom widget GtkFixed (popř. jeho scrolovací verze GtkLayout), který vytoří konteiner pro více widgetů.
Většina widgetů má nějaké signály. Signály nastávají při určitých událostech (např. zavření okna, kliknutí myší, apd.). Ke každému signálu je možné připojit i několik procedur kódu, který se provede, pokud signál nastane. Připojení procedury k signálu se provádí procedurou g_signal_connect a jednotlivé procedury jsou volány v tom pořadí, v jakém byly připojeny. Připojené procedury lze průběžně zakazovat-povolovat, nebo je i odpojit.
Na připojeném obrázku si můžete prohlédnout hierarchii vybraných objektů GTK+. Důležité objekty (GtkObject, GtkWidget a GtkContainer) jsou zvýrazněny modře. Hierarchie sice není kompletní, ale obsahuje většinu tříd. Tuto hierarchii jsem překreslil z Tutoriálu ke GTK.
Základními prvky jsou widgety, které tvoří, nebo jinak upravují otcovský konteiner
Jak již bylo řečeno v předchozí kapitole, jednen konteiner může obsahovat pouze jeden widget. Z tohoto důvodu je nutné mít k dispozici nástroje na rozdělení konetineru a také na zarovnávání prvků. K těmto účelů slouží speciální widgety:
![]() Horizontální a vertikální dělení (GtkHBox, GtkVBox) |
![]() Tabulka (GtkTable) |
![]() Fixní pozice (GtkFixed) |
![]() Zarovnání (GtkAlignment) |
Mezi běžné ovládací prvky, které programátor využívá denně, patří:
Hlavní nabídka programu (menu) a vysouvací nabídky (popup menu) jsou standardem při tvorbě aplikací. Pro vytváření nabídek se používají tyto widgety:
Nemenší váhu než menu mají dnes také lišty nástrojů:
Většina aplikací mívá také stavový řádek GtkStatusbar, který je umístěn na dolním okraji a zobrazuje stav aplikace, nebo třeba také nápovědu.
GTK umožňuje nastavovat způsob vykreslování aplikací bez jakékoli nutnosti jeich změn. Ve Windows je k tomuto účelu aplikace "Theme Selector",
ve které lze nastavit téma. Téma se nastavuje globálně pro všechny aplikace, nebo jen pro aplikace spouštěné přihlášeným uživatelem.
Nastavení se ukládá do souborů "gtkrc", které se nachází buď v domovských složkách uživatelů (pro lokální nastavení), nebo ve výchozím adresáři GTK+
\etc\gtk-2.0\ (v mém případě na
V operačním systému Linux se konfigurace vzhledu provádí pomocí konfiguračních souborů, které jsou uloženy buď pro lokální nastavení v domácím adresáři, nebo v obvyklém adresáři /etc/gtk/. Nejprve se hledá soubor ".gtkrc", pokud není nalezen hledá se soubor ".gtkrc.<jazyk>", kde <jazyk> je hodnota systémové proměnné $LANG. Tj. pokud je nastaveno prostředí na Spojené Státy (us), pak je hledán soubor ".gtkrc.us"
Knihovny GTK obsahují rovněž funkce pro načítání témat (konkrétně gtkrc souborů) dynamicky za běhu aplikace.
Na závěr uvádím několik snapshotů stejné aplikace v různých tématech:
![]() Výchozí téma |
![]() téma "Metal" |
![]() téma "MS-Windows" |
![]() téma "Litoral" |
![]() Ukázka aplikace Glade (klikněte pro zvětšení) |
Vytváření oken a rozmísťování widgetů pomocí zdrojového kódu není příliš pohodlné. Proto byla vyvinuta aplikace Glade, která nabízí uživateli přívětivé klikací prostředí a zároveň umí vygenerovat zdrojový kód. Pomocí myši lze vybírat widgety z palety a kliknutím je umísťovat do konteinerů. V postraním okně je pak možné měnit vlastnosti a obsluhu signálů vybraného widgetu.
Po navržení jednotlivých oken umí aplikace vygenerovat zdrojový kód. Je možné nastavit cestu i názvy souborů do kterých se kód generuje. Rovněž je možné nastavit generování v jazyce C, C++ (s modulem Glademm generuje přímo kód v GTK--), ale i v dalších jazycích (standardně např. Ada). Kromě generování zdrojového kódu si Glade ukládá projekty do vlastních soborů s příponou ".glade". Data jsou uložena ve formátu XML a jsou tedy snadno přístupná i pro jiné aplikace. Toho využívá např. knihovna LibGlade (viz. následující kapitola).
Na platformě Windows je aplikace Glade součástí developer balíčku, ale lze ji získat také samostatně a to v podobě binárních i zdrojových souborů. Osobně doporučuji připravené binární balíčky, přestože se jejich verze lehce opožďuje za vydávanými verzemi zdrojových kódů. Po neúspěchu zkompilovat GTK+ v prostředí CygWin jsem se o kompilaci aplikace Glade ani nepokoušel.
Naproti tomu kompilace pro Linux proběhla bezproblémově. Pro dychtivé kompilátory (to je člověk, který musí stále něco kompilovat) bych si dovolil jen malé upozornění: nejprve je třeba zkompilovat GTK+ (popř i GTK--).
V minulé kapitole jsem se zmínil o vlastnostech alikace Glade. Rovněž jsem naznačil, že soubory s příponou ".glade" jsou ukládány ve formátu XML, a slíbil jsem, že to bude užitečné pro jiné aplikace. Těchto vlastností využívá např. knihovna LibGlade. Jedná se o samostatnou knihovnu (není přímo součástí GTK+ ani aplikace Glade), která umí načíst a naparsovat XML soubor ".glade" a vygenerovat z něho příslučné widgety přímo za běhu aplikace. Tento dynamický přístup má celou řadu výhod:
Zkušený programátor musí mít v tomto okamžiku alespoň trochu zvrásněné čelo. Abstrakce vytváření UI (uživatelského rozhraní) od zdrojového kódu musí mít za následek komplikovanější vázání callback funkcí na signály (události). LibGlade nabízí dva způsoby řešení. Jednak je možné funkce svázat ručně. To znamená, že se každá callback funkce musí navázat samostatně. Druhou možností je automatické připojení callback funkcí. Knihovna LibGlade provede propojení tak, že se pokusí vyhledat seznam všech exportovaných funkcí a podle názvů je připojí k signálům. Aby toto propojení fungovalo, je třeba, aby byla aplikace slinkována s parametrem -E (resp. --export-dynamic).
Při automatickém linkování jsem narazil na potíže, které se mi dlouhou dobu nedařily odstranit. Až po čase jsem zjistil, že problém byl v kódových stránkách. Má česká lokalizace aplikace Glade vygenerovala menu s českými popisky, ale z nich také vygenerovala názvy callback funkcí, které měly háčky a čárky. Po opravě těchto názvů (osobně doporučuji používat pouze malá písmena angl. abecedy a číslice, popř. ještě podrtžítko) se mi podařilo na platformě Linux dosáhnout úspěšného svázání funkcí a signálů. Na Windowsech se ještě potýkám s problémy, nicméně se domnívám, že se jedná pouze o nastavení správných parametrů linkeru. Pokud se mi podaří problém vyřešit, rozhodně nebudete o řešení ochuzeni.
Osobně si myslím, že knihovny GTK+ patří mezi nejlepší, které můžete použít pro vývoj aplikací. Licence LGPL a možnost kompilace pro obě dnes nejpoužívanější platformy je činí velice atraktivní zejména pro vývoj Open Source a Freeware aplikací, ale jak již bylo řečeno, licence LGPL svoluje i plně komerčnímu použití. Při srovnání s mně známými knihovnami (jako je VCL, MFC, Qt nebo wxWidgets) si myslím, že co do bohatosti výbavy si s nimi GTK+ nic nezadá a dokonce některé předčí (např. MFC).
Aby nezůstalo jen u pochval, přece jen se najde pár věcí, které bych těmto knihovnám vytkl. Největším nedostatkem, který mě trápí je podpora dalších "negrafických" prvků (např. podpora síťování), na kterou se autorům nedostalo času. Druhou věcí, která mě zklamala, je nepatrná prodleva mezi změnou velikosti okna a překreslením jeho obsahu. Tento fenomén jsem ve verzi 2.6 zaznamenal pouze na Windowsech, nicméně mám pocit, že u starších verzí byl tento problém i v Linuxu. Nezbývá než doufat, že při tempu, kterým se knihovny GTK vyvíjí bude tato prodleva odstraněna a časem přibudou i další vlastnosti (jako např. zmiňovaná podpora síťování).
Na závěr bych rád uvedl seznam stránek, ze kterých jsem čerpal informace, a které doporučuji navštívit jako zdroj dalšího poznání: