Aus Linux-Magazin 07/2006

GUI-Programmierung mit Glade und Gazpacho

© photocase.com

Moderne Benutzeroberflächen gestalten ist dank der GTK-Bibliothek keine Kunst für besondere Experten. Eine optisch ansprechende Gestaltung erfordert allerdings einiges an Arbeitszeit. Glade und Gazpacho gehen dem Programmierer in der GUI-Küche zur Hand.

Der langwierigste und mitunter auch monotonste Teil bei der Erstellung von Software besteht aus Entwurf und Programmierung der grafischen Benutzeroberfläche (Graphical User Interface, GUI). Ohne Hilfen ist der Entwickler dazu gezwungen, jedes Oberflächenelement über entsprechende Codezeilen von Hand zu erzeugen. Das Ergebnis muss anschließend noch im laufenden Programm kontrolliert und gegebenenfalls korrigiert werden.

Um diese Arbeiten etwas zu beschleunigen, haben sich die so genannten GUI-Builder auf dem Markt etabliert. Sie gestatten es dem Designer, die gewünschte Oberfläche wie in einem Malprogramm bequem zusammenzuklicken. Auf Knopfdruck generieren sie den passenden Quellcode. Da auf diese Weise schnell und einfach komplette grafische Oberflächen entstehen, eigenen sich derartige Werkzeuge ideal zur Herstellung von Prototypen.

Unter Linux konkurrieren zwei große GUI-Bibliotheken um die Gunst der Programmierer. Aus der skandinavischen Softwareschmiede Trolltech stammt Qt, dem bereits standardmäßig ein schicker GUI-Builder beiliegt (siehe den IDE-Artikel in diesem Heft). Benutzer der alternativen GTK-Bibliothek, auf der auch der Gnome-Desktop basiert, müssen sich selbst versorgen. Dank Glade [1] und seit seit kurzem auch dank Gazpacho [2] müssen aber auch sie nicht ganz auf komfortable Helfer verzichten.

Glade

Der älteste GUI-Builder für GTK hört auf den Namen Glade. Seine Entwicklung wurde bereits 1998 in Angriff genommen. Entsprechend ausgereift liegt er vielen größeren Distributionen standardmäßig bei. Nach seinem Start erscheinen die drei Fenster aus Abbildung 1. Das Hauptfenster links oben dient der Projektverwaltung und führt in seiner Liste alle zur neuen Oberfläche gehörigen (Dialog-)Fenster. Die Werkzeugleiste (Palette) links enthält auf mehreren Registern alle GUI-Elemente, die man später in den Fenstern platzieren darf.

Abbildung 1: Die verschiedenen Fenster von Glade nach dem Erstellen eines neuen GTK-Projekts und dem Erzeugen eines Fensters mit dem Namen »window1«.

Abbildung 1: Die verschiedenen Fenster von Glade nach dem Erstellen eines neuen GTK-Projekts und dem Erzeugen eines Fensters mit dem Namen »window1«.

Das letzte vom GUI-Builder geöffnete Fenster listet alle Eigenschaften des gerade aktiven Elements auf. Mit nur wenigen Mausklicks lässt sich dort beispielsweise die Beschriftung einer Schaltfläche ändern. In Glade führt der Weg zu einem eigenen GTK-Programm normalerweise über ein neues Projekt (»Project |New«) und das Anlegen eines Hauptfensters. Für Letzteres genügt bereits ein Klick auf das oberste linke Symbol im Register »GTK+ Basic« der Palette.

Gazpacho

Das noch recht junge Gazpacho-Projekt hat sich auf die Fahnen geschrieben, einen “extrem leicht zu bedienenden GUI-Designer” für GTK zu entwickeln. Dass die Entwickler dabei massiv bei Glade abgekupfert haben, geben sie auf der Homepage nicht nur freiwillig zu, man sieht es dem Endprodukt auch deutlich an (Abbildung 2).

