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.7 Behälter  downtop

In der Einführung sind Sie bereits auf ein Behälter-Widget mit GtkBox gestoßen. Ohne den Behälter-Widget – gerne auch als Packing-Widgets bezeichnet – wäre es wohl aussichtslos, eine Anwendung zu erstellen. Denn gerade mithilfe der Behälter-Widgets entsteht das Layout des Fensters und somit der Anwendung.


Rheinwerk Computing

15.7.1 Boxen – GtkBox  downtop

Die wichtigsten und grundlegenden Behälter sind dabei die vertikalen und horizontalen Boxen. Diese werden immer dann verwendet, wenn mehrere Widgets nebeneinander und übereinander angeordnet werden sollen. Die Behälter-Widgets der Klasse GtkHBox und GtkVBox sind abgeleitet von der Oberklasse GtkBox. In der Abbildung sehen Sie den Klassenbaum von GtkBox.


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

Abbildung 15.8    Klassenbaum von GtkBox


In den meisten Fällen wird als Behälter GtkBox verwendet. Für den Fall, dass Sie sehr viele Zeilen und Spalten benötigen, können Sie entweder mehrere vertikale und horizontale Boxen in der richtigen Anordnung verwenden oder das Tabellen-Widget GtkTable. Ein Tabellen-Widget ist ein Behälter, mit dem Sie die weiteren Widgets in Zeilen und Spalten packen können.

Der Sinn und Zweck der Boxen – sei dies nun eine vertikale Box (Klasse GtkVBox mit der Typenkennung GTK_TYPE_VBOX) oder eine horizontale Box (Klasse GtkHBox mit der Typenkennung GTK_TYPE_HBOX) – ist immer derselbe. Boxen werden dazu verwendet, damit andere Widgets darin hineingepackt werden.

Folgende zwei Eigenschaften können einer Klasse GtkBox vom Typ GTK_TYPE_VBOX oder GTK_TYPE_HBOX vergeben bzw. können abgefragt werden:


Tabelle 15.7    Eigenschaften für eine GtkVBox und eine GtkHbox

Eigenschaft Datentyp Bedeutung
"spacing" gint Abstand zwischen den einzelnen gepackten Widgets in Pixel
"homogeneous" gboolean Bei TRUE bleiben alle gepackten Widgets gleich groß.

In den Listings bisher wurden die einzelnen Widgets mit der Funktion gtk_box_pack_start_defaults() mit den Standardeinstellungen einer Box hinzugefügt. Mit den folgenden Funktionen können Sie ganz individuell für jedes einzelne Widget eine Angabe machen, wie dieses zur Box hinzugefügt (gepackt) werden soll.

void gtk_box_pack_start_defaults( GtkBox *box,
                                  GtkWidget *widget );
void gtk_pack_box_start( GtkBox *box, 
                         GtkWidget *widget, 
                         gboolean expand, 
                         gboolean fill,
                         guint padding );
void gtk_pack_box_end (  GtkBox *box,
                         GtkWidget *widget,
                         gboolean expand,
                         gboolean fill,
                         guint padding );

Der Unterschied der beiden Funktionen (.._start und .._end) ist, dass ein Widget mit der _end-Version vom Ende der vertikalen oder der rechten Seiten der horizontalen Box aus gepackt wird. Bei der _start-Version ist das Gegenteil der Fall.

Die ersten beiden Parameter der Funktionen gtk_pack_box_start() und gtk_pack_box_end() sind gleichbedeutend wie bei der Funktion gtk_box_pack_default(). box ist die Box, worin Sie das Widget widget hineinpacken wollen. Mit den nächsten drei Parametern können Sie die Darstellung des Widgets in der Box beeinflussen.

gp  expand – Wird hier TRUE angegeben, darf sich das Widget ausdehnen. Befinden sich mehrere Widgets in dieser Box, wird der verfügbare Bereich unter diesen Widgets aufgeteilt, bei denen dieser Parameter ebenfalls TRUE ist.
gp  fill – Wird für expand TRUE verwendet und für fill (ausfüllen) ebenfalls, wird der übrige Freiraum zwischen den Widgets selbst völlig ausgefüllt, anstatt sich nur zu zentrieren.
gp  padding – Hier können Sie einen Wert in Pixeln angeben, womit ein Leerraum rund um das Widget »gepolstert« werden darf.

