GTK+ programozás C nyelven

A leírásról, vagyis az előszó előszava

szerkesztés

Jelen leírás célja elsősorban a hiánypótlás. Sajnos nem találtam olyan átfogó, magyar nyelvű leírást, amely a különféle nyílt forráskódú rendszerek alatt (is) elérhető szabadon használható fejlesztőeszközökről szólna. Viszont véleményem szerint több ilyen alkalmazás születne, ha lenne egy részletesebb, példákkal illusztrált, magyar nyelvű leírás valamely ilyen függvénykönyvtár használatáról.
Mivel én eléggé GTK+ rajongó vagyok, így ezt választottam eme kis leírás témájául, ebben érzem többé-kevésbé otthon magam. Célom nem a teljes részlegesség, ez nem is lehetne, hiszen egyrészt maga a GTK+ is szélsebesen fejlődik, mellyel nem feltétlenül tudok teljes mértékben lépést tartani. Nem mutathatok be mindent, de alapot adhatok, amelyen esetleg érdemes elindulni, kísérletezni. Szeretném több, jól használható példán keresztül bemutatni ezt a rendszert, mert véleményem szerint így könnyebben lehet a rendszer sajátosságait megismerni. Esetleg kedvet kaphat hozzá az érdeklődő, hogy kipróbálja eme remek programozói eszköztárban az alkalmazásfejlesztést. Talán később mások továbbfejlesztik ezt a kis leírást, bővítik, és kijavítják a benne fellelt hibákat és hiányosságokat, és segítenek frissen tartani, követve a változásokat. Így talán a hazai open-source közösség ismét egy remek leírással gyarapodhat.
Mielőtt belefogtam volna ebbe a leírásba, jópár más, angol nyelvű szakirodalmat átolvastam, törekedve a minél jobb megértésre, és felhasználva azokat az általam fejlesztett alkalmazások készítése során. Így könnyen lehet, hogy a leírás struktúrája a végeredményben emlékeztet majd egyik-másik dokumentáció szerkezetére, ez csak olyan szinten tudatos, hogy az ésszerűen felépített gondolatmenettől nem feltétlenül hasznos teljes egészében eltérni. Talán az első pár példaprogram is hasonlítani fog másikakra, de az elején vannak dolgok, amiket egyszerűen nem lehet másképpen csinálni. De ez a dokumentáció nem azok mása, vagy bármilyen átdolgozása, hanem egy teljesen egyedi kezdeményezés. Jelen leíráshoz ajánlanék pár angol nyelvű oldalt, ha valaki szeretne egy adott témában komolyabban elmélyedni, esetleg másmilyen megközelítésre vágyik. Az első a GTK 2.0 tutorial, amely nagyon hasznos olvasnivaló, a legalapvetőbb ismeretektől kezdve komoly szintig jut el, teljesen ésszerű megközelítéssel. Nem tudom, mennyire részletesen fogunk tudni majd kitérni a lista és faszerkezetet megjelenítő widgetek használatára, hiszen az eleve egy külön litánia lehetne, mindenesetre ajánlom az adott témába vágó GTK 2.0 Tree View Tutorial -t is. Illetve referenciaként hasznos elolvasni a GTK API -t is, amely részletesen tárgyalja az egyes funkciókat is. A leírás a C programozási nyelv ismeretét feltételezi, és ezt veszi alapul. Nem fog arra kitérni, hogyan kell használni a C nyelvet, ha erre van szükséged, javaslom a számtalan idevágó programozási szakkönyv egyikét. Nem fog mélyebben kitérni az általad használt C fordítóprogram használatára sem, csak olyan szinten, amely szükséges a példaprogramok lefordításához. Ez a dokumentáció a gcc fordítóprogram használatát fogja figyelembe venni, ha a rendszered ettől eltér, keresd meg a szükséges információkat. Igyekeztem minden ismertetett példát kipróbálni és letesztelni, de ez nem garantálja a teljes hibamentességüket. Mindenesetre dolgozom rajta. A forrásprogramokban szereplő megjegyzések magyar nyelven olvashatóak, de nem használtam ékezeteket, hogy ez ne jelentsen nehézséget a kipróbálás során. A forrás formai tagolásánál az olvashatóságot és az egyes modulok jó elkülönülését tartottam szem előtt, mindemellett igyekeztem vigyázni arra, hogy elkerüljem a felesleges terjengősséget.

A jelölésekről és szóhasználatról

szerkesztés

Kérlek, a későbbi szerkesztés és bővítés során is tartsd magad az itt leírt szabályokhoz.

Jelölésrendszer

szerkesztés

