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.12 Auswählen (Selection)  downtop

Dinge wie das Auswählen (Selektieren) einer Datei, der Farben oder Schriftarten muss man zum Glück nicht mehr selbst programmieren. Hierzu existieren in GTK+ wieder einige vorbereitete Widgets. Zur einfachen Farbauswahl wird das Widget GtkColorSelection, zur Auswahl von Schriftarten GtkFontSelection und zur Dateiauswahl GtkFileSelection verwendet.

Auf die Auswahl von Dateien soll in diesem Abschnitt etwas näher eingegangen werde. Hierzu wurde das Listing des einfachen Texteditors vom Beispiel zuvor um die Funktion der Dateiauswahl erweitert. Damit können Sie nun einfache Textdateien öffnen und im Editor anzeigen lassen. Zusätzlich wurde dem Beispiel auch noch eine Funktion zum Speichern spendiert, wobei hier wiederum einige weitere Funktionen des Text-Widget-Systems von GTK+ verwendet wurden.

/* gtk8.c */
/* Mehrzeiliger Text                   */
/* mit Dateiauswahl - GtkFileSelection */
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
/* Funktionsprototypen */
static GtkWindow *create_window (void);
static void create_tags (GtkTextBuffer * buffer);
static void on_button_clear_clicked ( 
                     GtkButton * button, gpointer user_data );
static void on_button_cut_clicked ( 
                     GtkButton * button, gpointer user_data );
static void on_button_copy_clicked ( 
                     GtkButton * button, gpointer user_data );
static void on_button_paste_clicked ( 
                     GtkButton * button, gpointer user_data );
static void on_button_bold_clicked ( 
                     GtkButton * button, gpointer user_data );
static void on_button_underline_clicked ( 
                     GtkButton * button, gpointer user_data );
static void on_button_strike_clicked ( 
                     GtkButton * button, gpointer user_data );
static void on_button_color_clicked ( 
                     GtkButton * button, gpointer user_data );
static void ok_buttonCB (
                     GtkWidget * clicked, GtkWidget * selection);
static void file_open (
                     GtkButton * clicked, GtkWidget * selection);
static void on_button_save_clicked ( 
                     GtkButton * button, gpointer user_data );