In den gleich folgenden beiden Beispielen wurde auf ein Widget mit einer Box als Behälter erst einmal verzichtet, da es ohnehin in fast jedem der noch folgenden Listings verwendet wird oder bereits verwendet wurde. Daher soll hier erst ein umfassender Blick auf andere Behälter-Widgets gemacht werden.


Rheinwerk Computing

15.7.2 Aufteilungen, Register und Button-Box  downtop

In den jetzt folgenden Listings werden die (Behälter-)Widgets GtkHPaned und GtkVPaned (mit den Typenkennungen GTK_TYPE_HPANED bzw. GTK_TYPE_VPANED) gezeigt, womit Sie mehrere verstellbare (sowohl horizontale als auch vertikale) Aufteilungen erzeugen können, wie Sie dies z. B. von FTP- oder Mailclient-Anwendungen her kennen. Des Weiteren wird ein Behälter mit mehreren Registern erzeugt (GtkNotebook von der Typenkennung GTK_TYPE_NOTEBOOK), wie Sie dies z. B. von Notizbüchern (oder Ringordnern) her kennen. Daneben werden Sie auch noch Behälter kennen lernen, die nur Buttons aufnehmen können.

/* gkt3.c */
/* Behälter:       */
/*    horizontale und vertikale Aufteilung (GtkPaned) */
/*    Register (GtkNootebook)                         */
/*    horizontale und vertikale Boxen                 */
#include <gtk/gtk.h>
#define NBOOK 6
#define BUF 35
#define BUTTONS 4
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");
  gtk_main_quit();
}
int main(int argc, char **argv) {
  GtkWindow  *win;
  GdkPixbuf  *pic;
  GtkVPaned  *vpan;
  GtkHPaned  *hpan;
  GtkNotebook *nbook;
  GtkLabel    *nbook_content[NBOOK],
  *nbook_titel[NBOOK];
  GtkVButtonBox *vbutbox;
  GtkButton     *vbuttons[BUTTONS];
  GtkHButtonBox *hbutbox;
  GtkButton     *hbuttons[BUTTONS];
  guint i;
  gchar buf[BUF];
  gtk_init( &argc, &argv );
  /* Eine Grafik in einen Pixbuf laden */
  pic = gdk_pixbuf_new_from_file("icon/at-work.gif", NULL );
  /* Fenster mit folgenden Eigenschaften anlegen */
  win = g_object_new( GTK_TYPE_WINDOW,
                      "title", "Behaelter-Widgets",
                      "default-width",  300,
                      "default-height", 200,
                      "resizable", TRUE,
                      "window-position", GTK_WIN_POS_CENTER,
                      "border-width", 10,
                      "icon", pic,
                      NULL );
  /* vertikale Aufteilung erzeugen */
  vpan = g_object_new( GTK_TYPE_HPANED, NULL );
  /* horizontale Aufteilung erzeugen */
  hpan = g_object_new( GTK_TYPE_VPANED, NULL );
  /* vpan oben-links von hpan mit den */
  /* Standardparametern hinzufügen    */
  gtk_paned_add1( GTK_PANED(hpan), GTK_WIDGET(vpan) );
  /* ein neues Notizbuch erzeugen */
  nbook = g_object_new( GTK_TYPE_NOTEBOOK,
                        "enable-popup", TRUE,
                        NULL );
  /* nbook rechts-unten von vpan mit den */
  /* Standardparametern hinzufügen */
  gtk_paned_add2(GTK_PANED(vpan), GTK_WIDGET(nbook));
  /* Titel der Reiter mit entsprechendem Inhalt erzeugen  */
  /* und im Notizbuch hinzufügen */
  for(i=0; i < NBOOK; i++) {
    g_snprintf(buf,BUF,"Inhalt von GtkNotebook Seite %d",i+1);
    nbook_content[i] = g_object_new( GTK_TYPE_LABEL,
                                     "label", buf,
                                     NULL);
    g_snprintf(buf,BUF,"Seite %d",i+1);
    nbook_titel[i]   = g_object_new( GTK_TYPE_LABEL,
                                     "label", buf,
                                     NULL );
    gtk_notebook_append_page_menu(nbook,
                                  GTK_WIDGET(nbook_content[i]),
                                  GTK_WIDGET(nbook_titel[i]),
                                  NULL);
  }
  /* vertikale Button-Box erzeugen */
  vbutbox = g_object_new( GTK_TYPE_VBUTTON_BOX, NULL);
  /* horizontale Button-Box erzeugen */
  hbutbox = g_object_new( GTK_TYPE_HBUTTON_BOX, NULL);
  /* Buttons erzeugen und in die Button-Box packen */
  for(i=0; i < BUTTONS; i++ ) {
    g_snprintf(buf,BUF,"(v)Button %d",i+1);
    vbuttons[i] = g_object_new( GTK_TYPE_BUTTON,
                                "label", buf,
                                NULL);
    gtk_box_pack_start_defaults( GTK_BOX(vbutbox),
                                 GTK_WIDGET(vbuttons[i]));
    g_snprintf(buf,BUF,"(h)Button %d",i+1);
    hbuttons[i] = g_object_new( GTK_TYPE_BUTTON,
                                "label", buf,
                                NULL );
    gtk_box_pack_start_defaults( GTK_BOX(hbutbox),
                                 GTK_WIDGET(hbuttons[i]));
  }
  /* vbutbox oben-links von vpan mit den */
  /* Standardparametern hinzufügen       */
  gtk_paned_add1(GTK_PANED(vpan), GTK_WIDGET(vbutbox));
  /* hbutbox rechts-unten von hpan mit den */
  /* Standardparametern hinzufügen         */
  gtk_paned_add2(GTK_PANED(hpan), GTK_WIDGET(hbutbox));
  /* Signalhandler einrichten */
  g_signal_connect( win, "delete-event",
                    G_CALLBACK(delete_Event), NULL );
  g_signal_connect( win, "destroy",
                    G_CALLBACK(end), NULL );
  gtk_container_add(GTK_CONTAINER( win ), GTK_WIDGET( hpan ) );
  /* Fenster anzeigen */
  gtk_widget_show_all( GTK_WIDGET(win) );
  /* Hauptschleife von gtk */
  gtk_main();
  g_print("Die GTK-Hauptschleife wurde beendet\n");
  return 0;
}

