15.9 Dateneingabe
Im folgenden Abschnitt lernen Sie einige Widgets kennen, die sich rein zum Erfassen von Daten eignen. Zur Eingabe einzelner Zeilen wird gerne das Widget der Klasse GtkEntry (Typenkennung: GTK_TYPE_ENTRY) verwendet. Einen Schieberegler, womit Sie einige Werte ähnlich wie bei einer Stereoanlage einstellen können, stellt Ihnen die Klasse GtkScale mit ihren Unterklassen GtkVScale (Typenkennung: GTK_TYPE_VSCALE) für einen vertikalen und GtkHScale (Typenkennung: GTK_HSCALE) für einen horizontalen Schieberegler zur Verfügung. Des Weiteren finden Sie Zahlenfelder der Klasse GtkSpinButton (Typenkennung: GTK_TYPE_SPIN_BUTTON), die sich recht ähnlich wie die Schieberegler verhalten und einsetzen lassen. Zu guter Letzt werden Sie für die beiden Widgets GtkSpinButton und GtkScale eine Stellgröße zur Regulierung der Werte benötigen. Hierzu verwendet man das Widget der Klasse GtkAdjustment (Typenkennung: GTK_TYPE_ADJUSTMENT).
Hierzu wieder ein Listing mit der anschließenden Erläuterung der Widgets.
/* gkt5.c */
/* Dateneingabe: */
/* Textfelder - GtkEntry */
/* Schieberegler - GtkScale */
/* Zahlenfelder - GtkSpinButton */
#include <gtk/gtk.h>
#define VBOX 3
#define ENTRYS 3
#define SCALES 3
#define SPIN 2
#define BUF 50
static GtkEntry *entry[ENTRYS];
static GtkVScale *vscale[SCALES];
static GtkAdjustment *vadj[SCALES];
static GtkSpinButton *spin[SPIN];
static GtkAdjustment *spinadj[SPIN];
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();
}
/* Auswertung Eingabefelder */
static void entry_auswerten(gpointer auswert) {
gchar *e1, *e2, *e3;
g_object_get(entry[0], "text", &e1, NULL);
g_object_get(entry[1], "text", &e2, NULL);
g_object_get(entry[2], "text", &e3, NULL);
g_print("Entry-Feld Auswertung:\n");
g_print("Name, Vorname : %s\n", e1);
g_print("Strasse, Hausnr. : %s\n", e2);
g_print("Ort, PLZ : %s\n", e3);
g_print("---------------------------\n");
}
/* Auswertung Schieberegler */
static void scale_auswerten(GtkAdjustment *adj, gpointer scale) {
g_print("Schieberegler Auswertung:\n");
g_print("Regler 1 : %.1f\n",
gtk_adjustment_get_value(vadj[0]));
g_print("Regler 2 : %.1f\n",
gtk_adjustment_get_value(vadj[1]));
g_print("Regler 3 : %.1f\n",
gtk_adjustment_get_value(vadj[2]));
}
/* Auswertung Zahlenfelder */
static void spin_auswerten(GtkAdjustment *adj, gpointer scale) {
g_print("Zahlenfelder Auswertung:\n");
g_print("Regler 1 : %.1f\n",
gtk_adjustment_get_value(spinadj[0]));
g_print("Regler 2 : %.1f\n",
gtk_adjustment_get_value(spinadj[1]));
}
/* Eingabefelder zurücksetzen - löschen */
static void entry_loeschen(gpointer auswert) {
gint i;
for(i=0; i<ENTRYS; i++)
gtk_entry_set_text(entry[i], "");
}
int main(int argc, char **argv) {
GtkWindow *win;
GdkPixbuf *pic;
GtkTable *table;
GtkLabel *label[ENTRYS];
GtkButton *entry_button[2];
GtkHBox *hbox, *hbox_2, *hbox_vscale;
GtkVBox *vbox, *vbox_spin;
GtkHSeparator *hsep;
guint i;
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", "Dateieingabe",
"default-width", 380,
"default-height", 200,
"resizable", TRUE,
"window-position", GTK_WIN_POS_CENTER,
"border-width", 10,
"icon", pic,
NULL );
/* Eine Tabelle 8x3 erzeugen */
table = g_object_new( GTK_TYPE_TABLE,
"n-rows", 8,
"n-columns", 3,
"row-spacing", 3,
"column-spacing" , 3,
"homogeneous", FALSE,
NULL);
/* horizontale Box erzeugen */
hbox = g_object_new( GTK_TYPE_HBOX,
"spacing", 10,
NULL );
/* horizontale Box erzeugen */
hbox_2 = g_object_new( GTK_TYPE_HBOX,
"spacing", 10,
NULL );
/* horizontale Box für Schieberegler erzeugen */
hbox_vscale = g_object_new( GTK_TYPE_HBOX,
"spacing", 20,
NULL );
/* vertikale Box erzeugen */
vbox = g_object_new( GTK_TYPE_VBOX,
"spacing", 10,
NULL );
/* vertikale Box für Zahlenfelder erzeugen */
vbox_spin = g_object_new( GTK_TYPE_VBOX,
"spacing", 7,
NULL );
/* ENTRYS Textfelder erzeugen */
for(i=0; i < ENTRYS; i++)
entry[i] = g_object_new( GTK_TYPE_ENTRY,
"text", "Ihre Eingabe hier ...",
"max-length" ,BUF,
NULL );
/* Labels für die Textfelder erzeugen */
label[0] = g_object_new( GTK_TYPE_LABEL,
"justify", GTK_JUSTIFY_LEFT,
"label", "Name, Vorname",
NULL );
label[1] = g_object_new( GTK_TYPE_LABEL,
"label", "Strasse/Hausnr.",
NULL );
label[2] = g_object_new( GTK_TYPE_LABEL,
"label", "Ort, Postleitz.",
NULL );
/* Buttons zum Auswerten der Textfelder erzeugen */
entry_button[0] = g_object_new( GTK_TYPE_BUTTON,
"label", "Auslesen",
NULL );
entry_button[1] = g_object_new( GTK_TYPE_BUTTON,
"label", "Reset",
NULL );
/* SCALES Stellgrößen für die Schieberegler erzeugen */
for(i=0; i<SCALES; i++)
vadj[i] = GTK_ADJUSTMENT(
gtk_adjustment_new( 1.0,
-100.0,
100.0,
0.1,
10.0,
0.0) );
/* SCALES vertikale Schieberegler erzeugen */
for(i=0; i<SCALES; i++)
vscale[i] = g_object_new( GTK_TYPE_VSCALE,
"adjustment", vadj[i],
NULL );
/* SPIN Stellgrößen für die Zahlenfelder erzeugen */
for(i=0; i<SPIN; i++)
spinadj[i] = GTK_ADJUSTMENT(
gtk_adjustment_new( 1.0,
-100.0,
100.0,
0.1,
10.0,
0.0) );
/* SPIN Zahlenfelder erzeugen */
for(i=0; i<SPIN; i++)
spin[i] = g_object_new( GTK_TYPE_SPIN_BUTTON,
"adjustment", spinadj[i],
"digits", 1,
"value", 20.0,
NULL );
/* horizontale Linie erzeugen */
hsep = g_object_new( GTK_TYPE_HSEPARATOR, NULL);
/* Signalhandler einrichten */
g_signal_connect( win, "delete-event",
G_CALLBACK(delete_Event), NULL );
g_signal_connect( win, "destroy",
G_CALLBACK(end), NULL );
/* Signalhandler für die Buttons */
g_signal_connect( entry_button[0], "clicked",
G_CALLBACK(entry_auswerten), NULL);
g_signal_connect( entry_button[1], "clicked",
G_CALLBACK(entry_loeschen), NULL);
/* Signalhandler, wenn sich einer der */
/* Schieberegler verändert */
g_signal_connect( vscale[0], "value-changed",
G_CALLBACK(scale_auswerten), NULL);
g_signal_connect( vscale[1], "value-changed",
G_CALLBACK(scale_auswerten), NULL);
g_signal_connect( vscale[2], "value-changed",
G_CALLBACK(scale_auswerten), NULL);
/* Signalhandler, wenn sich eines der Zahlenfelder */
/* verändert */
g_signal_connect( spin[0], "value-changed",
G_CALLBACK(spin_auswerten), NULL);
g_signal_connect( spin[1], "value-changed",
G_CALLBACK(spin_auswerten), NULL);
/* Großes Packen der Widget beginnt */
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(label[0]),
0, 1, 0, 1,
GTK_FILL, GTK_FILL, 0, 0 );
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(entry[0]),
1, 2, 0, 1,
GTK_FILL, GTK_FILL, 0, 0 );
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(label[1]),
0, 1, 2, 3,
GTK_FILL, GTK_FILL, 0, 0);
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(entry[1]),
1, 2, 2, 3,
GTK_FILL, GTK_FILL, 0, 0);
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(label[2]),
0, 1, 4, 5,
GTK_FILL, GTK_FILL, 0, 0);
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(entry[2]),
1, 2, 4, 5,
GTK_FILL, GTK_FILL, 0, 0);
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(hbox),
1, 2, 6, 7,
GTK_FILL, GTK_FILL, 0, 0);
gtk_box_pack_start_defaults( GTK_BOX(hbox),
GTK_WIDGET(entry_button[0]) );
gtk_box_pack_start_defaults( GTK_BOX(hbox),
GTK_WIDGET(entry_button[1]) );
gtk_box_pack_start_defaults( GTK_BOX(vbox_spin),
GTK_WIDGET(hsep) );
gtk_box_pack_start_defaults( GTK_BOX(vbox_spin),
GTK_WIDGET(spin[0]) );
gtk_box_pack_start_defaults( GTK_BOX(vbox_spin),
GTK_WIDGET(spin[1]) );
gtk_table_attach ( GTK_TABLE (table), GTK_WIDGET(vbox_spin),
1, 2, 7, 8,
GTK_FILL, GTK_FILL, 0, 0);
for(i=0; i<SCALES; i++)
gtk_box_pack_start_defaults( GTK_BOX(hbox_vscale),
GTK_WIDGET(vscale[i]) );
gtk_container_add( GTK_CONTAINER( vbox ),
GTK_WIDGET( hbox_2) );
gtk_container_add( GTK_CONTAINER( hbox_2 ),
GTK_WIDGET( table ) );
gtk_container_add( GTK_CONTAINER( hbox_2 ),
GTK_WIDGET( hbox_vscale ) );
gtk_container_add( GTK_CONTAINER( win ), GTK_WIDGET( vbox ) );
/* 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 gtk5 gtk5.c `pkg-config gtk+-2.0 --cflags --libs`
$ ./gtk5
Bei der Betätigung einzelner Aktionen kann die Ausgabe auf die Konsole wie folgt aussehen:
...
Schieberegler Auswertung:
Regler 1 : -67,3
Regler 2 : -13,9
Regler 3 : -24,3
Zahlenfelder Auswertung:
Regler 1 : 22,5
Regler 2 : 14,7
Zahlenfelder Auswertung:
Regler 1 : 22,5
Regler 2 : 14,7
Entry-Feld Auswertung:
Name, Vorname : Wolf, Jürgen
Strasse, Hausnr. : Musterstrasse 1
Ort, PLZ : Musterdorf, 666666
---------------------------
...
15.9.1 Textfelder – GtkEntry
Für einfache einzeilige Texteingaben wie z. B. bei einer Passwortabfrage eignet sich das Textfeld-Widget GtkEntry (Typenkennung: GTK_TYPE_ENTRY). Standardmäßig liefert dieses Widget ein eigenes Kontextmenü mit, das, neben den gewöhnlichen Funktionen auf eine Zwischenablage zuzugreifen (Ausschneiden, Kopieren, Einfügen), auch die Eingabe von Unicode-Steuerzeichen unterstützt. Auch die Erstellung und das Packen des Widgets gestalten sich wieder recht einfach, und es kann neben den verwendeten Eigenschaften im Beispiel noch folgende weitere Eigenschaften beinhalten:
Tabelle 15.15
Eigenschaften für GtkEntry (GTK_TYPE_ENTRY)
Eigenschaft
|
Datentyp
|
Bedeutung
|
"activates-default"
|
gboolean
|
Bei TRUE kann ein Vorgabe-Widget, meistens ein Button, verwendet werden, das bei Druck auf die (ENTER)-Taste aktiviert wird.
|
"cursor-position"
|
gint
|
(nur lesbar) Position des Cursors im Feld, beginnend bei 0 vor dem ersten Zeichen
|
"editable"
|
gboolean
|
Darf Text verändert werden? (TRUE=Ja; FALSE=Nein)
|
"has-frame"
|
gboolean
|
Bei TRUE bekommt das Textfeld einen Reliefrahmen.
|
"max-length"
|
gint
|
Maximale Länge des Feldinhaltes in Zeichen (0 = unbegrenzte Länge)
|
"scroll-offset"
|
gint
|
(nur lesbar) Die Anzahl Pixel (!), womit der Textinhalt im Feld nach links gerollt ist.
|
"selection-bound"
|
gint
|
(nur lesbar) Bei markiertem Text werden hier die einzelnen Zeichen vom Anfang bis zum Ende der markierten Position gezählt und zurückgegeben.
|
"text"
|
gchararray
|
Vorgegebener Text, der beim Anzeigen des Widgets im Entry-Feld stehen soll.
|
"visibility"
|
gboolean
|
Bei FALSE kann hier eine passwortabfrage-typische Eingabe gemacht werden – sprich, der Text ist bei der Eingabe nicht ablesbar und wird meistens durch ein Sternchen versehen. Dies kann aber mit der Eigenschaft "invisible-char" verändert werden.
|
"invisible-char"
|
guint
|
Das Zeichen, das verwendet werden soll, wenn visibility auf FALSE gesetzt wird.
|
"width-chars"
|
gint
|
Breite des Textfeldes in Zeichen
|
GtkEntry kann auch eine Reihe von Signalen emittieren. Die wichtigsten Signale sind:
Tabelle 15.16
Mögliche Signale für GtkEntry
Signal
|
Bedeutung
|
"changed"
|
Der Inhalt des Textfeldes wurde verändert.
|
"activate"
|
Wird emittiert, wenn die (ENTER)-Taste im Textfeld gedrückt wurde.
|
"copy-clipboard"
|
Wird beim Kopieren eines Textes aus dem Textfeld emittiert.
|
"cut-clipboard"
|
Wird beim Ausschneiden eines Textes aus dem Textfeld emittiert.
|
"paste-clipboard"
|
Wird beim Einfügen eines Textes aus der Zwischenablage emittiert.
|
15.9.2 Schieberegler – GtkScale
Die Schieberegler sind eine abgeleitete Klasse von GtkRange (Typenkennung: GTK_TYPE_RANGE), einem Rollbalken. Sie können hiermit entweder einen vertikalen Schieberegler (GtkVScale; Typenkennung: GTK_TYPE_VSCALE) oder einen horizontalen Schieberegler (GtkHScale; Typenkennung: GTK_TYPE_HSCALE) erzeugen. Das Wichtigste bei einem Schieberegler ist wohl die Eigenschaft der Stellgröße adjustment, die Sie bei der Erzeugung mit angeben müssen. Folgende Eigenschaften können Sie für einen solchen Schieberegler setzen bzw. erfragen:
Tabelle 15.17
Eigenschaften für GtkVScale und GtkHScale
Eigenschaft
|
Datentyp
|
Bedeutung
|
"digits"
|
gint
|
Anzahl der Nachkommastellen
|
"draw-value"
|
gboolean
|
Bei TRUE wird der Wert neben dem Schieberegler angezeigt.
|
"value-pos"
|
GtkPositionType
|
Hier kann angegeben werden, wo der Wert beim Schieberegler angezeigt werden soll.
GTK_POS_LEFT = links
GTK_POS_RIGHT = rechts
GTK_POS_TOP = darüber
GTK_POS_BOTTOM = darunter
|
"adjustment"
|
GtkAdjustment
|
Die Stellgröße GtkAdjustment des Schiebereglers
|
Wichtige Signale, die ein Schieberegler emittieren kann, wären:
Tabelle 15.18
Mögliche Signale für GtkVScale und GtkHScale
Signal
|
Bedeutung
|
"adjust-bounds"
|
Der Schieberegler wurde verändert.
|
"move-slider"
|
Der Schieberegler wurde mit einem entsprechenden Tastendruck (z. B. Pfeil-nach-oben) verändert.
|
"value-changed"
|
Der Wert des Schiebereglers hat sich verändert.
|
15.9.3 Zahlenfelder – GtkSpinButton
Die Zahlenfelder GtkSpinButton (Typenkennung: GTK_TYPE_SPIN_BUTTON) sind eine Unterklasse des Widgets GtkEntry, so dass Sie hierbei auch alle Signale und Eigenschaften verwenden können, die Sie bei den Textfeldern kennen gelernt haben. Abgesehen davon ist die Erstellung von Zahlenfeldern ähnlich wie bei einem Schieberegler. Also, auch bei den Zahlenfeldern wird die Eigenschaft der Stellgröße unbedingt benötigt. Folgende Eigenschaften lassen sich bei den Zahlenfeldern verwenden:
Tabelle 15.19
Eigenschaften für GtkSpinButton (GTK_TYPE_SPIN_BUTTON)
Eigenschaften
|
Datentyp
|
Bedeutung
|
"adjustment"
|
GtkAdjustment
|
Die Stellgröße GtkAdjustment des Schiebereglers
|
"climb-rate"
|
gdouble
|
Hier wird die Rate eingetragen, um wie viel der Wert zu- bzw. abnimmt, wenn der Schrittschalter länger gedrückt wurde.
|
"digits"
|
guint
|
Die Anzahl der Nachkommastellen
|
"numeric"
|
gboolean
|
Bei FALSE werden nicht nummerische (!) Zahlen verwendet.
|
"snap-to-ticks"
|
gboolean
|
Bei TRUE werden von Hand eingetragene Werte auf die nächste Schrittweite gerundet.
|
"value"
|
gdouble
|
Wird für den Zugriff auf den aktuellen Wert benötigt
|
"wrap"
|
gboolean
|
Mit TRUE wird ein zyklisches Zahlenfeld erzeugt, das beim Erreichen des höchsten Wertes zum niedrigsten Wert umschlägt.
|
Neben den Signalen von GtkEntry, die für GtkSpinButton verwendet werden können, steht Ihnen auch das Signal value-changed zur Verfügung, das emittiert wird, wenn sich das Zahlenfeld verändert hat.
15.9.4 Einstellungen – GtkAdjustment
Im Beispiel wurde zweimal das Widget GtkAdjustment (Typenkennung: GTK_TYPE_ADJUSTMENT) für GtkSpinButton und GtkScale verwendet. Neben diesen beiden Widgets werden Stellgrößen auch gerne als Verbindung zwischen rollbaren Flächen und Rollbalken verwendet.
Erzeugt wird eine solche Stellgröße mit der Funktion gtk_adjustment_new(). Da es für GtkAdjustment keine Eigenschaften gibt, werden zum Abfragen und Setzen von bestimmten Größen die Funktionen gtk_adjustment_set_value() und gtk_adjustment_get_value() verwendet. Hierzu die Syntax der Funktionen:
GtkObject* gtk_adjustment_new ( gdouble value,
gdouble lower,
gdouble upper,
gdouble step_increment,
gdouble page_increment,
gdouble page_size );
gdouble gtk_adjustment_get_value ( GtkAdjustment *adjustment);
void gtk_adjustment_set_value ( GtkAdjustment *adjustment,
gdouble value );
Das erste Argument value der Funktion gtk_adjustment_new() entspricht dem anfänglichen Wert der Stellgröße, wenn das Widget erzeugt und angezeigt wird. Mit den Argumenten zwei und drei geben Sie den minimalen (lower) und maximalen (upper) Wert der Stellgröße an. Im Beispiel betrug dieser Wert –100 bis +100. Mit step_increment geben Sie die Schrittweite an, um die sich der Wert minimal verändert, wenn die Stellgröße durch die Maus bzw. durch die Tastatur (Pfeiltaste) verändert wird. Mit dem Argument page_increment geben Sie die maximale Schrittweite an, um die der Wert verändert wird, wenn Sie mit der Maus in der freien Fläche eines z. B. Schiebereglers klicken. Mit dem letzten Argument können Sie noch die Seitengröße angeben. Dies ist nur dann sinnvoll, wenn die Stellgröße mit der Größe eines Reglers gekoppelt ist. In diesem Fall stellt dieser Wert dann den Wert für die Größe des Schiebers dar. Bei Schiebereglern wird hierfür gewöhnlich 0.0 angegeben.
Mit gtk_adjustment_get_value() können Sie den Wert der aktuellen Stellgröße abfragen, und mit gtk_adjustment_set_value() können Sie hingegen einen neuen Wert dafür setzen. Natürlich können Sie auch während der Ausführung die minimale und maximale Stellgröße (Argument Nr. zwei und drei bei gtk_adjustment_new()) mit der Funktion gtk_adjustment_clamp_page() verändern. Sofern Sie allerdings einen Wert wie die Schrittweite oder Seitengröße von GtkAdjustment verändern, müssen Sie die Funktion gtk_adjustment_changed() aufrufen, um der Anwendung mitzuteilen, dass Sie die Parameter des Widgets verändert haben.
void gtk_adjustment_clamp_page ( GtkAdjustment *adjustment,
gdouble lower,
gdouble upper );
Ein GtkAdjustment-Widget kann zwei Signale emittieren:
Tabelle 15.20
Signale für GtkAdjustment
Signal
|
Bedeutung
|
"changed"
|
Die Werte des Widgets selbst haben sich verändert, wie Schrittweite oder Seitengröße (z. B. mit gtk_adjustment_clamp_page()).
|
"value-changed"
|
Der eigentliche Wert der Stellgröße hat sich verändert.
|
15.9.5 GtkEditable
GtkEditable ist eine Unterklasse des Widgets GtkEntry und stammt noch aus der älteren Zeit von GTK+. Es ist nur noch aus Kompatibilitätsgründen vorhanden, und somit belasse ich es auch hiermit und gebe diesem Widget den Stempel »veraltet«.
|