Primer programa v C z GLADE

Pri tej nalogi za oblikovanje uporabniškega vmesnika uporabite program glade-3. Rezultat je datoteka s končnico .glade (na primer naloga12.glade), v kateri je v obliki xml zapisan ustvarjen uporabniški vmesnik. Napisati moramo torej še program, v katerem bomo to datoteko uporabili za prikaz uporabniškega vmesnika. Tak program lahko napišemo v različnih programskih jezikih (npr. C, C++, Python, Ruby, PHP ...); spodnji primer bomo prikazali v jeziku C, ki je tudi jezik GTK+.

Program, ki ga moramo sami napisati, zajema funkcijo main in vse odzivne funkcije na dogodke (slednje oz. njihova imena smo sicer določili že pri izgradnji uporabniškega vmesnika, vendar jih moramo tu še definirati). Na začetku programa moramo vključiti zaglavno datoteko knjižnice GTK+:

#include <gtk/gtk.h>

V funkciji main moramo najprej poskrbeti za inicializacijo GTK+. Pokličemo funkcijo

gtk_init(&argc, &argv);

kjer sta argc in argv argumenta funkcije main.

Nato za izgradnjo uporabniškega vmesnika uporabimo GtkBuilder, ki pregleda našo .glade datoteko (naloga12.glade) in ustvari vse objekte (widgets), ki so v njej definirani, določi njihove lastnosti ter vzpostavi relacije (hierarhijo) med njimi:

builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "naloga12.glade", NULL);

Spremenljivka builder, ki predstavlja GtkBuilder, je kazalec na ta objekt, in jo moramo pred uporabo seveda deklarirati:

GtkBuilder *builder;

Ko smo ustvarili celoten vmesnik, moramo pridobiti še reference na tiste objekte, ki jih želimo v programu še uporabljati oz. z njimi manipulirati. Primer:

// pridobimo referenco na glavno okno, ki smo ga v Glade poimenovali window1
window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));

// pridobimo referenco na oznako, ki smo jo v Glade poimenovali labelA
label = GTK_WIDGET(gtk_builder_get_object(builder, "labelA"));

// pridobimo referenco na dialog za izbiro datoteke, ki smo ga v Glade poimenovalii fileChooserDialog1
chooser = GTK_WIDGET(gtk_builder_get_object(builder, "fileChooserDialog1"));

Pri tem moramo spremenljivki window in label deklarirati kot kazalca na GtkWidget:

GtkWidget *window, *label;

Nato moramo povezati odzivne funkcije s signali:

gtk_builder_connect_signals(builder, NULL);

Drugi parameter v funkciji je kazalec na strukturo, ki se pošlje vsem signalom kot uporabniški podatki. V našem primeru tega ne bomo uporabljali, zato je to NULL.

S tem smo opravili vse potrebno za pravilno delovanje uporabniškega vmesnika. Objekta builder tako ne potrebujemo več, zato ga uničimo:

g_object_unref(G_OBJECT(builder));

Za konec moramo le še prikazati glavno okno programa (naša spremenljivka window)

gtk_widget_show(window);

ter zagnati glavno dogodkovno zanko (neskončna zanka, ki čaka na dogodke):

gtk_main();

S tem lahko zaključimo našo funkcijo main.

V glavni dogodkovni zanki GTK+ preverja stanje objektov in po potrebi sproža signale. Na te signale se odzivajo funkcije, ki so z njimi povezane. Vse funkcije, ki se odzivajo na dogodke (signale), smo določili že v programu Glade. V našem programu jih moramo seveda še definirati. Vsaka funkcija prejme dva parametra, to sta kazalec na objekt, ki je prejel signal (GtkObject *object), in morebitni podatki uporabnika (gpointer user_data). Slednjih v našem primeru ne uporabljamo (glej klic funkcije za povezavo signalov).

Primer dveh odzivnih funkcij (prva zapiše neko besedilo v oznako, druga pa prikaže dialog za izbiro datoteke):

void on_option1_menu_item_activate(GtkObject *object, gpointer user_data) {
    // koda za odziv na signal, v oznaki label se izpiše besedilo
    // ime funkcije on_option1_menu_item_activate smo določili že v programu Glade
    gtk_label_set_text(GTK_LABEL(label), "Besedilo, ki se prikaze v oznaki.");
}
void on_file_open_menu_item_activate(GtkObject *object, gpointer user_data) {
    // koda za odziv na signal, prikaže se dialog za izbiro datoteke in prebere ime izbrane datoteke
    // ime funkcije on_file_open_menu_item_activate smo določili že v programu Glade
    gchar *imeDatoteke;
    // pridobimo ime izbrane datoteke
    imeDatoteke = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));
    // skrijemo dialog
    gtk_widget_hide(chooser);
    // pridobljeno ime datoteke zapišemo v oznako
    gtk_label_set_text(GTK_LABEL(label), imeDatoteke);
}

Pa še nekaj uporabnih funkcij (nekatere smo uporabili že v zgornjem primeru):

  • Program lahko zaključimo tako, da pokličemo funkcijo, ki prekine glavno dogodkovno zanko (in s tem zaključi program): gtk_main_quit();
  • Besedilo v oznaki label lahko nastavimo na "bla bla" z naslednjim klicem funkcije: gtk_label_set_text(GTK_LABEL(label), "bla bla");
  • Ime datoteke, ki jo izberemo v oknu za izbiro datoteke chooser, dobimo s klicem naslednje funkcije:

    gchar *fName; // ime datoteke kot niz znakov fName = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));

  • Okno chooser lahko skrijemo s klicem: gtk_widget_hide(chooser);

Ko program v jeziku C napišemo, ga prevedemo z ukazom:

gcc -Wall -g -o naloga12 naloga12.c -export-dynamic $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)

pri čemer je naloga12.c ime našega programa z izvorno kodo, naloga12 pa je ime prevedenega programa (oboje po potrebi zamenjajte). Rezultat prevajanja (če ni bilo napak) je datoteka naloga12 (ali drugo ime, ki ste ga podali). Program poženemo z ukazom:

./naloga12

V pomoč pri izdelavi naloge vam je tudi spletni tutorial v treh delih Micah Carrick: GTK+ and Glade3 GUI Programming Tutorial.

Opise objektov in njihove funkcije najdete tudi v priročniku GTK+ Reference Manual.