Das Programm bei der Ausführung:

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

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

Abbildung 15.9    Einige Behälter-Widgets – Aufteilungen, Register, Button-Box


Aufteilungen – GtkPaned

Im Beispiel haben Sie jeweils eine vertikale und eine horizontale Schiebeleiste (Aufteilung) verwendet. Bei einer Aufteilung der Klassen GtkVPaned (Typenkennung: GTK_TYPE_VPANED) bzw. GtkHPaned (Typenkennung: GTK_TYPE_HPANED) kann an beiden Seiten je ein Widget gepackt werden. Bei GtkVPaned ist dies je ein Widget oberhalb und unterhalb der Schiebeleiste und bei GtkHPaned links und rechts von der Leiste. Um das Packen entsprechend vorzunehmen, werden hierfür die Funktionen gtk_paned_add1() und gtk_paned_add2() verwendet.

void gtk_paned_add1 ( GtkPaned *paned,
                      GtkWidget *child );
void gtk_paned_add2 ( GtkPaned *paned,
                      GtkWidget *child );

Als erstes Argument verwenden je beide Funktionen die Schiebeleiste (GtkPaned) und als zweites Argument ein Widget, das darin hineingepackt werden soll. Mit gtk_paned_add1() wird ein Widget links über und mit gtk_paned_add2() rechts unter die Schiebeleiste gepackt.

Sofern Sie ähnlich wie beim Packen von Boxen mit gtk_box_pack_start() auch die Größenveränderung des Widgets beeinflussen wollen, können Sie hierfür die Funktionen gtk_paned_pack1() und gtk_paned_pack2() verwenden.

/* links oben */
void gtk_paned_pack1 ( GtkPaned *paned,
                       GtkWidget *child,
                       gboolean resize,
                       gboolean shrink );
/* rechts unten */
void gtk_paned_pack2 ( GtkPaned *paned,
                       GtkWidget *child,
                       gboolean resize,
                       gboolean shrink );