Abbildung 2: Das Hauptfenster von Gazpacho ähnelt in seinem Aufbau den Fenstern von Glade. Hier wurde mit dem entsprechenden Werkzeug ein neues Fenster erstellt, das bereits eine horizontalen Box enthält.

Abbildung 2: Das Hauptfenster von Gazpacho ähnelt in seinem Aufbau den Fenstern von Glade. Hier wurde mit dem entsprechenden Werkzeug ein neues Fenster erstellt, das bereits eine horizontalen Box enthält.

Die Bedienung des alternativen GUI-Designers ist mit der von Glade fast identisch. Der einzige optische Unterschied besteht in der Kapselung aller Bedienelemente in einem einzigen großen Hauptfenster. Gazpacho selbst ist vollständig in Python geschrieben. Daher muss das Werkzeug nicht erst kompiliert werden, benötigt aber neben der Skriptsprache selbst noch die Py-GTK-Bibliothek.

Schwere Ladung

Um die Arbeitsweisen von Glade und Gazpacho zu verstehen, muss man sich die Konzepte von GTK vergegenwärtigen. Unabhängig von einer konkreten GUI-Bibliothek sind bei der Gestaltung von Fensterinhalten zwei grundlegende Vorgehensweisen zu erkennen. Eine besteht darin, jedem Element eine exakte Position und eine feste Größe zuzuweisen. Meist geschieht dies durch die Angabe von Pixeln, ausgehend von einer Fensterecke. Die festen Positionen und starren Abmessungen haben jedoch den Nachteil, dass auf Bildschirmen mit hoher Auflösung die Symbole, Menüs und Schaltflächen unter Umständen nur noch mit der Lupe zu finden sind.

Aus diesem Grund entschieden sich die Entwickler von GTK für das Container-Modell: Sie teilen das Fenster in mehrere Bereiche ein, die dann anschließend die einzelnen GUI-Elemente aufnehmen. Beim späteren Vergrößern oder Verkleinern des Fensters passen sich die Bereiche und somit zwangsweise auch die darin befindlichen Elemente automatisch an.

Bildlich lässt sich dieses Konzept durch Pappschachteln verdeutlichen: Das Hauptfenster besteht aus einem großen Karton, der weitere Schachteln aufnehmen kann. Jede von ihnen darf wiederum weitere Schachteln oder ein GUI-Element enthalten, zum Beispiel eine Schaltfläche. Die Teilbereiche – oder Schachteln – heißen in der GTK-Terminologie auch Container. Üblicherweise fasst man alle GUI-Elemente unter der Bezeichnung Widgets (Window Gadgets) zusammen.

GTK-Container

In Abbildung 1 enthält das Hauptfenster bereits eine so genannte horizontale Box. Sie stellt mehrere (in diesem Fall zwei) Container bereit, die nebeneinander angeordnet sind. Glade und Gazpacho kennen auch das Gegenstück in Form der vertikalen Box sowie die so genannten Panes. Bei dieser Container-Variante darf später der Benutzer des fertigen Programms die Größe der Bereiche über einen kleinen Knubbel verändern. In der Palette von Glade finden sich die Container für alle Geschmacksrichtungen im unteren Bereich des Registers »GTK+ Basic«, bei Gazpacho verstecken sie sich in dem Register »Containers & Ornaments«.

Sobald die Struktur mit Hilfe der Container feststeht, sind in einem zweiten Schritt die so entstandenen Bereiche mit Widgets zu füllen. Hierdurch baut sich zwangsläufig eine Hierarchie aus GUI-Elementen auf. Glade zeigt diese Struktur in einem eigenen Fenster an, das über das Menü »View | Show Widget Tree« erreichbar ist. Unter Gazpacho findet sich die entsprechende Ansicht in dem Register »Widgets«.