/* Dateiname zum Öffnen */
static gchar *file = NULL;
static GtkTextView *textview;
static GtkWindow * create_window (void) {
  GtkWindow *window;
  GdkPixbuf  *pic;
  GtkVBox *vbox_main;
  GtkToolbar *toolbar;
  GtkWidget *button_clear, *button_cut, *button_copy,
  *button_paste, *button_bold, *button_underline,
  *button_strike, *button_color, *button_open,
  *button_save;
  GtkScrolledWindow *scrolledwindow;
  GtkTextBuffer *buffer;
  GtkFileSelection *fileselect;
  /* Eine Grafik in einen Pixbuf laden */
  pic = gdk_pixbuf_new_from_file("icon/at-work.gif", NULL );
  /* Fenster mit folgenden Eigenschaften anlegen */
  window = g_object_new( GTK_TYPE_WINDOW,
                         "title", "Textansicht und Textpuffer",
                         "default-width",  300,
                         "default-height", 200,
                         "resizable", TRUE,
                         "window-position", GTK_WIN_POS_CENTER,
                         "border-width", 0,
                         "icon", pic,
                         NULL );
  /* eine vertikale Box erzeugen */
  vbox_main = g_object_new( GTK_TYPE_VBOX,
                            "spacing", 0,
                            NULL);
  /* Eine neue Toolbar erzeugen */
  toolbar = g_object_new (GTK_TYPE_TOOLBAR,
                         /* "toolbar-style", GTK_TOOLBAR_ICONS,*/
                          NULL);
  /* Buttons mit Stock-Icons für die Toolbar erzeugen */
  button_open = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-open",
                                      "Datei oeffnen",
                                      NULL, NULL, NULL, -1);
  button_save = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-save",
                                      "Datei speichern",
                                      NULL, NULL, NULL, -1);
  button_clear=gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-clear",
                                      "Text loeschen",
                                      NULL,NULL,NULL,-1);
  button_cut=gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-cut",
                                      "Text ausschneiden",
                                      NULL, NULL, NULL, -1);
  button_copy = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-copy",
                                      "Text kopieren",
                                      NULL, NULL, NULL, -1);
  button_paste=gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-paste",
                                      "Text einfuegen",
                                      NULL, NULL, NULL, -1);
  gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
  button_bold = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-bold",
                                      "Fette Schriftart",
                                      NULL, NULL, NULL, -1);
  button_underline=gtk_toolbar_insert_stock(
                                      GTK_TOOLBAR (toolbar),
                                      "gtk-underline",
                                      "Schrift unterstreichen",
                                      NULL, NULL, NULL, -1);
  button_strike=gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-strikethrough",
                                      "Schrift durchstreichen",
                                      NULL, NULL, NULL, -1);
  button_color=gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
                                      "gtk-select-color",
                                      "farbige Schrift (Blau)",
                                      NULL, NULL, NULL, -1);
  /* Rollbalken erzeugen */
  scrolledwindow = g_object_new( GTK_TYPE_SCROLLED_WINDOW,
                      "hscrollbar_policy" , GTK_POLICY_AUTOMATIC,
                      "vscrollbar_policy" , GTK_POLICY_AUTOMATIC,
                      "window_placement"  , GTK_CORNER_TOP_LEFT,
                      NULL);
  /* Eine Textansicht erzeugen */
  textview = g_object_new( GTK_TYPE_TEXT_VIEW, NULL);
  /* Aktuellen Puffer für die Textansicht ermitteln */
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
  /* Einige einfache Tags zur Formatierung anlegen */
  create_tags (buffer);
  /* Dateiauswahlbox erzeugen */
  fileselect = g_object_new( GTK_TYPE_FILE_SELECTION,
                         "filename" ,"Bitte Datei auswaehlen ...",
                         "select-multiple", FALSE,
                         "show-fileops"  , TRUE,
                         NULL);
  /* Signalhandler einrichten */
  g_signal_connect ( (gpointer) window, "delete_event",
                     G_CALLBACK (gtk_main_quit), NULL);
  g_signal_connect ( (gpointer) button_clear, "clicked",
                     G_CALLBACK (on_button_clear_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_cut, "clicked",
                     G_CALLBACK (on_button_cut_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_copy, "clicked",
                     G_CALLBACK (on_button_copy_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_paste, "clicked",
                     G_CALLBACK (on_button_paste_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_bold, "clicked",
                     G_CALLBACK (on_button_bold_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_underline, "clicked",
                     G_CALLBACK (on_button_underline_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_strike, "clicked",
                     G_CALLBACK (on_button_strike_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_color, "clicked",
                     G_CALLBACK (on_button_color_clicked),
                     (gpointer) textview);
  g_signal_connect ( (gpointer) button_save, "clicked",
                     G_CALLBACK (on_button_save_clicked),
                     (gpointer) textview);
  g_signal_connect (GTK_OBJECT
                 (GTK_FILE_SELECTION (fileselect)->ok_button),
                 "clicked", G_CALLBACK(ok_buttonCB), fileselect);
  g_signal_connect_swapped (
      GTK_OBJECT(GTK_FILE_SELECTION (fileselect)->ok_button),
      "clicked",
      G_CALLBACK(gtk_widget_hide),
      GTK_OBJECT (fileselect));
  g_signal_connect_swapped (
      GTK_OBJECT(GTK_FILE_SELECTION (fileselect)->cancel_button),
      "clicked",
      G_CALLBACK(gtk_widget_hide),
      GTK_OBJECT (fileselect));
  g_signal_connect (GTK_OBJECT(button_open), "clicked",
                    G_CALLBACK (file_open), fileselect);
  /* Alles packen */
  gtk_container_add( GTK_CONTAINER (window),
                     GTK_WIDGET(vbox_main) );
  gtk_box_pack_start ( GTK_BOX (vbox_main),
                       GTK_WIDGET(toolbar),
                       FALSE, FALSE,0);
  gtk_box_pack_start ( GTK_BOX (vbox_main),
                       GTK_WIDGET(scrolledwindow),
                       TRUE,TRUE, 0);
  gtk_container_add ( GTK_CONTAINER (scrolledwindow),
                      GTK_WIDGET(textview));
  /* Erzeugtes Fenster zurückgegeben */
  return window;
}
/* Bitte entnehmen Sie die Funktionen ...
 * on_button_clear_clicked(), on_button_cut_clicked(), 
 * on_button_copy_clicked(), on_button_paste_clicked(),
 * on_button_bold_clicked(), on_button_underline_clicked(),
 * on_button_strike_clicked(), on_button_color_clicked (),
 * create_tags ()
 * ... vom Beispiel gtk7.c oder von der Buch-CD.
 */
/* Datei zum Lesen öffnen */
static void
ok_buttonCB (GtkWidget * clicked, GtkWidget * selection) {
  FILE *f;
  gchar buf[255];
  GtkTextBuffer *buffer = NULL;
  GtkTextIter end;
  file=gtk_file_selection_get_filename (
         GTK_FILE_SELECTION(selection));
  if (file == NULL)
    return; /* Datei existiert nicht */
  f = fopen (file, "r");
  if (NULL == f) {
    printf("Keine solche Datei vorhanden!!\n");
    return;
  }
  else {
    buffer = gtk_text_view_get_buffer (
               GTK_TEXT_VIEW (textview) );
    while(fgets(buf,255,f)) {
      gtk_text_buffer_get_end_iter(buffer, &end);
      gtk_text_buffer_insert(buffer, &end, buf, -1);
    }
  }
  fclose (f);
}
static void
file_open (GtkButton * clicked, GtkWidget * selection) {
  GtkTextBuffer *buffer = NULL;
  /* Neue Datei öffnen, daher:
     + Dateinamen auf NULL setzen
     + Inhalt von bereits vorhandenem Text löschen */
  file = NULL;
  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
  gtk_text_buffer_set_text(buffer,"", -1);
  gtk_widget_show (selection);
}
/* Datei abspeichern - ohne wenn und aber !*/
static void
on_button_save_clicked (GtkButton * button, gpointer user_data) {
  GtkTextBuffer *buffer = NULL;
  GtkTextIter start, end;
  gchar *buf;
  gchar *dyn;
  FILE *f;
  if(file != NULL) {
    /* Aktuellen Puffer für die Textansicht ermitteln */
    buffer = gtk_text_view_get_buffer (
               GTK_TEXT_VIEW (user_data) );
    /* Markierte Auswahl im Puffer ermitteln */
    gtk_text_buffer_get_bounds (buffer, &start, &end);
    /* Zeiger auf den kompletten Text zurück */
    buf=gtk_text_buffer_get_text(buffer, &start, &end, TRUE);
    dyn = g_malloc( strlen(buf)+1 );
    g_stpcpy( dyn, buf );
    /* Zur Kontrolle Ausgabe auf die Konsole */
    g_print("%s\n... gespeichert!\n",dyn);
    f = fopen(file, "w");
    if(f != NULL)
      fwrite(dyn, strlen(dyn)+1, 1, f);
    fclose(f);
  }
}
int main (int argc, char **argv) {
  GtkWindow *window;
  gtk_init (&argc, &argv);
  window = create_window ();
  gtk_widget_show_all (GTK_WIDGET(window));
  gtk_main ();
  return 0;
}

Das Programm bei der Ausführung:

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

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

Abbildung 15.17    Neue Funktionen zum Öffnen und Speichern von Dateien



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

Abbildung 15.18    Widget GtkFileSelection im Einsatz



Hinweis   Aus drucktechnischen Gründen wurde auch hier wieder die Toolbar des Listings auf dem Screenshot mit der Eigenschaft "toolbar-style", GTK_TOOLBAR_ICONS versehen; also ohne den Text unter dem Icon.

Hinweis   Bei diesem Beispiel wurden Sie höchstwahrscheinlich zum ersten Mal mit UTF-8-Warnmeldungen in der Konsole überschüttet, aus der Sie das Programm gestartet haben. Natürlich nur, wenn die Datei, die Sie öffnen, Nicht-ASCII-Zeichen enthält. Zwangsläufig müssen Sie sich hierbei wohl intensiver mit den UTF-8-Funktionen der Glib auseinander setzen, wenn Sie derartige Programme für die Masse entwickeln wollen.



Rheinwerk Computing

15.12.1 Dateiauswahl – GtkFileSelection  toptop

Wie Sie im Beispiel schon gesehen haben, ist es üblich, diesen Dialog via Signalhandler anzulegen – genauer, anzeigen zu lassen, indem die Buttons OK und Abbrechen mit dieser Dialogbox gebunden und ausgewertet werden. Beide Buttons finden Sie in der Struktur GtkFileSelection unter dem Namen ok_button und cancel_button.

struct GtkFileSelection {
...
  GtkWidget *ok_button;
  GtkWidget *help_button;
...
};

Folgende Eigenschaften stehen Ihnen bei der Dateiauswahl zur Verfügung:


Tabelle 15.28    Eigenschaften für GtkFileSelection

Eigenschaft Datentyp Bedeutung
"filename" gchararray Der Dateiname mit Pfad, der ausgewählt wurde. Macht allerdings nur Sinn auszuwerten, wenn select-multiple FALSE ist.
"select-multiple" gboolean Bei TRUE können mehrere Dateien auf einmal ausgewählt werden (bei gedrückter (STRG)-Taste möglich).
"show- fileops" gboolean Sollen die Buttons zur Dateiverwaltung mit angezeigt werden (Verzeichnis anlegen, Datei löschen, Datei umbenennen)?

Wie schon erwähnt, können Sie auch mehrere Dateien auf einmal selektieren. Dann allerdings müssen Sie die Funktion gtk_file_selection_get_selections() verwenden. Mit dieser Funktion erhalten Sie ein nullterminiertes Feld von Strings zurück, worin die Dateinamen enthalten sind. Allerdings sind in den Dateinamen die lokalen Zeichenkodierungen enthalten. Damit es nicht reihenweise Fehler oder gar Abstürze hagelt, sollten Sie die Dateinamen zuvor in eine UTF-8-Kodierung mit der Funktion g_filename_from_utf8() umwandeln. Dies natürlich nur, wenn Nicht-ASCII-Zeichen beim Dateinamen verwendet wurden. Das UTF-8-Problem wurde bereits zu Beginn kurz angesprochen.

Im Beispiel wurde die Funktion gtk_file_selection_get_filename() mit der Dateiauswahl GtkFileSelection als Argument verwendet, um den Dateinamen mitsamt Pfad zu ermitteln, der ausgewählt wurde.

Ferner wurden noch weitere Funktionen verwendet, die sich auf GtkTextBuffer beziehen, die hier nicht unerwähnt bleiben sollten.

void gtk_text_buffer_get_end_iter ( GtkTextBuffer *buffer,
                                    GtkTextIter *iter );
void gtk_text_buffer_insert ( GtkTextBuffer *buffer,
                              GtkTextIter *iter,
                              const gchar *text,
                              gint len );
void gtk_text_buffer_get_bounds ( GtkTextBuffer *buffer,
                                  GtkTextIter *start,
                                  GtkTextIter *end );
gchar *gtk_text_buffer_get_text( GtkTextBuffer *buffer,
                                 const GtkTextIter *start,
                                 const GtkTextIter *end,
                                 gboolean include_hidden_chars );

Mit gtk_text_buffer_get_end_iter() ermitteln Sie das Ende des Textpuffers. Die so ermittelte Adresse verwenden Sie anschließend in der Funktion gtk_text_buffer_insert(). Mit dieser Funktion wird ein Text text an der Position iter mit der Länge len angefügt. Für len kann auch –1 angegeben werden, was allerdings voraussetzt, dass der Text nullterminiert ist.

Mit der Funktion gtk_text_buffer_get_bounds() ermitteln Sie die Startposition (start) und Endposition (end) im Textpuffer (buffer). Diese beiden so ermittelten Iteratoren werden gleich mit der Funktion gtk_text_buffer_get_text() verwendet, die aus dem Textpuffer dann eine Adresse auf den kompletten Text zwischen diesen beiden Iteratoren zurückgibt. Mit include_hidden_chars können Sie angeben, ob auch unsichtbare Zeichen mitgenommen werden.

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