Beide Funktionen sind bis zu den ersten beiden Parametern gleichwertig wie gtk_paned_add1() und gtk_panded_add2(). Zusätzlich können Sie hier noch mit dem dritten Parameter angeben, ob sich das Kind-Widget ausdehnen soll (darf), wenn die Größe des Widgets verändert wird. Mit dem vierten Argument bestimmen Sie hingegen, ob das Widget jenseits der Minimalgröße schrumpfen darf, wenn das Hauptfenster verkleinert wird.

Folgende zwei Eigenschaften stehen Ihnen außerdem für das Widget GtkPaned zur Verfügungen:


Tabelle 15.8    Eigenschaften für GtkPaned

Eigenschaft Datentyp Bedeutung
"position" gint Hier kann eine Position, gerechnet von der linken bzw. oberen Seite, für die Schiebeleiste eingetragen werden (abhängig von position-set).
"position-set" gboolean Damit der Wert in position auch beachtet wird, muss hier TRUE eingetragen werden.

Notizbuch – GtkNotebook

Das Notizbuch (GtkNotebook; Typenkennung: GTK_TYPE_NOTEBOOK) besteht aus mehreren Reitern, die beim Anklicken auch jeweils eine neue Seite beinhalten. Um zum Notizbuch weitere Seiten und Reiter hinzuzufügen, stehen Ihnen mindestens folgende Funktionen zur Verfügung (wovon Sie ja im Beispiel die Funktion gtk_notebook_append_page_menu() verwenden):

void gtk_notebook_append_page_menu ( GtkNotebook *notebook,
                                     GtkWidget *child,
                                     GtkWidget *tab_label,
                                     GtkWidget *menu_label );
void gtk_notebook_prepend_page_menu ( GtkNotebook *notebook,
                                      GtkWidget *child,
                                      GtkWidget *tab_label,
                                      GtkWidget *menu_label );
void gtk_notebook_insert_page_menu ( GtkNotebook *notebook,
                                     GtkWidget *child,
                                     GtkWidget *tab_label,
                                     GtkWidget *menu_label,
                                     gint position );

Die einzelnen Argumente haben bei allen drei Funktionen dieselbe Bedeutung. Das erste Argument ist das Widget GtkNotebook selbst, wo ein neuer Eintrag hinzugefügt werden soll. Mit dem zweiten Argument geben Sie den Inhalt der Seite an, den Sie in das Notizbuch hineinpacken wollen. Hierbei können Sie natürlich (fast) jedes beliebige andere Widget, wie im Beispiel mit GtkLabel gesehen, hineinpacken. Mit dem dritten Argument gibt man normalerweise die Beschriftung (Reitername) für die neue Seite an, wobei rein theoretisch auch hier ein beliebiges Widget verwendet werden könnte (ob das jetzt Sinn macht, sei dahingestellt). Im Beispiel wurde auch hierzu GtkLabel verwendet. Das vierte Argument könnte ein weiteres Beschriftungs-Widget aufnehmen, das für das Schnellzugriffsmenü der einzelnen Reiter dient. Dieses Menü erreichen Sie über einen Rechtsklick auf irgendeinen der Reiter. Wollen Sie, dass sich hier derselbe Eintrag, wie der Name des Reiters selbst (drittes Argument), befindet, können Sie hier auch NULL angeben.

Der Unterschied der Funktionen gtk_notebook_append_page_menu() und gtk_notebook_prepend_page_menu() liegt darin, dass mit _append_ der neue Eintrag hinten und mit _prepend_ der neue Eintrag vorne eingefügt wird. Die Funktion gtk_notebook_insert_page_menu() hingegen hat noch ein fünftes Argument, womit der Menüeintrag an einer beliebigen Stelle bestimmt (angefangen von links (vorne) = 0) werden kann.

Entfernen können Sie einen Notizbucheintrag wieder mit gtk_notebook_remove_page():

void gtk_notebook_remove_page ( GtkNotebook *notebook,
                                gint page_num );

Hierzu müssen Sie neben der Angabe des Notizbuches (erstes Argument) auch die Position (angefangen von vorne mit 0) des Eintrags angeben, der entfernt werden soll.