Zusätzlich erlaubt diese Darstellungsform das Selektieren aller Elemente, die sich im entstehenden Fenster nicht mehr anklicken lassen, vor allem die Container. Im Beispiel aus Abbildung 3 ist die linke Seite des Hauptfensters mit einer Schaltfläche bestückt, die rechte mit einer Beschriftung (Label), deren Hierarchie die Abbildung 4 zeigt. Jeder dort eingerückte Eintrag enthält alle unter ihm angeordneten Elemente.

Abbildung 3: Hier wurde das Fenster »window1« aus Abbildung 1 auf der rechten Seite um eine Beschriftung (Label) ergänzt.

Abbildung 3: Hier wurde das Fenster »window1« aus Abbildung 1 auf der rechten Seite um eine Beschriftung (Label) ergänzt.

Abbildung 4: Die Hierarchie der in Abbildung 3 sichtbaren GUI-Elemente: Die »hbox1« dient den beiden sichtbaren Elementen als Container.

Abbildung 4: Die Hierarchie der in Abbildung 3 sichtbaren GUI-Elemente: Die »hbox1« dient den beiden sichtbaren Elementen als Container.

Klick mich!

Wie Glade am Fenster »Properties« und Gazpacho auf dem Register »Widgets« erkennen lassen, erhält jedes GUI-Element einen eindeutigen Namen. Er spielt später eine besondere Rolle, wenn die jetzt noch funktionslose GUI Leben eingehaucht bekommt. Der Entwickler sollte die hier zu vergebenden Namen also möglichst sinnvoll wählen.

In diesem Zusammenhang spielt auch der in dem gleichen Fenster zu findende Reiter »Signals« eine wichtige Rolle (Abbildung 5). Sobald der Benutzer im fertigen Programm eine Aktion auslöst, erzeugt die GTK-Bibliothek ein Signal. (In anderen GUI-Frameworks heißen diese Signale normalerweise Ereignisse.) Ein Klick auf eine Schaltfläche löst beispielsweise das Signal »clicked« aus. Anschließend ruft GTK eine Funktion auf, die für die Behandlung eben dieses Signals zuständig ist.

Abbildung 5: Die Zuordnung eines Signals zu einer Callback-Funktion unter Glade.

Abbildung 5: Die Zuordnung eines Signals zu einer Callback-Funktion unter Glade.

In dem oben bereits angesprochenen Register »Signals« legt der GUI-Programmierer fest, welche Funktion bei welchem Signal auszuführen ist. Um eine Zuordnung vorzunehmen, gibt er unter Glade entweder den Namen des Signals ein oder ruft eine Liste mit allen möglichen Signalen zu Hilfe. Der Name der aufzurufenden Funktion landet dann in dem Feld »Handler«.

Handler registrieren

In Gazpacho genügt ein Doppelklick auf den entsprechenden Eintrag »Type the signal’s handler here« (Abbildung 6). Da GTK diese Funktion beim Eintreten des Signals gewissermaßen zurückruft und diese dann auf das entsprechende Signal reagiert, heißt sie auch Callback-Funktion oder Signal-Handler.

Abbildung 6: Die übersichtliche Zuordnung von Signalen zu Callback-Funktionen in Gazpacho.

Abbildung 6: Die übersichtliche Zuordnung von Signalen zu Callback-Funktionen in Gazpacho.

Bei der Zuweisung eines Signals zu einer Funktion sind zwei Dinge zu beachten: Zum einen beziehen sich die hier eingegeben Daten nur auf das gerade ausgewählte und im Fenster »Properties« (beziehungsweise im Register »Widget«) angezeigte Widget, zum anderen darf man unter Glade nicht vergessen die Schaltfläche »Add« zu betätigen.

Darin erschöpft sich die Hilfe von Glade und Gazpacho bei der Erstellung von Oberflächen schon fast. Per »Project/Build« erstellt Glade immerhin noch den Quellcode, der im Verzeichnis »src« des Projektverzeichnisses landet. Wie das entsprechende Dialogfenster zeigt, kennt der GUI-Builder verschiedene Zielsprachen, darunter neben dem klassischen C auch C++ und Ada95. Gazpacho dagegen kann nicht direkt Code erzeugen. Um die mit ihm erstellten Oberflächen in eigenen Programmen zu nutzen, ist die Hilfe der Libglade-Bibliothek erforderlich. Mehr dazu weiter unten.

