Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Linux-UNIX-Programmierung von Jürgen Wolf
Das umfassende Handbuch – 2., aktualisierte und erweiterte Auflage 2006
Buch: Linux-UNIX-Programmierung

Linux-UNIX-Programmierung
1216 S., mit CD, 49,90 Euro
Rheinwerk Computing
ISBN 3-89842-749-8
gp Kapitel 15 GTK+
  gp 15.1 Was ist GTK+?
    gp 15.1.1 Was sind GDK und Glib?
    gp 15.1.2 Schnittstellen von GTK+ zu anderen Programmiersprachen
    gp 15.1.3 GTK+ und GNOME
    gp 15.1.4 GTK+ Version 1.2 und 2.x
    gp 15.1.5 GTK+-Aufbau des Kapitels
  gp 15.2 GTK+-Anwendungen übersetzen
  gp 15.3 Eine Einführung in die Glib-Bibliothek
    gp 15.3.1 Datentypen
    gp 15.3.2 Routinen
    gp 15.3.3 Assertions-Funktionen
    gp 15.3.4 Speicherverwaltung
    gp 15.3.5 Stringbearbeitung
    gp 15.3.6 Selbstverwaltender Stringpuffer
    gp 15.3.7 Timer
    gp 15.3.8 Dynamische Arrays
    gp 15.3.9 Listen, Hashtabellen und binäre Bäume
    gp 15.3.10 Ausblick Glib
  gp 15.4 Grundlagen der GTK+-Programmierung
    gp 15.4.1 Die Umgebung initialisieren
    gp 15.4.2 Widgets erzeugen und ggf. die Attribute setzen
    gp 15.4.3 Eine Callback-Funktion einrichten, um Events abzufangen
    gp 15.4.4 Eine GTK+-Anwendung beenden
    gp 15.4.5 Die hierarchische Anordnung der Widgets definieren
    gp 15.4.6 Widgets anzeigen
    gp 15.4.7 Signale und Events abfangen und bearbeiten – (Events-)Verarbeitungsschleife
    gp 15.4.8 GTK+ und Umlaute (Zeichenkodierung)
  gp 15.5 Fenster – GtkWindow
    gp 15.5.1 Dialogfenster (Dialogboxen)
    gp 15.5.2 GtkMessageDialog
  gp 15.6 Anzeige-Elemente
    gp 15.6.1 Text – GtkLabel
    gp 15.6.2 Trennlinie – GtkSeparator
    gp 15.6.3 Grafiken – GtkImage
    gp 15.6.4 Statusleiste – GtkStatusbar
    gp 15.6.5 Fortschrittsbalken – GtkProgressBar
  gp 15.7 Behälter
    gp 15.7.1 Boxen – GtkBox
    gp 15.7.2 Aufteilungen, Register und Button-Box
    gp 15.7.3 Tabellen – GtkTable
    gp 15.7.4 Ausrichtung – GtkAlignment
  gp 15.8 Buttons und Toogled-Buttons
    gp 15.8.1 Buttons allgemein
    gp 15.8.2 Radio-Buttons (GtkRadioButton)
    gp 15.8.3 GtkRadioButton, GtkCheckButton und GtkToggleButton
    gp 15.8.4 Signale für Buttons (GtkButton)
  gp 15.9 Dateneingabe
    gp 15.9.1 Textfelder – GtkEntry
    gp 15.9.2 Schieberegler – GtkScale
    gp 15.9.3 Zahlenfelder – GtkSpinButton
    gp 15.9.4 Einstellungen – GtkAdjustment
    gp 15.9.5 GtkEditable
  gp 15.10 Menü und Toolbar
    gp 15.10.1 Menü – GtkItemFactory
    gp 15.10.2 Toolbar – GtkToolbar
    gp 15.10.3 Options-Menü – GtkOptionsMenu
    gp 15.10.4 Combo-Boxen – GtkCombo
  gp 15.11 Mehrzeiliger Text
    gp 15.11.1 Text(editor) – GtkTextView, GtkTextBuffer
    gp 15.11.2 Scrollendes Fenster – GtkScrolledWindow
  gp 15.12 Auswählen (Selection)
    gp 15.12.1 Dateiauswahl – GtkFileSelection
  gp 15.13 Events
  gp 15.14 Weitere Widget- und GTK+-Elemente im Überblick