Die Eigenschaften, die Sie für ein neues Notizbuch von der Klasse GtkNootebook (Typenkennung: GTK_TYPE_NOTEBOOK) vergeben können, finden Sie wieder in der folgenden Tabelle aufgelistet.


Tabelle 15.9    Eigenschaften für GtkNootebook (GTK_TYPE_NOTEBOOK)

Eigenschaft Datentyp Bedeutung
"enable-popup" gboolean Hier kann bestimmt werden, ob das Kontextmenü (Schnellzugriff) für das direkte Anspringen bei Rechtsklick auf einen Reiter erscheint (standardmäßig TRUE).
"homogeneous" gboolean Bei TRUE haben alle Reiter die gleiche Breite.
"page" gint Indexnummer der aktuellen Seite
"scrollable" gboolean Sind mehr Reiter vorhanden als auf dem Fenster anzeigbar, kann hier mit TRUE dafür gesorgt werden, dass ein scrollbarer Pfeil angezeigt wird, womit Sie quer durch die Reiter blättern können.
"show-border" gboolean Soll der Rand angezeigt werden oder nicht?
"show-tabs" gboolean Sollen die Reiter angezeigt werden oder nicht?
"tab-border" guint (nur beschreibbar) Breite des Randes um die Reiterbeschriftung (in Pixel)
"tab-hborder" guint Breite des Randes über und unter der Reiterbeschriftung (in Pixel)
"tab-vborder" guint Breite des Randes links und rechts der Reiterbeschriftung (in Pixel)
"tab-pos" GtkPositionType Position des Reiter GTK_POS_LEFT – links GTK_POS_RIGHT – rechts GTK_POS_TOP – oben GTK_TOP_BOTTOM – unten

Button-Boxen – Gtk*ButtonBox

Die Button-Boxen GtkVButtonBox (Typenkennung: GTK_TYPE_VBUTTON_BOX) und GtkHButtonBox (Typenkennung: GTK_TYPE_HBUTTON_BOX) sind abgeleitete Klassen von GtkVBox und GtkHBox. Diese Behälter-Widgets eignen sich überall dort, wo Sie Button in einer vertikalen oder horizontalen Reihenfolge anordnen müssen. Ansonsten verhalten sich Button-Boxen bezüglich ihrer Eigenschaften, die vorhanden sind, genauso wie die normalen Boxen. Hinzu kommt noch die zusätzliche Eigenschaft layout-style, womit Sie angeben können, wie die Knöpfe in der Box angeordnet werden sollen. Mögliche Werte hierfür wären:

gp  GTK_BUTTONBOX_DEFAULT_STYLE – Standardeinstellung lassen
gp  GTK_BUTTONBOX_SPREAD – gleichmäßig verteilen
gp  GTK_BUTTONBOX_EDGE – an den Enden der Box platzieren
gp  GTK_BUTTONBOX_START – am Anfang der Box gruppieren
gp  GTK_BUTTONBOX_END – am Ende der Box gruppieren

Rheinwerk Computing

15.7.3 Tabellen – GtkTable  downtop

Neben den Boxen sind Tabellen (Klasse GtkTable; Typenkennung: GTK_TYPE_TABLE) sehr gut geeignet, um das Layout der Software zusammenzupacken. Ähnlich wie bei einer Tabellenkalkulation lassen sich die Widgets hiermit in Zeilen und Spalten anordnen. Ebenso wie auf die Boxen, so werden Sie auch auf die Tabellen noch das eine oder andere Mal in diesem Kapitel stoßen, so dass hier nur ein kurzes Beispiel angeführt werden soll, das mehr oder weniger nur die Packfunktionen der Tabellen demonstriert.

