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.8 Buttons und Toogled-Buttons  downtop

Einfache Buttons haben Sie in den Beispielen zuvor schon mehrfach verwendet, ohne dass hierbei genauer darauf eingegangen wurde. Buttons (oder auch als Knöpfe bezeichnet) gibt es bei GTK+ in vierfacher Ausführung – wobei alle von der Klasse GtkButton (Typenkennung: GTK_TYPE_BUTTON) abstammen.

Neben dem einfachen Button (GtkButton) stehen Ihnen noch Ankreuzfelder (GtkCheckButtons; Typenkennung: GTK_TYPE_CHECK_BUTTON), Radioknöpfe (GtkRadioButton; Typenkennung: GTK_TYPE_RADIO_BUTTON) und Umschalt-Buttons (GtkToggleButton; Typenkennung: GTK_TYPE_TOGGLED_BUTTON) zur Verfügung. Bevor auf die einzelnen Buttons im Detail eingegangen wird, wieder ein Listing, das die einzelnen Buttons präsentiert.

/* gkt4.c */
/* Buttons:        */
/*    Button-Demo */
#include <gtk/gtk.h>
#define VBOX 5
#define BUTTONS 4
#define LABEL   4
#define BUF 50
static GtkToggleButton *tbuttons[BUTTONS];
static GtkRadioButton  *rbuttons[BUTTONS];
static GtkCheckButton  *cbuttons[BUTTONS];
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();
}
/* Zustand aller Umschaltbuttons auswerten */
static void toogled_auswerten(gpointer button) {
  gboolean toogled1, toogled2, toogled3, toogled4 = FALSE;
  g_print("Toogled-Button Auswertung:\n");
  g_object_get(tbuttons[0], "active", &toogled1, NULL);
  g_object_get(tbuttons[1], "active", &toogled2, NULL);
  g_object_get(tbuttons[2], "active", &toogled3, NULL);
  g_object_get(tbuttons[3], "active", &toogled4, NULL);
  if(toogled1)
    g_print("Toogled-Button 1 ist aktiviert\n");
  if(toogled2)
    g_print("Toogled-Button 2 ist aktiviert\n");
  if(toogled3)
    g_print("Toogled-Button 3 ist aktiviert\n");
  if(toogled4)
    g_print("Toogled-Button 4 ist aktiviert\n");
  if(!toogled1 && !toogled2 && !toogled3 && !toogled4)
    g_print("Kein Toogled-Button ist aktiv\n");
  g_print("--------------------------------\n");
}
/* Zustand aller Radio-Buttons auswerten */
static void radio_auswerten(gpointer button) {
  gboolean radio1, radio2, radio3, radio4 = FALSE;
  g_print("Radio-Button Auswertung:\n");
  g_object_get(rbuttons[0], "active", &radio1, NULL);
  g_object_get(rbuttons[1], "active", &radio2, NULL);
  g_object_get(rbuttons[2], "active", &radio3, NULL);
  g_object_get(rbuttons[3], "active", &radio4, NULL);
  if(radio1)
    g_print("Radio-Button 1 ist aktiviert\n");
  else if(radio2)
    g_print("Radio-Button 2 ist aktiviert\n");
  else if(radio3)
    g_print("Radio-Button 3 ist aktiviert\n");
  else
    g_print("Radio-Button 4 ist aktiviert\n");
  g_print("--------------------------------\n");
}
/* Zustand aller Ankreuz-Buttons auswerten */
static void check_auswerten(gpointer button) {
  gboolean check1, check2, check3, check4 = FALSE;
  g_print("Check-Button Auswertung:\n");
  g_object_get(cbuttons[0], "active", &check1, NULL);
  g_object_get(cbuttons[1], "active", &check2, NULL);
  g_object_get(cbuttons[2], "active", &check3, NULL);
  g_object_get(cbuttons[3], "active", &check4, NULL);
  if(check1)
    g_print("Check-Button 1 ist aktiviert\n");
  if(check2)
    g_print("Check-Button 2 ist aktiviert\n");
  if(check3)
    g_print("Check-Button 3 ist aktiviert\n");
  if(check4)
    g_print("Check-Button 4 ist aktiviert\n");
  if(!check1 && !check2 && !check3 && !check4)
    g_print("Kein Check-Button aktiv\n");
  g_print("--------------------------------\n");
}
int main(int argc, char **argv) {
  GtkWindow  *win;
  GdkPixbuf  *pic;
  GtkHBox    *hbox;
  GtkVBox    *vbox[VBOX];
  GtkLabel   *label[LABEL];
  GtkVSeparator *vsep[VBOX-2];
  GtkButton  *buttons[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",  350,
                      "default-height", 200,
                      "resizable", TRUE,
                      "window-position", GTK_WIN_POS_CENTER,
                      "border-width", 10,
                      "icon", pic,
                      NULL );
  /* Eine horizontale Box erzeugen */
  hbox = g_object_new( GTK_TYPE_HBOX,
                       "spacing", 10,
                       NULL);
  /* VBOX vertikale Boxen erzeugen */
  for(i=0; i < VBOX; i++)
    vbox[i] = g_object_new( GTK_TYPE_VBOX,
                            "spacing", 10,
                            NULL);
  /* VBOX-2 vertikale Linien erzeugen */
  for(i=0; i < VBOX-2; i++)
    vsep[i] = g_object_new( GTK_TYPE_VSEPARATOR, NULL);
  /* Labels erzeugen */
  label[0] = g_object_new( GTK_TYPE_LABEL,
                           "label", "Auswerten der ...",
                           NULL);
  label[1] = g_object_new( GTK_TYPE_LABEL,
                           "label", "Toogled-Buttons:",
                           NULL );
  label[2] = g_object_new( GTK_TYPE_LABEL,
                           "label", "Radio-Buttons:",
                           NULL);
  label[3] = g_object_new( GTK_TYPE_LABEL,
                           "label", "Check-Buttons:",
                           NULL );
  /* "normale" Buttons erzeugen */
  buttons[0] = g_object_new( GTK_TYPE_BUTTON,
                             "label", "Toggled-Buttons",
                             "relief", GTK_RELIEF_HALF,
                             NULL );
  buttons[1] = g_object_new( GTK_TYPE_BUTTON,
                             "label", "Radio-Buttons",
                             "relief", GTK_RELIEF_HALF,
                             NULL );
  buttons[2] = g_object_new( GTK_TYPE_BUTTON,
                             "label", "Check-Buttons",
                             "relief", GTK_RELIEF_HALF,
                             NULL );
  buttons[3] = g_object_new( GTK_TYPE_BUTTON,
                             "label", "Programmende",
                             "relief", GTK_RELIEF_HALF,
                             NULL );
  /* BUTTONS Umschalt-Buttons erzeugen */
  for(i = 0; i < BUTTONS; i++) {
    g_snprintf(buf,BUF,"Toggled %d",i+1);
    tbuttons[i] = g_object_new( GTK_TYPE_TOGGLE_BUTTON,
                                "label", buf,
                                NULL );
  }
  /* BUTTONS Radio-Buttons erzeugen */
  for(i = 0; i < BUTTONS; i++) {
    g_snprintf(buf,BUF,"Radio %d",i+1);
    rbuttons[i] = g_object_new( GTK_TYPE_RADIO_BUTTON,
                                "label", buf,
                                NULL );
    if(i!=0)
      g_object_set( rbuttons[i],
                    "group", rbuttons[0],
                    NULL );
  }
  /* BUTTONS Check-Buttons erzeugen */
  for(i = 0; i < BUTTONS; i++) {
    g_snprintf(buf,BUF,"Ckeck %d",i+1);
    cbuttons[i] = g_object_new( GTK_TYPE_CHECK_BUTTON,
                                "label", buf,
                                NULL );
  }
  /* Signalhandler einrichten */
  g_signal_connect( win, "delete-event",
                    G_CALLBACK(delete_Event), NULL );
  g_signal_connect( win, "destroy",
                    G_CALLBACK(end), NULL );
  /* Signalhandler zum Auswerten der einzelnen */
  /* Buttons einrichten                        */
  g_signal_connect( buttons[0], "clicked",
                    G_CALLBACK(toogled_auswerten), NULL);
  g_signal_connect( buttons[1], "clicked",
                    G_CALLBACK(radio_auswerten), NULL);
  g_signal_connect( buttons[2], "clicked",
                    G_CALLBACK(check_auswerten), NULL);
  g_signal_connect( buttons[3], "clicked",
                    G_CALLBACK(end), NULL);
  /* Vertikale Boxen und Linien in die horizontalen */
  /* Boxen packen                                  */
  for(i=0; i<VBOX; i++) {
    gtk_box_pack_start_defaults( GTK_BOX(hbox),
                                 GTK_WIDGET(vbox[i]));
    if(i < VBOX-2)
      gtk_box_pack_start_defaults( GTK_BOX(hbox),
                                   GTK_WIDGET(vsep[i]));
  }
  /* Beschriftung der ersten vertikalen Box packen */
  gtk_box_pack_start_defaults( GTK_BOX(vbox[0]),
                               GTK_WIDGET(label[0]) );
  /* normale Buttons in die erste vertikale Box */
  /* unter der Beschriftung einfügen            */
  for(i = 0; i < BUTTONS; i++)
    gtk_box_pack_start_defaults( GTK_BOX(vbox[0]),
                                 GTK_WIDGET(buttons[i]) );
  /* Beschriftung der zweiten vertikalen Box packen */
  gtk_box_pack_start_defaults( GTK_BOX(vbox[1]),
                               GTK_WIDGET(label[1]));
  /* Umschalt-Buttons in die zweite vertikale Box */
  /* unter der Beschriftung einfügen              */
  for(i = 0; i < BUTTONS; i++)
    gtk_box_pack_start_defaults( GTK_BOX(vbox[1]),
                                 GTK_WIDGET(tbuttons[i]) );
  /* Beschriftung der dritten vertikalen Box packen */
  gtk_box_pack_start_defaults( GTK_BOX(vbox[2]),
                               GTK_WIDGET(label[2]) );
  /* Radio-Buttons in die dritte vertikale Box */
  /* unter der Beschriftung einfügen           */
  for(i = 0; i < BUTTONS; i++)
    gtk_box_pack_start_defaults( GTK_BOX(vbox[2]),
                                 GTK_WIDGET(rbuttons[i]) );
  /* Beschriftung der vierten vertikalen Box packen */
  gtk_box_pack_start_defaults( GTK_BOX(vbox[3]),
                               GTK_WIDGET(label[3]) );
  /* Check-Buttons in die vierte vertikale Box */
  /* unter der Beschriftung einfügen           */
  for(i = 0; i < BUTTONS; i++)
    gtk_box_pack_start_defaults( GTK_BOX(vbox[3]),
                                 GTK_WIDGET(cbuttons[i]) );
  /* Die horizontale Box in das Hauptfenster packen */
  gtk_container_add(GTK_CONTAINER( win ), GTK_WIDGET( hbox) );
  /* 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 gtk4 gtk4.c `pkg-config gtk+-2.0 --cflags --libs`
$ ./gtk4

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

Abbildung 15.12    Demonstration von Buttons


Wurden anhand der Abbildung nacheinander die Buttons zur Auswertung betätigt, erhalten Sie nun die entsprechende Ausgabe:

Toogled-Button Auswertung:
Toogled-Button 2 ist aktiviert
Toogled-Button 4 ist aktiviert
--------------------------------
Radio-Button Auswertung:
Radio-Button 3 ist aktiviert
--------------------------------
Check-Button Auswertung:
Check-Button 1 ist aktiviert
Check-Button 3 ist aktiviert
Check-Button 4 ist aktiviert
--------------------------------

Rheinwerk Computing

15.8.1 Buttons allgemein  downtop

Im Großen und Ganzen lassen sich die einzelnen Buttons zusammenfassen, da alle Knöpfe auf die gleiche Art erstellt werden. Jeder Button wird beim Erzeugen (mit entsprechender Typenkennung) mit einem Label versehen und wie ein übliches Widget in den Behälter (hier vertikale Box) gepackt. Folgende Eigenschaften können daher auch für alle Buttons übernommen werden:


Tabelle 15.12    Allgemeine Eigenschaften für alle Arten von Buttons

Eigenschaft Datentyp Bedeutung
"label" gchararray Beschriftung des Buttons
"use-stock" gboolean Bei TRUE wird der Inhalt von label aus dem Repertoire (mehr dazu gleich) und nicht als Beschriftung dargestellt. Vorausgesetzt, eine solche Angabe existiert im Repertoire.
"use-underline" gboolean Bei TRUE kann als Unterstrich ein markierter Buchstabe als Abkürzung verwendet werden, z. B.: "label", "_Programmende", hiermit würde der Anfangsbuchstabe P des Labels unterstrichen und könnte somit als Abkürzung mittels (ALT)+(P) aktiviert werden.


Hinweis   Das Repertoire enthält u. a. standardisierte Icons. Dabei ist jedes dieser Icons in mehreren Größen verfügbar. Neben Icons befinden sich im Repertoire-Eintrag auch standardisierte Beschriftungen und Abkürzungsbuchstaben mit Tastaturkürzel. GTK+ 2.0 liegt eine Demo-Anwendung namens gtk-demo bei (die Sie auch mit diesem Namen in der Kommandozeile starten können). Dabei finden Sie eine Demonstration Stock Item and Icon Browser, die Ihnen sämtliche Einträge des Repertoires auflistet und anzeigt.



Rheinwerk Computing

15.8.2 Radio-Buttons (GtkRadioButton)  downtop

Eine Eigenschaft, die nur ein Radio-Button gewöhnlich besitzt, ist, dass hierbei nur eine Auswahl betätigt werden soll (darf). Wird z. B. ein anderer Radio-Button aktiviert, muss der aktive Button automatisch deaktiviert werden. Hierbei werden alle Radio-Buttons einer Gruppe einem betreffenden Button (meistens der erste) zugeordnet, der dann beim Start der Anwendung auch markiert ist. Im Beispiel wurde hier mit

   g_object_set( rbuttons[i],
                 "group", rbuttons[0],
                 NULL );

allen anderen Radio-Buttons, außer dem ersten, die group-Eigenschaft verhängt.

Eigenschaften von Widgets nachträglich setzen oder abfragen

Sie sahen außerdem, wie Sie nachträglich mit der Funktion g_object_set() einzelne oder mehrere Eigenschaften eines Widgets setzen können, wenn dieses bereits erzeugt wurde. Gleichwertig können Sie hierzu auch die get-Version zum Abfragen von Eigenschaften einzelner Widgets verwenden. Hier die Syntax der beiden Funktionen:

void g_object_set ( gpointer object,
                    const gchar *first_property_name, ...);
void g_object_get ( gpointer object,
                    const gchar *first_property_name, ...);

Im Prinzip könnten Sie in den meisten GTK+-Anwendungen die drei Funktionen g_object_new() zum Erzeugen und Setzen, g_object_get() zum Abfragen und g_object_set() zum Setzen der Eigenschaften von Widgets verwenden. Natürlich soll auch darauf hingewiesen werden, dass Sie auch auf die vielen unzähligen Funktionen, wie gtk_einWidget_get_einWert(), eines jeden Widgets zugreifen können, anstatt g_object_get() zu verwenden.


Rheinwerk Computing

15.8.3 GtkRadioButton, GtkCheckButton und GtkToggleButton  downtop

Diese drei Button-Typen haben zusätzlich noch zwei weitere wichtige Eigenschaften:


Tabelle 15.13    Eigenschaften GtkRadioButton, GtkCheckButton und GtkToggleButton

Eigenschaft Datentyp Bedeutung
"active" gboolean Eigentlich die wichtigste Eigenschaft. Hier kann der Wahrheitswert ermittelt werden: ist der Button aktiv (betätigt, angekreuzt) oder nicht. Hierzu kann die Funktion g_object_get() (wie im Beispiel gesehen) verwendet werden.
"inconsistent" gboolean Bei TRUE wird der Button oder alles um den Button mit einem Querbalken und grau dargestellt, was so viel bedeuten soll, dass sich keine eindeutige Aussage über den Zustand des Widgets machen lässt.


Rheinwerk Computing

15.8.4 Signale für Buttons (GtkButton)  toptop

In der folgenden Tabelle finden Sie eine Liste der Signale, die von jedem Button-Typ (ausgehend von GtkButton) emittiert werden können. Im Beispiel wurden zum Auswerten der Buttons globale Widgets als Buttons erzeugt. Dies wäre nicht nötig gewesen, wenn Sie als Callback-Funktion folgenden Prototyp verwendet hätten, um die Signale zu emittieren:

void button_callback (GtkButton *button,   gpointer user_data)

Tabelle 15.14    Signal für Buttons

Signal Bedeutung
"activate" Kann verwendet werden, um einen Button zu klicken, ohne dass der Anwender diesen angeklickt hätte – Geistermodus.
"clicked" Wird beim Anklicken des Buttons emittiert (bedeutet = Mauszeiger auf dem Button, während Maustaste gedrückt und losgelassen wurde). Dieses Signal wird gewöhnlich am meisten verwendet.
"enter" Wird emittiert, wenn der Mauszeiger sich über dem Button befindet.
"leave" Wird emittiert, wenn der Mauszeiger den Button verlässt.
"pressed" Wird emittiert, wenn der Button gedrückt wurde.
"released" Wird emittiert, wenn der Button losgelassen wurde.

 << 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