Callback-Funktionen

Unter Glade entsteht das Grundgerüst einer GTK-Anwendung, wobei die Anzahl der erzeugten Dateien stets gleich ist. Die wichtigste von ihnen ist »callback.c«. Sie enthält alle Callback-Funktionen, die der nächste Schritt mit Leben füllt. Mit der Oberfläche aus Abbildung 3 als Ausgangspunkt ist hier nur eine leere Funktion »on_button1_clicked()« zu finden.

Das GTK-Toolkit übergibt als Argumente die betroffene Schaltfläche und einen Zeiger auf eine beliebige, vom Programmierer weitergereichte Datenstruktur. Um beispielsweise die Textfläche auf der rechten Seite zu ändern, heißt die Funktion:

void on_button1_clicked(GtkButton *button, gpointer user_data)
{
gtk_label_set_text(GTK_LABEL(lookup_widget(GTK_WIDGET(button), "label1")), "Schalter wurde gedrueckt.");
}

Dabei kommen die zuvor vergebenen Widget-Namen zum Zug. Die Funktion »lookup_widget()« verwendet sie für die eindeutige Identifikation der einzelnen Elemente.

Im Verzeichnis »/src« verbleiben noch drei weitere Dateien, doch nur »main.c« empfiehlt sich für Veränderungen. Wie der Name vermuten lässt, enthält sie den Einstiegspunkt in das Programm. Die Datei »interface.c« kapselt alle Funktionen, die später das Hauptfenster und die restlichen Widgets erzeugen. Die letzte Datei im Bunde trägt den Namen »support.c« und enthält ein paar zusätzliche Hilfsfunktionen, die unter anderem die Anbindung der Signale an die Callback-Funktionen erleichtern.

Eine Ebene höher im Projektverzeichnis hat Glade für den Übersetzungsvorgang bereits entsprechende Skripte abgelegt. Ein Aufruf von »./autogen.sh« erzeugt das Makefile, das anschließend per »make« den eigentlichen Übersetzungsvorgang steuert. Das setzt die Tools Autoconf und Automake voraus.

Abbildung 7: Das fertige Programm vereint den Entwurf aus Abbildung 3 und die im Artikel entwickelte Logik: Beim Klicken der Schaltfläche erscheint der entsprechende Text im Textfeld (Label).

Abbildung 7: Das fertige Programm vereint den Entwurf aus Abbildung 3 und die im Artikel entwickelte Logik: Beim Klicken der Schaltfläche erscheint der entsprechende Text im Textfeld (Label).

Libglade

Wer mit Glade ein etwas größeres Programm entwirft, gerät früher oder später in die Bredouille: Ändert er im GUI-Designer die grafische Oberfläche und erzeugt anschließend den Quellcode neu, überschreibt Glade vorhandene Dateien wie zum Beispiel »interface.c|.h« und »support.c|.h«.

Abhilfe verschafft die Bibliothek Libglade. Ihre Arbeitsweise basiert auf dem glücklichen Umstand, dass die von Glade und Gazpacho gespeicherten Projekte reine XML-Textdateien sind, die im Klartext die Beschreibung der zusammengestellten Oberfläche enthalten. Libglade ist nun in der Lage, eine derartige Projektdatei zur Laufzeit einzulesen und die darin beschriebenen GUI-Elemente (halb-)automatisch zu erzeugen. Die Bibliothek entkoppelt somit die Benutzeroberfläche vom Programm.

Im Quellcode selbst lädt die Funktion per »glade_xml_new()« zunächst die Projektdatei, holt dann das entsprechende Element via »glade_xml_get_widget()« und verbindet schließlich die Callback-Funktionen über »g_signal_connect()« mit dem entsprechenden Signal. Listing 1 liefert hierfür ein Beispiel.