Rheinwerk Computing

15.5 Fenster – GtkWindow  downtop

Der erste Schritt einer GTK+-Anwendung dürfte wohl meistens das Erzeugen eines Fensters sein. Das folgende Beispiel zeigt Ihnen, wie Sie ein solches (Behälter-)Widget der Klasse GtkWindow mit der Typenkennung GTK_TYPE_WINDOW erstellen und anzeigen können.

/* gkt1.c */
/* Ein leeres Fenster und Pixbuf */
#include <gtk/gtk.h>
static gint
delete_Event(GtkWidget * widget, GdkEvent event, gpointer daten){
  g_print ("Das Fenster wird zerstoert!\n");
  /* Nur mit FALSE wird die Anwendung wirklich beendet */
  return FALSE;
}
static void end (GtkWidget * widget, gpointer daten) {
  g_print ("Und tschuess!\n");
  /* Die Verarbeitungsschleife beenden */
  gtk_main_quit ();
}
int main (int argc, char **argv) {
  GtkWindow *win;
  GdkPixbuf *pic;
  /* 1. Die Umgebung initialisieren */
  gtk_init (&argc, &argv);
  /* 2. Die Widgets erzeugen */
  /* Eine Grafik in einen Pixbuf laden */
  pic = gdk_pixbuf_new_from_file ("icon/at-work.gif", NULL);
  /* 2a. Fenster mit den folgenden Eigenschaften ... anlegen */
  win = g_object_new (GTK_TYPE_WINDOW,
                      "title", "Ein leeres Fenster",
                      "default-width", 300,
                      "default-height", 200,
                      "resizable", TRUE,
                      "window-position", GTK_WIN_POS_CENTER,
                      "border-width", 5, "icon", pic, NULL);
  /* 3. Signalhandler (Callback-Funktion) einrichten  */
  g_signal_connect ( win, "delete-event",
                     G_CALLBACK (delete_Event), NULL);
  g_signal_connect ( win, "destroy",
                     G_CALLBACK (end), NULL);
  /* 4. Hier gibt es noch nichts zum Packen */
  /* 5. (Widgets-)Fenster anzeigen */
  gtk_widget_show_all (GTK_WIDGET (win));
  /* 6. Hauptschleife von gtk-Verarbeitungsschleife */
  gtk_main ();
  g_print ("Die GTK-Hauptschleife wurde beendet\n");
  return 0;
}

Das Programm bei der Ausführung:

$ gcc -Wall -o gtk1 gtk1.c \
  `pkg-config gtk+-2.0 --cflags --libs`
$ ./gtk1

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 15.4    Ein leeres Fenster (GtkWindow)


Im Großen und Ganzen muss eigentlich nicht mehr viel zu diesem Listing gesagt werden. Mit g_object_new() erzeugen Sie ein neues Fenster (GtkWindow) vom Typ GTK_TYPE_WINDOW mit einer variabel langen Liste von Eigenschafts-/Wertpaaren. Diese Liste wird mit NULL abgeschlossen:

"Eigenschaft1", Wert,
"Eigenschaft2", "Wert",
...,
NULL

Jede Eigenschaft ist abhängig von einem entsprechenden Datentyp, der als Wert gesetzt werden kann. Beispielsweise ist die Eigenschaft resizable vom Typ gboolean, und somit kann der Wert nur ein boolescher (TRUE oder FALSE) sein. title hingegen ist vom Typ gchararray, weshalb hier auch eine Zeichenkette für den Fenstertitel verwendet werden muss.

Folgende nützliche Eigenschaften können Sie für ein Fenster der Klasse GtkWindow verwenden (setzen) oder aber auch abfragen (ohne Garantie auf Vollständigkeit):


Tabelle 15.5    Eigenschaften für GtkWindow (GTK_TYPE_WINDOW)