/* gtk3b.c */
/* Behälter:        */
/*    Tabellen-Demo */
#include <gtk/gtk.h>
#define BUTTONS 3
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");
  gtk_main_quit();
}
int main(int argc, char **argv) {
  GtkWindow  *win;
  GdkPixbuf  *pic;
  GtkTable   *table;
  GtkButton  *button1, *button2, *button3;
  gtk_init( &argc, &argv );
  /* Eine Grafik in einen Pixbuf laden */
  pic = gdk_pixbuf_new_from_file("icon/at-work.gif", NULL );
  /* Fenster mit folgenden Eigenschaften anlegen */
  win = g_object_new( GTK_TYPE_WINDOW,
                      "title", "Eine einfache Tabelle",
                      "default-width",  300,
                      "default-height", 200,
                      "resizable", TRUE,
                      "window-position", GTK_WIN_POS_CENTER,
                      "border-width", 10,
                      "icon", pic,
                      NULL );
  button1 = g_object_new( GTK_TYPE_BUTTON,
                     "label","Kein Schrumpfen\nkein Expandieren",
                     NULL);
  button2 = g_object_new( GTK_TYPE_BUTTON,
                    "label","Expandiert und schrumpft\nvertikal",
                    NULL);
  button3 = g_object_new( GTK_TYPE_BUTTON,
           "label","Expandiert und schrumpft\n in beide Seiten",
           NULL);
  table = g_object_new( GTK_TYPE_TABLE,
                        "n-columns", 2,
                        "n-rows", 2,
                        NULL);
  /* Signalhandler einrichten */
  g_signal_connect( win, "delete-event",
                    G_CALLBACK(delete_Event), NULL );
  g_signal_connect( win, "destroy",
                    G_CALLBACK(end), NULL );
  /* Inhalt der Tabelle mit verschiedenen Optionen erstellen */
  gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(button1),
                     0, 1, 0, 1,
                     GTK_FILL, GTK_FILL, 0, 0);
  gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(button2),
                     0, 1, 1, 2,
                     GTK_FILL, GTK_FILL|GTK_EXPAND|GTK_SHRINK,
                     0, 0);
  gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(button3),
                     1, 2, 1, 2,
                     GTK_FILL | GTK_EXPAND | GTK_SHRINK,
                     GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
  gtk_container_add(GTK_CONTAINER( win ), GTK_WIDGET( table ) );
  /* Fenster anzeigen */
  gtk_widget_show_all( GTK_WIDGET(win) );
  /* Hauptschleife von gtk */
  gtk_main();
  g_print("Die GTK-Hauptschleife wurde beendet\n");
  return 0;
}

Das Programm bei der Ausführung:

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

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

Abbildung 15.10    Widgets in GtkTable mit verschiedenen Optionen packen


Das Tabellen-Packing-Widget mit der Klasse GtkTable (Typenkennung: GTK_TYPE_TABLE) funktioniert im Prinzip genauso wie das der vertikalen bzw. horizontalen Boxen. Nur verwenden Sie für das Packen eines Widgets x/y-Koordinaten. Sie können sich das Ganze wie bei einem Tabellenkalkulationsprogramm vorstellen. Sie erzeugen mithilfe der Eigenschaften n-rows für Zeilen und n-columns für Spaltenanzahl eine Tabelle. Dann geben Sie bei den entsprechenden Packfunktionen die Koordinaten an, in welcher Reihe und Spalte das Widget platziert werden soll.

Die Funktionen, mit denen Sie das Packen mit Tabellen realisieren können, lauten:

void gtk_table_attach_defaults( GtkTable *table,
                                GtkWidget *widget,
                                quint left_attach,
                                quint right_attach,
                                quint top_attach,
                                quint bottom_attach );
GtkWidget *gtk_table_attach ( GtkTable *table,
                              GtkWidget *widget,
                              quint left_attach,
                              quint right_attach,
                              quint top_attach,
                              quint bottom_attach,
                              GtkAttachOptions xoptions,
                              GtkAttachOptions yoptions,
                              quint xpadding,
                              quint ypadding );

Die einfachste Version, einzelne Widgets in den Tabellenbehälter zu packen, ist mit der Funktion gtk_table_attach_defaults() gegeben. Damit packen Sie das Widget (zweiter Parameter) in die Tabelle (erster Parameter). Die Angabe der Spalte lautet von left_attach für links nach right_attach für rechts und für die Zeile von top_attach für oben bis bottom_attach für unten. Ein Codeausschnitt zum besseren Verständnis mit anschließender Abbildung (15.11) dazu:

/* Erzeugen einer 3x2-Tabelle */
table = gtk_table_new(3,2,TRUE);
/* ein Widget an die linke obere Ecke einfügen */
gtk_table_attach_defaults(GTK_TABLE(table), button1, 0,1, 0,1);
/* ein Widget an der linken unteren Ecke hinzufügen */
gtk_table_attach_defaults(GTK_TABLE(table), button2, 0,1, 1,2);
/* ein Widget an der rechten unteren Ecke hinzufügen */
gtk_table_attach_defaults(GTK_TABLE(table), button3, 2,3, 1,2);

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

Abbildung 15.11    Verwendung eines tabellarischen Packet-Widgets


Wollen Sie hingegen mehr als die Standardeinstellung zum Packen der Widgets in eine Tabelle verwenden, müssen Sie die Funktion gtk_table_attach() verwenden. Hier sind noch weitere vier Parameter neben gtk_table_attach_defaults() hinzugekommen. Für xoptions und yoptions vom Typ GtkAttachOptions können Sie noch folgende symbolische Konstanten verwenden:

gp  GTK_EXPAND – Widget breitet sich aus, falls überschüssiger Platz vorhanden ist (siehe Box-Widget).
gp  GTK_FILL – Das Widget füllt den zusätzlichen Platz ganz aus (siehe Box-Widget).
gp  GTK_SHRINK – Das Widget lässt sich verkleinern, und zwar, falls nötig, kleiner als seine Zelle.

Die einzelnen Optionen lassen sich auch mit dem bitweisen ODER-Operator (|) verknüpfen.

Mit xpadding und ypadding können Sie den Abstand in Pixeln vom Nachbarn rechts/links bzw. oben/unten angeben. Ich finde, das zuvor gezeigte ausführbare Beispiel zeigt die Bedeutungen der einzelnen Argumente recht eindeutig.

Folgende Eigenschaften können außer der Spalten- und Reihenanzahl noch an die Tabelle GtkTable übergeben werden:


Tabelle 15.10    Eigenschaften für GtkTable (GTK_TYPE_TABLE)

Eigenschaft Datentyp Bedeutung
"column-spacing" guint Spaltenabstand in Pixel
"homogeneous" gboolean Bei TRUE bleiben alle Spalten der Tabelle gleich hoch und breit.
"n-columns" guint Spaltenanzahl der Tabelle
"n-rows" guint Zeilenanzahl der Tabelle
"row-spacing" guint Zeilenabstand in Pixel


Rheinwerk Computing

15.7.4 Ausrichtung – GtkAlignment  toptop

GtkAlignment (von der Typenkennung GTK_TYPE_ALIGNMENT) ist ein Behälter, worin Sie Widgets hineinpacken und nach bestimmten Eigenschaften ausrichten können. Hier die möglichen Eigenschaften für diesen Behälter-Widget:


Tabelle 15.11    Eigenschaften für GtkAlignment (GTK_TYPE_ALIGNMENT)

Eigenschaft Datentyp Bedeutung
"xalign" gfloat Horizontale Ausrichtung des Kind-Widgets (0.0 = links bündig; 0.5 = horizontal zentriert; 1.0 = rechtsbündig)
"xscale" gfloat Nimmt der Behälter mehr Fläche ein als das Kind-Widget, kann hiermit die horizontale Ausrichtung des Kind-Widgets im Behälter bestimmt werden. (0.0 = Kind-Widget darf nicht vergrößert werden; 1.0 = Kind-Widget darf den kompletten zur Verfügung stehenden Platz im Behälter einnehmen.)
"yalign" gfloat Vertikale Ausrichtung des Kind-Widgets (0.0 = oben; 0.5 = vertikal zentriert; 1.0 = unten)
"yscale" gfloat Siehe xscale, nur für die vertikale Ausrichtung

 << zurück
  
  Zum Rheinwerk-Shop
Neuauflage: Linux-UNIX-Programmierung
Neuauflage:
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Linux-Server






 Linux-Server


Zum Rheinwerk-Shop: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Rheinwerk-Shop: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Rheinwerk-Shop: Shell-Programmierung






 Shell-
 Programmierung


Zum Rheinwerk-Shop: Linux Handbuch






 Linux Handbuch


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
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.


Nutzungsbestimmungen | Datenschutz | Impressum

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

Cookie-Einstellungen ändern