A leírásban szereplő forráskódok, illetve azok részletei külön formázásként jelennek meg, hogy jobban elkülönüljön a körülötte található szövegtől, akkor is, ha az idézett rész mindössze egyetlen sorból áll. Ehhez azonban nem a táblázatkezelő parancsokat használjuk "csak" minden sor elé teszünk egy szóközt. A forráskódokban az egyes blokkok közti behúzás mértéke két szóköz. Ha a folyó szövegben kell egy-egy alprogram vagy függvény nevét megemlíteni, azt mindenképpen félkövér módon jelöljük, a végére kiírva a jelző zárójeleket. Ha egyéb, a forrással kapcsolatos szövegrészről esik szó (pl. fordítási kapcsolók), akkor azokat egyszerűen dőlt betűkkel írjuk. Ha egy teljes forrásállományt idézek a leírásban, akkor a forrás előtt szerepel az állomány neve, vagyis próba esetén milyen néven érdemes elmenteni, mert a későbbiekben ezen néven fogok hivatkozni rá.

Szóhasználat

szerkesztés

A leírásban több helyen is használom majd a szignál kifejezést. Ez nem azonos a Unix világban általánosan megszokott szignálok fogalmával (ahol mégis, ott külön felhívom a figyelmet erre), mert míg az előbbi az operációs rendszer funkciója, itt egy programozástechnikai eszközt jelöl.


Kezdeti lépések

szerkesztés

A leírás nem foglalkozik hosszabban a GTK+ telepítésével. Ennek oka az, hogy a legtöbb Linux/Unix/BSD terjesztés már előre csomagolt formában szállítja azt, sőt egyéb rendszerekre (pl. Windows, MacOSX, OS/2) is létezik előre lefordított változat. Ha mégis a forrásból való lefordításra és telepítésre gondolsz, akkor bővebb segítséget találsz a kibontott forráscsomag INSTALL és README állományaiban.

Egy nagyon egyszerű program ismertetése

szerkesztés

Készítünk egy programot, amely indulása után megjelenít egy 200 képpont széles és magas ablakot, az ablak fejlécén a szokványos kezelőgombokkal. Az én rendszeremen az ablak így nézett ki:

 

És most jöjjön a program forrása, alatta a részletesebb ismertetés. A forráskódnak én a gtk_01.c nevet adtam.

#include <gtk/gtk.h>

int main (int argc,  char *argv[]) {
  GtkWidget * main_window;

  gtk_init (&argc, &argv);
  main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_widget_show (main_window);
  gtk_main ();
  return 0;
}

Látható, hogy milyen rövid és érthető, miért kellene feleslegesen elbonyolítani az egészet. Az elmentett forráskód lefordításához én a következő parancsot adtam ki a lementett forrást tartalmazó könyvtárban: gcc -Wall gtk_01.c `pkg-config --cflags --libs gtk+-2.0` -o gtk_01

Látható, hogy használtam a gcc -Wall kapcsolóját, amely minden fordítási figyelmeztetést kijelez, ez az első időkben nagyon hasznos lehet. A pkg-config pedig visszaadja azokat a fordításhoz szükséges kapcsolókat és beállításokat, melyek szükségesek ahhoz, hogy a rendszereden elérd a GTK+ -t programfejlesztési célból. Figyelj arra, hogy a pkg-config parancs és paraméterei ` ` jelek közé vannak zárva, vagyis nem az oda beírt szöveg helyettesítődik be, hanem a parancs kimenete.

A példaprogram forráskódjának részletesebb ismertetése

szerkesztés

Eljött az idő, hogy részletesebben kivesézzük az első példaprogramunk forráskódját, picit elmerengve az egyes sorok jelentéstartalma felett. A példa első sora így kezdődött:

#include <gtk/gtk.h>

Ez arra utasítja a rendszert, hogy a forráskódba szerkessze be a GTK+ használatához szükséges C fejlécállományokat. Ez minden GTK+ -t használó C programozási nyelvben írt alkalmazáshoz szükséges.

GtkWidget * main_window;

Ez a következő sor, amely érdekes lehet. Itt létrehozunk egy pointert, amely alkalmas arra, hogy a későbbiekben a GTK+ által használt elemeket (widgeteket) tároljunk el vele. Szinte minden GTK+ -beli "objektumot" ilyen mutatóval tudunk elérni és használni, így az ehhez hasonló sorok gyakori visszatérő vendégeink lesznek.

gtk_init (&argc, &argv);

Ez a sor alaphelyzetbe hozza a rendszert, és beállít néhány hasznos tulajdonságot, ilyenek például a szignálkezelők, illetve leellenőrzi és feldolgozza a programnak átadott futtatási paramétereket. Erre a sorra mindig szükség van ebben a formában, enélkül nem tudunk a programból elérni semmilyen GTK+ -s funkciót.

main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

És igen, ki hitte volna, itt készül el az alkalmazás ablaka, amely számunkra is megjelenik. Látható, hogy a gtk_window_new () függvény visszatérési értékét elmentjük a fentebb létrehozott pointerbe, hogy később is tudjunk hivatkozni rá. Érdekes még a függvénynek átadott paraméter, amellyel meghatározzuk, hogy az alkalmazás főablakát, úgynevezett "top-level" ablakot szeretnénk készíteni.

gtk_widget_show (main_window);

Egy widget, legyen az ablak, nyomógomb, címke, vagy bármi más, addig nem látható, amíg mi nem kérjük a megjelenítését. Természetesen, ha ez egy szülő-objektum, amely beágyazva tartalmaz más gyermek-widgeteket, akkor a szülőobjektum megjelenítésével az összes gyermek-widget is láthatóvá válik. Vagyis ha az ablakba elhelyezünk egy nyomógombot, akkor ilyenkor elég csak az ablakot megjeleníteni, ezzel a nyomógomb is láthatóvá válik. Ezzel a szülő-gyermek viszonnyal a későbbiekben még foglalkozunk.

gtk_main ();

Ez szintén egy olyan sor, melyet minden GTK+ -t használó programnak tartalmaznia kell. Erre a sorra érkezve a GTK+ olyan állapotba kerül, amikor már nem jelenít meg több objektumot, hanem a beérkezett események feldolgozásába kezd bele, legyen az billentyűleütés vagy egérmozgatás. Mivel ezt nem kezeltük ebben a kis programban, így nem is foglalkozunk most tovább vele. Az eseményekkel pedig nemsokára úgyis alaposabban megismerkedünk.

Típusátalakítás (castolás)

szerkesztés

Mint bizonyára észrevehető volt, az ablak mutatóját egy GtkWidget típusú pointerben tároltuk el, pedig mennyivel egyszerűbb lett volna, ha az API referencia alapján átírtuk volt a GtkWidget -et GtkWindow -ra. A példa lefordítható így is, de a fordítóprogram két helyen is figyelmeztetést (warning -ot) jelez.
Mi is a GtkWidget valójában? Egy olyan ős-objektumtípus, amely minden GTK+ -beli objektum szülője, tőle van származtatva. Ezért vár ilyen típusú pointert a gtk_widget_show () függvény, hiszen neki egyaránt le kell kezelnie azt, ha valaki egy ablakot, egy nyomógombot, esetleg egy címkét szeretne megjelentetni. A legtöbb alapvető függvény is ilyen típusú mutatót vár, ahol pedig ez nem igaz, ott a mutatót konvertálni kell. Hiszen míg típusátalakítás a program futása során elvégezhető, egy mutató típusát nem lehet változtatni. A típusátalakítás a GTK+ -ban nagyon egyszerű dolog. Minden widget-típusnak létezik egy párja, melyet az átalakításkor használhatunk, és amely nevét csupa nagybetűvel írjuk. Így lesz a GtkWidget -ből GTK_WIDGET, és a GtkWindow -ból GTK_WINDOW, és ehhez hasonlóan a többi widget-típus is. Zárójelben meg kell adni az átalakítandó pointert, és visszatérési értékként megkapjuk az átalakított párját. És, hogy miért is volt fontos ezt elmondani?

Változtassuk meg az ablak címsorát

szerkesztés

Ott tartunk, hogy előttünk a nagyon egyszerű program forrása, amelynek a lefordítása és futtatása során az ablak címsorán a nem túl sokatmondó "gtk_01" felirat áll. Változtassuk meg ezt, mondjuk a "Hello!" feliratra. A GTK+ API megfelelő részét felkeresve, rövid kutakodás után eredményesen megtaláljuk a gtk_window_set_title () függvényt, amely megfelelőnek tűnik számunkra. Paraméterként szükséges a megváltoztatni kívánt ablak pointere, GtkWindow* típusra alakítva, illetve a módosított címsor szövege. Mivel mi nagyon helyesen az ablak pointerét egy GtkWidget* típusú pointerbe tároltuk el, ezért típusátalakítást kell végezni. A fentebb vázolt egyszerű szabály szerint szúrjuk be az alábbi sort a példaprogram forrásába, az ablak létrehozása után (gtk_window_new), de az ablak megjelenítése előtt (gtk_widget_show):

gtk_window_set_title (GTK_WINDOW (main_window), "Hello!");

Fordítsuk újra le a programot az ott írt módon, indítsuk el, és láthatjuk, hogy sikerült.


Külső hivatkozások

szerkesztés