Eigenschaft Datentyp Bedeutung
"allow-grow" gboolean Fenster darf vergrößert werden.
"allow-shrink" gboolean Fenster darf verkleinert werden.
"default-height" gint Höhe des neuen Fensters in Pixel
"default-width" gint Breite des neuen Fensters in Pixel
"destroy-with-parent" gboolean Wenn das Eltern-Widget zerstört wird, wird auch das Fenster zerstört.
"has-toplevel-focus" gboolean Ist das Fenster ganz vorne sichtbar und hat den Fokus, kann nur gelesen werden.
"icon" GdkPixbuf Ein Icon, welches das Fenster erhält. Im Beispiel anhand von GdkPixbuf demonstriert.
"is-active" gboolean Ist das Fenster aktiv, kann nur gelesen werden.
"modal" gboolean Wenn dieses Fenster existiert, können hier mit TRUE alle anderen Fenster in den Hintergrund gestellt werden (sprich, die Reaktion verweigern) – und zwar so lange, bis Sie die Angabe mit FALSE wieder rückgängig machen.
"resizable" gboolean Der Anwender darf die Größe des Fensters verändern.
"title" gchararray Ein String mit dem Titel des Fensters
"window-position" GtkWindowPosition Hier können Aufzählungswerte verwendet werden, womit die Position des Fensters auf dem Bildschirm bestimmt werden kann. Mögliche Angaben hierfür sind: GTK_WIN_POS_NONE Das Platzieren überlassen Sie dem Fenstermanager (Standard). GTK_WIN_POS_CENTER Zentriert in der Bildschirmmitte GTK_WIN_POS_CENTER_ON_PARENT Zentriert in der Mitte des Eltern-Widgets GTK_WIN_POS_MOUSE Wenn möglich, an der Position des Mauszeigers


Hinweis   Damit in dieser Tabelle nicht alles hereingequetscht wirkt, wurden einige Eigenschaften in zwei Zeilen geschrieben – was Sie im Listing als kompletten String verwenden sollten!

Hinweis   Die Reihenfolge, in der Sie die Eigenschafts-/Wertpaare angeben, ist frei wählbar. Es ist somit egal, ob Sie title vor die Eigenschaft icon setzen oder dahinter.


Nach der umfangreichen Einführung in GTK+ zuvor haben Sie sicherlich etwas Komplizierteres als das Listing und die Erläuterungen hier erwartet. Es kommt noch besser. Wenn Sie das Beispiel verstanden haben, ist der Rest des Kapitels und der Rest von GTK+ eigentlich nur noch »Formsache«, da der Vorgang immer ähnlich wie im Beispiel eben abläuft (abgesehen davon, dass Sie in diesem Listing noch keine Widgets packen mussten).


Rheinwerk Computing

15.5.1 Dialogfenster (Dialogboxen)  downtop

Abgeleitet von der Klasse GtkWindow gibt es noch die Fensterklasse GtkDialog. Das ist ein Widget für ein Dialogfenster, das gewöhnlich dazu verwendet wird, dem Anwender etwas Wichtiges mitzuteilen oder ihn abzufragen. Das folgende Listing ist eine Erweiterung des ersten Beispiels. Hinzugefügt wurde gegenüber dem Beispiel zuvor eine Abfragefunktion in Form eines einfachen Dialogfensters, das aufpoppt, wenn der Anwender das (Haupt-)Fenster schließen (zerstören) will. Eine übliche »Sind Sie sicher?«-Abfrage.

/* gkt1b.c */
/* Ein leeres Fenster und eine Dialogbox */
#include <gtk/gtk.h>
static GtkWindow *win;
static gint
delete_Event(GtkWidget * widget, GdkEvent event, gpointer daten){
  GtkWidget *dialog, *label;
  gint result;
  /* Eine neue Dialogbox erzeugen */
  dialog = gtk_dialog_new_with_buttons (
                                "Sind Sie sicher?",
                                win,
                                GTK_DIALOG_DESTROY_WITH_PARENT,
                                "Ja", GTK_RESPONSE_ACCEPT,
                                "Nein", GTK_RESPONSE_REJECT,
                                NULL);
  /* Ein Label dazu */
  label = gtk_label_new (
            "Wollen Sie das Programm wirklich beenden?");
  /* Label in die vorhandene (Standard-)Box (vertikal) */
  /* von der Dialogbox packen                          */
  gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox),
     label);
  /* Dialogbox anzeigen */
  gtk_widget_show_all (dialog);
  /* Wartet auf eine Eingabe in der Dialogbox des Anwenders */
  result = gtk_dialog_run (GTK_DIALOG (dialog));
  switch (result) {
  case GTK_RESPONSE_ACCEPT: /* Ja-Button wurde gedrückt */
    g_print("GTK_RESPONSE_ACCEPT\n");
    /* Dialogbox zerstören */
    gtk_widget_destroy (dialog);
    /* Hauptfenster auch zerstören */
    return FALSE;
    break;
  case GTK_RESPONSE_REJECT:
    g_print("GTK_RESPONSE_REJECT\n");
    /* Dialogbox zerstören */
    gtk_widget_destroy (dialog);
    /* Hauptfenster nicht zerstören */
    return TRUE;
    break;
  case GTK_RESPONSE_DELETE_EVENT:
    g_print("GTK_RESPONSE_DELETE_EVENT\n");
    /* Dialogbox zerstören */
    gtk_widget_destroy (dialog);
    /* Hauptfenster nicht zerstören */
    return TRUE;
    break;
  default:
    g_print("Fehler beim Auswerten der Dialogbox?\n");
    return TRUE;
  }
}
static void end (GtkWidget * widget, gpointer daten) {
  g_print ("Und tschuess!\n");
  /* Die Verarbeitungsschleife beenden */
  gtk_main_quit ();
}
int main (int argc, char **argv) {
  /* 1. Die Umgebung initialisieren */
  gtk_init (&argc, &argv);
  /* 2. Die Widgets erzeugen */
  /* 2a. Fenster mit den folgenden Eigenschaften ... anlegen */
  win = g_object_new (GTK_TYPE_WINDOW,
                      "title", "Ein leeres Fenster",
                      "default-width", 300,
                      "default-height", 200,
                      "resizable", TRUE,
                      "window-position", GTK_WIN_POS_CENTER,
                      "border-width", 5, NULL);
  /* 3. Signalhandler (Callback-Funktion) einrichten */
  g_signal_connect ( win, "delete-event",
                     G_CALLBACK (delete_Event), NULL );
  g_signal_connect ( win, "destroy",
                     G_CALLBACK (end), NULL );
  /* 4. Hier gibt es noch nichts zum Packen */
  /* 5. (Widgets-)Fenster anzeigen */
  gtk_widget_show_all (GTK_WIDGET (win));
  /* 6. Hauptschleife von gtk-Verarbeitungsschleife */
  gtk_main ();
  g_print ("Die GTK-Hauptschleife wurde beendet\n");
  return 0;
}

Das Programm bei der Ausführung:

$ gcc -Wall -o gtk1b gtk1b.c \
  `pkg-config gtk+-2.0 --cflags --libs`
$ ./gtk1b

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 15.5    Ein einfaches Dialogfenster


Zum Erstellen eines neuen Dialogfensters wurde hier die Funktion gtk_dialog_new_with_buttons() verwendet. Zwar wäre auch hier der Weg über g_object_new() möglich gewesen, nur wäre es in diesem Fall (ausnahmsweise) nicht so komfortabel wie mit gtk_dialog_new_with_buttons(). Die Funktion besitzt folgende Syntax:

GtkWidget* gtk_dialog_new_with_buttons( 
                            const gchar *title,
                            GtkWindow *parent,
                            GtkDialogFlags flags,
                            const gchar *first_button_text, ...);

Mit dem ersten Parameter können Sie den Titel des Dialogfensters angeben. Als zweiter Parameter wird das Elternfenster verwendet – quasi das Fenster, welches das Dialogfenster erzeugt hat. Jetzt werden noch einige Flags benötigt (dritter Parameter), wovon Sie folgende zur Auswahl haben:

gp  GTK_DIALOG_MODAL – Wie schon beim gewöhnlichen Fenster können Sie auch hier ein modales Fenster erzeugen (wovon allerdings in der Praxis immer abzuraten ist).
gp  GTK_DIALOG_NO_SEPARATOR – Hiermit können Sie den Trennbalken (Separator) über den Buttons in der vertikalen Box entfernen.
gp  GTK_DIALOG_DESTROY_WITH_PARENT – Mit dem Setzen dieses Flags gehen Sie sicher, wenn sich das Elternfenster noch vor dem Dialogfenster beendet, dass das Dialogfenster auch zerstört wird.

Mit den letzten Parametern können Sie eine variable Buttonliste angeben, die abwechselnd aus der Beschriftung des Buttons und einer Antwortkennung vom Typ gint für den Button besteht. Theoretisch können Sie für diese Antwortkennung eine beliebige positive Ganzzahl verwenden. In der Praxis wird hierbei allerdings gewöhnlich auf eine der vordefinierten Konstanten zurückgegriffen. Wird im Dialogfenster ein Button geklickt, wird das Signal response emittiert. Theoretisch könnten Sie hier auch eine Callback-Funktion einrichten, die wie folgt aussieht:

void dialog_callback( GtkDialog *dlg, gint resp, gpointer data)

Im zweiten Parameter würden Sie dann die Antwortkennung vorfinden, die response emittiert hat. Folgende vordefinierte Konstanten sind für die Antwortkennung (Kennungs-ID) dabei schon vergeben:

gp  GTK_RESPONSE_DELETE_EVENT – Dies wird zurückgegeben, wenn das Dialogfenster über dem Fenstermanager geschlossen wird. Hierbei wird das übliche delete-event-Signal emittiert.
gp  GTK_RESPONSE_NONE – Wurde das Dialogfenster vom Programm entfernt, wird diese Kennung zurückgegeben.

Die weiteren Konstanten sind Kennungen, die im Gegensatz zu den beiden eben erwähnten Konstanten keine besondere Bedeutung haben und nur dem Komfort dienen:

gp  GTK_RESPONSE_ACCEPT – Annehmen
gp  GTK_RESPONSE_REJECT – Ablehnen
gp  GTK_RESPONSE_OK – O. k.
gp  GTK_RESPONSE_CANCEL – Abbrechen
gp  GTK_RESPONSE_CLOSE – Schließen
gp  GTK_RESPONSE_YES – Ja
gp  GTK_RESPONSE_NO – Nein
gp  GTK_RESPONSE_HELP – Hilfe

Da im Beispiel keine Callback-Funktion mit g_signal_connect() eingerichtet wurde, wird die Funktion gtk_dialog_run() verwendet:

gint gtk_dialog_run (GtkDialog *dialog);

Diese Funktion blockiert so lange in einer rekursiven Schleife, bis das Dialogfenster ein empfangenes (response) Signal emittiert oder das Fenster zerstört wird. Wird das Dialogfenster während der Ausführung von gtk_dialog_run() zerstört, wird GTK_RESPONSE_NONE zurückgegeben. Ansonsten wird die Kennungs-ID (wurden eben beschrieben) vom response-Signal zurückgegeben. Beachten Sie bitte, dass in der rekursiven Schleife die Funktion gtk_widget_show() verwendet wird. Würden Sie im Beispiel nicht

gtk_widget_show_all (dialog);

verwenden, würde das Dialogfenster zwar trotzdem angezeigt, allerdings ohne seine Kinder-Widgets (im Beispiel ohne das Text-Label)!

Im Listing wurde auch ein Text-Label erzeugt und in die Box des Dialogfensters gepackt. Genaueres zu diesen beiden Widgets erfahren Sie noch ausführlicher. Natürlich können Sie hierbei jedes beliebige Widget in das Dialogfenster packen, da es sich ja hierbei auch um eine abgeleitete Klasse von GtkWindow handelt.


Rheinwerk Computing

15.5.2 GtkMessageDialog  toptop

GtkMessageDialog ist wiederum eine abgeleitete Klasse von GtkDialog und somit auch abgeleitet von GtkWindow. Der Vorteil von GtkMessageDialog ist, dass sich hiermit noch einfacher und schneller einige Hinweis-Dialoge zusammenbasteln lassen. Wobei man dazu gleich erwähnen muss, dass diese Klasse im Funktionsumfang sehr eingeschränkt ist und man kaum mehr als einfache Ja-/Nein-Buttons erstellen kann. Somit ist diese Klasse nur beschränkt für den Praxisgebrauch geeignet.

 << zurück
  
  Zum Katalog
Zum Katalog: Linux-UNIX-Programmierung
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Linux-Server






 Linux-Server


Zum Katalog: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Katalog: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Katalog: Shell-Programmierung






 Shell-
 Programmierung


Zum Katalog: Linux Handbuch






 Linux Handbuch


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
Info





Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de