Listing 1:
»libglade-bsp.c«

01 #include <gtk/gtk.h>
02 #include <glade/glade.h>
03 
04 void on_button1_clicked(GtkButton *button, gpointer user_data)
05 {
06   gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(user_data, "label1")), "Schalter wurde gedrueckt.");
07 }
08
09 int main(int argc, char **argv)
10 {
11    GladeXML  *window;
12    GtkWidget *button;
13
14    gtk_init(&argc, &argv);
15    /* Beschreibungsdatei laden */
16    window = glade_xml_new ("./project1.glade", NULL, NULL);
17    /* Schaltfläche holen... */
18    button = glade_xml_get_widget (window, "button1");
19    /* ...und die Callbackfunktion registrieren. Beim Eintreten des Signals übergibt GTK+ "window" an die Callback-Funktion. */
20    g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_button1_clicked), window);
21
22    gtk_main (); /* Hauptschleife */
23
24    return 0;
25 }

Die Quellcode-Generierung durch Glade ist also nicht mehr nötig. Die Übersetzung übernimmt der Befehl »gcc -o Programm Programm.c `pkg-config –cflags –libs libglade-2.0`«. Der Aufruf von »pkg-config« sorgt für die korrekte Einbindung der Libglade-Bibliothek.

Obwohl alle bisherigen Beispiele in C verfasst sind, existieren auch Anbindungen an viele weitere Sprachen, etwa Python (Pyglade), C++ (Libglademm), C#, Perl oder Java. Glade bietet außerdem die Möglichkeit, die Verbindung zwischen Signal und Handler automatisch herzustellen. Mehr dazu verrät der Kasten “Automatisch verbinden”. Allerdings unterstützt das Glade-Format nicht das in GTK 2.4 eingeführte Interface GTK-UI-Manager, das ein eigenes, inkompatibles XML-Format verwendet.

Automatisch
verbinden

Libglade lässt sich auch auf eine andere Art nutzen, die aber nicht völlig problemlos ist. In Listing 1 erfolgt die Verknüpfung zwischen einem Signal (»clicked«) und der entsprechenden Behandlungsroutine noch manuell. Über »glade_xml_signal_autoconnect()« verbindet Libglade alle zuvor im GUI-Builder definierten Signal-Handler automatisch mit den passenden Funktionen. Letztere müssen selbstverständlich im Quellcode existieren.

Der manuelle Aufruf von »g_signal_connect()« ist somit nicht mehr nötig. Hierdurch nimmt der Entwickler sich aber auch die Chance, selbst noch wichtige Variablen an die Callback-Funktion weiterzureichen. Damit diese Funktionen dennoch auf bestimmte Datenwerte zugreifen können, ist die Versuchung groß, globale Variablen für den Datenaustausch zu verwenden. Insbesondere bei größeren Projekten führt das aber recht schnell zu schlecht les- und wartbarem Quellcode.

Die beschriebene automatische Verbindung zwischen GTK-Signalen und Callback-Funktionen erreicht Libglade, indem es mit Hilfe von Gmodule die Funktionsnamen in der globalen Symboltabelle ermittelt.

Gut für GUIs

Glade wie Gazpacho unterstützen das Konzept des Rapid Application Development (RAD) nur ansatzweise. Richtige Zwei-Wege-Werkzeuge, wie mittlerweile unter Windows üblich, sind beide Kandidaten nicht. Immerhin erleichtern sie im Zusammenspiel mit Libglade den Entwurf von GTK-GUIs und ersparen damit einige Handarbeit. (ofr)

Infos

[1] Glade: [http://glade.gnome.org]

[2] Gazpacho: [http://gazpacho.sicem.biz]

[3] Libglade: [http://www.jamesh.id.au/software/libglade]

Copyright © 2002 Linux New Media AG

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben