Sehr Umfangreiche Webseite zum Programmieren in C Perl CGI, Skripting, Linux, Systemprogrammierung C C++ C/C++ ANSI C Linux Windows GUI gtk gtk+ Gimp Toolkit Fenster Signale Callbacks Container GUI gtk gtk+ Gimp Toolkit Fenster Signale Callbacks Container Alles in einem Container verpacken

Packing Widgets (vertiakl und horizontal)           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Nun haben Sie im Kapitel zuvor das Konzept von GTK kennen gelernt. Sie haben auch zuvor folgenden Code gesehen ...

gtk_container_add(GTK_CONTAINER(fenster), button);

Damit wird dem Widget fenster das Widget button zugeordnet. Genauer wir haben den Button in den Container des Fensters zugeordnet. Was ist aber nun ein Container? Ein Container ist nichts anderes als ein Widget, welches ein anderes Widget enthält. Eine Kiste wo man alles reinlegen kann, wenn Sie so wollen.

Toll werden Sie denken, einfach alle neuen Widget in den Container und dann anzeigen. Nur würde ein Konstrukt wie ...

gtk_container_add(GTK_CONTAINER(fenster), button1);
gtk_container_add(GTK_CONTAINER(fenster), button2);

... keine zwei Buttons im Fenster anzeigen, wie wahrscheinlich vermutet. Das liegt daran, dass in GTK pro Container nur ein Widget enthalten sein darf. Beispielsweise können Sie dem Widget Fenster einen Button zuordnen und dem Widget Button können Sie wiederum ein Label für die Beschriftung zuordnen. Wie aber können wir einen zweiten Button anzeigen?

Dafür gibt es in GTK zum Glück so etwas wie einen Container in dem wir mehrer Widgets packen können. Also so etwas wie eine Grabbelbox, die wir als Kind hatten und beim Aufräumen alles reingeschmissen haben. Für einen solchen Fall gibt es zwei Arten von Container ...

Wir wollen uns zuerst die Packing Widgets (Packing Boxes) ansehen.

Vertikal Packing Widgets
Zuerst wollen wir den Syntax der Funktion ansehen, mit der wir die neuen Widgets vertikal anordnen können ...

GtkWidget *gtk_vbox_new(gboolen homogeneous, gint spacing);

Für den Parameter homogeneous können Sie folgendes angeben ...

Mit spacing legen Sie den vertikalen Abstand der einzelnen Widgets fest.

Bis jetzt haben wir aber erst eine vertikal Box konstruiert. Nun benötigen wir noch eine Funktion mit der wir die einzelnen Widgets in diese Box packen können. Dies erledigen wir mit der Funktion ...

void gtk_box_pack_start(GtkBox *box, GtkWidget *child,
                        gboolen expand, gboolen fill, gint padding);

box ist der Container den wir mit der Funktion gtk_vbox_new() erzeugt haben. Darin packen wir nun ein neues Widget child. Die nächsten drei Parameter, beeinflussen die Darstellung der Box. Für den Parameter expand gilt folgendes ...

Für den Parameter fill gilt folgendes ...

Mit padding bestimmen Sie den Abstand des Widgets zum Nachbarn. Bitte beachten Sie, dass mit der Funktion gtk_box_pack_start, das neue Widget oben über das zuletzt eingefügte Widget gepackt wird.

Wollen Sie das neue Widget unten vom zuletzt Hinzugefügten packen, verwenden Sie bitte die folgende Funktion ...

void gtk_box_pack_end(GtkBox *box, GtkWidget *child,
                      gboolen expand, gboolen fill, gint padding);

Die Parameter sind und haben die selbe Bedeutung wie bei der Funktion gtk_box_pack_start().

Nun wollen wir uns natürlich dazu wieder ein Programmbeispiel ansehen ...

#include <gtk/gtk.h>

void ende_cb(GtkObject *object)
{
 gtk_main_quit();
}


int main(int argc, char **argv)
{
 GtkWidget *fenster;
 GtkWidget *button1, *button2, *button3, *button_quit;
 GtkWidget *box;
 /*Gtk initialisieren*/
 gtk_init(&argc, &argv);
 /*Ein neues Fenster erstellen*/
 fenster = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 /*Buttons erstellen*/
 button1  = gtk_button_new_with_label("Knopf 1");
 button2  = gtk_button_new_with_label("Knopf 2");
 button3  = gtk_button_new_with_label("Knopf 3");
 button_quit  = gtk_button_new_with_label("Ende");
 /*Neue Box erstellen*/
 box = gtk_vbox_new(FALSE,0);

 /*Signale registrieren*/
 gtk_signal_connect_object(GTK_OBJECT(button_quit), "clicked",
                           GTK_SIGNAL_FUNC(gtk_main_quit), GTK_OBJECT(fenster));
 /*Fenstertitel*/
 gtk_window_set_title(GTK_WINDOW(fenster), "Vertikale Box");
 /*Fensterposition*/
 gtk_window_set_position(GTK_WINDOW(fenster),GTK_WIN_POS_CENTER);

 gtk_container_set_border_width(GTK_CONTAINER(fenster),25);

 /*Nun alles rein in die Box....*/
 gtk_box_pack_start(GTK_BOX(box), button1, FALSE, FALSE, 0);
 gtk_box_pack_start(GTK_BOX(box), button2, FALSE, FALSE, 0);
 gtk_box_pack_start(GTK_BOX(box), button3, FALSE, FALSE, 0);
 gtk_box_pack_start(GTK_BOX(box), button_quit, FALSE, FALSE, 20);


 gtk_container_add(GTK_CONTAINER(fenster),box);

 /*Zeigs uns.....*/
 gtk_widget_show_all(fenster);

 gtk_main();

 return 0;
}

Und so ähnlich könnte es aussehen ...

Natürlich sollten Sie nicht vergessen, die box am Ende auch in den Container fenster zu zuordnen ...

gtk_container_add(GTK_CONTAINER(fenster),box);

Sie können ja gerne an diesem Programm und seinen Optionen herumspielen.

Horizontales Packing Widget

Jetzt wollen wir sehen wie wir das ganze in eine horizontale Box packen können. Zuerst die Funktion mit der wir eine solche Box erzeugen ...

GtkWidget *gtk_hbox_new(gboolen homogeneous, gint spacing);

Auch hier haben die Paramter dieselbe Bedeutung, wie schon bei der Funktion gtk_vbox_new().

Für den Paramter homogeneous können Sie angeben ...

Mit spacing legen Sie den vertikalen Abstand der einzelnen Widgets fest.

Und natürlich gilt auch hier dasselbe mit dem packen in die Box mit den Funtkionen gtk_box_pack_start() und gtk_box_pack_end(). Nur das bei gtk_box_pack_start() das neue Widget links neben dem zuletzt eingefügtem Widget kommt. Bei gtk_box_pack_end() passiert logischerweise das Gegenteil!

Nun wollen wir uns das Beispiel dazu ansehen ...

#include <gtk/gtk.h>

void ende_cb(GtkObject *object)
{
 gtk_main_quit();
}

int main(int argc, char **argv)
{
 GtkWidget *fenster;
 GtkWidget *button1, *button2, *button3, *button_quit;
 GtkWidget *box1, *box2;
 /*Gtk initialisieren*/
 gtk_init(&argc, &argv);
 /*Ein neues Fenster erstellen*/
 fenster = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 /*Buttons erstellen*/
 button1  = gtk_button_new_with_label("Knopf 1");
 button2  = gtk_button_new_with_label("Knopf 2");
 button3  = gtk_button_new_with_label("Knopf 3");
 button_quit  = gtk_button_new_with_label("Ende");
 /*Neue Box erstellen*/
 box1 = gtk_hbox_new(FALSE,0);
 box2 = gtk_vbox_new(FALSE,0);

 /*Signale registrieren*/
 gtk_signal_connect_object(GTK_OBJECT(button_quit), "clicked",
                           GTK_SIGNAL_FUNC(gtk_main_quit), GTK_OBJECT(fenster));
 /*Fenstertitel*/
 gtk_window_set_title(GTK_WINDOW(fenster), "Horizontale Box");
 /*Fensterposition*/
 gtk_window_set_position(GTK_WINDOW(fenster),GTK_WIN_POS_CENTER);

 gtk_container_set_border_width(GTK_CONTAINER(fenster),35);

 /*Nun alles rein in die Box....*/
 gtk_box_pack_start(GTK_BOX(box1), button1, FALSE, FALSE, 0);
 gtk_box_pack_start(GTK_BOX(box1), button2, FALSE, FALSE, 0);
 gtk_box_pack_start(GTK_BOX(box1), button3, FALSE, FALSE, 0);
 gtk_box_pack_start(GTK_BOX(box2), box1, FALSE,FALSE, 20);
 gtk_box_pack_start(GTK_BOX(box2), button_quit, FALSE, FALSE, 0);

 gtk_container_add(GTK_CONTAINER(fenster),box2);

 /*Zeigs uns.....*/
 gtk_widget_show_all(fenster);

 gtk_main();

 return 0;
}

Und so könnte es aussehen ...

Ich habe bei diesem Beispiel gleichzeitig eine Horizontale und Vertikale Box verwendet. In der Zeile ...

gtk_box_pack_start(GTK_BOX(box2), box1, FALSE,FALSE, 20);

... können Sie sehen, dass Boxen auch in Boxen gepackt werden können. Ich denke mal das Programm läßt sich recht einfach nachvollziehen.

Tabellarische Packing Widgets           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Das Packing Widget funktioniert im Prinzip genauso wie bei den vertikalen bzw. horizontalen Packet Widgets. Nur geben wir hier für das Packen eines Widgets in die Box, x/y-Koordinaten an. Man kann sich das ganze wie bei einem Tabellenkalkulations-Programm vorstellen. Sie erzeugen ein Tabelle mit einer bestimmten Anzahl von Reihen und Spalten. Mit Hilfe der x/y Koordinaten geben Sie die Reihe und Spalte an wo Sie das Widget platzieren wollen.

Zuerst wollen wir uns den Syntax der Funktion ansehen, mit der wir eine neue Tabelle erzeugen können ...

GtkWidget *gtk_table_new(quint rows, quint columns, gboolen homogeneous);

Mit dieser Funktion legen wir eine Tabelle mit rows Reihen und columns Spalten an. Für die Variable homogeneous können sie folgendes angeben ...

Nun benötigen Sie noch die Funktion, mit der Sie einzelnen Widgets in die Tabelle packen können ...

void gtk_table_attach_defaults(GtkTable *table, GtkWidget *widget,
                               quint left_attach, quint right_attach,
                               quint top_attach, quint bottom_attach);

Mit dieser Funktion packen wir unser Widget in die Tabelle. Die Koordinaten für die Spalte ist von links -> left_attach bis rechts -> right_attach. Und die Koordinaten der Reihe ist von oben -> top_attach bis unten -> bottom_attach.

Nehmen wir z.B. mal an, wir erzeugen eine 3x2 Tabelle ...

table = gtk_table_new(3,2,TRUE);

Somit ergibt sich folgendes Bild ...

Wollen Sie nun ein Widget in dieser Tabelle links oben an der Ecke einfügen, müssen Sie dies folgendermaßen machen ...

gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1, 0,1);

Somit ergibt sich folgendes Bild ...

Nun wenn Sie ein weiteres Widget links unten zur Tabelle hinzufügen wollen schreiben Sie folgende Koordinaten ...

gtk_table_attach_defaults(GTK_TABLE(table), button2, 0,1, 1,2);

Ich denke mal Sie haben verstanden, wie die Koordinaten zu verwenden sind. Für rechts unten müssten sie folgende Koordinaten verwenden ...

gtk_table_attach_defaults(GTK_TABLE(table), button2, 2,3, 1,2);

Nun die Funktionsendung _defaults sagt uns schon, dass es sich dabei um ein packen in der Defaulteinstellung ohne irgendewelche Optionen handelt. Dann stellt sich wohl die Frage wie die Funktion aussieht, mit der wir die Eigenschaften der einzelnen Tabellen-Zellen beeinflussen können ...

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

Hier sind noch vier weiter Parameter hinzugekommen. Für die Parameter gtkAttachOptions können Sie folgende Werte angeben ...

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

Mit xpadding und ypadding können Sie den Abstand in Pixeln vom Nachbarn rechts/links bzw. oben/unten einstellen.

Am besten ich demonstriere Ihnen die Funktion gtk_table_attach() anhand eines Beispiels ...

#include <gtk/gtk.h>

void ende_cb(GtkObject *object)
{
 gtk_main_quit();
}


int main(int argc, char **argv)
{
 GtkWidget *fenster;
 GtkWidget *button1, *button2, *button3;
 GtkWidget *table;
 /*Gtk initialisieren*/
 gtk_init(&argc, &argv);
 /*Ein neues Fenster erstellen*/
 fenster = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 /*Buttons erstellen*/
 button1  = gtk_button_new_with_label("Kein schrumpfen\nkein expandieren");
 button2  = gtk_button_new_with_label("Expandiert und schrumpft\nvertikal");
 button3  = gtk_button_new_with_label("Expandiert und schrumpft\n in beide Seiten");
 /*Tabelle erstellen...*/
 table = gtk_table_new(2,2,FALSE);

 /*Signale registrieren*/
 gtk_signal_connect(GTK_OBJECT(fenster), "delete_event",
                    GTK_SIGNAL_FUNC(ende_cb), NULL);
 /*Fenstertitel*/
 gtk_window_set_title(GTK_WINDOW(fenster), "Tabellendemo");
 /*Fensterposition*/
 gtk_window_set_position(GTK_WINDOW(fenster),GTK_WIN_POS_CENTER);

 gtk_container_set_border_width(GTK_CONTAINER(fenster),15);

 /*Inhalt der Tabelle mit verschiedenen Optionen erstellen....*/
 gtk_table_attach(GTK_TABLE(table),button1, 0,1, 0,1,
                  GTK_FILL, GTK_FILL, 0,0);
 gtk_table_attach(GTK_TABLE(table), button2, 0,1, 1,2,
                  GTK_FILL, GTK_FILL|GTK_EXPAND|GTK_SHRINK,0,0);
 gtk_table_attach(GTK_TABLE(table), button3, 1,2, 1,2,
                  GTK_FILL|GTK_EXPAND|GTK_SHRINK,GTK_FILL|GTK_EXPAND|GTK_SHRINK,
                  0,0);


 gtk_container_add(GTK_CONTAINER(fenster),table);

 /*Zeigs uns.....*/
 gtk_widget_show_all(fenster);

 gtk_main();

 return 0;
}

Und so könnte es aussehen ...

Nun wollen wir unser Tabellendemo auch demonstrieren. Zuerst wollen wir unser Fenster vertikal vergrößern ...

Jetzt wollen wir es noch horizontal vergrößern ...

Ich empfehle Ihnen nun dazu selbst mit den Optionen herumzuspielen.

Ich möchte Ihnen nun noch ein paar Funktionen nennen, die Sie mit Packing Tabellen verwenden können.

void gtk_table_resize(GtkTable *table, quint rows, quint columns);

Damit können Sie die Größe einer bereits erzeugten Tabelle um rows Reihen und columns Spalten ändern.

void gtk_table_set_row_spacing(GtkTable *table, quint rows, quint spacing);
void gtk_table_set_col_spacing(GtkTable *table, quint cols, quint spacing);

Damit können Sie den Abstand zwischen einzelnen Widgets in der Reihe (row) bzw. Spalte (col) ändern.

void gtk_table_set_row_spacings(GtkTable *table, quint spacing);
void gtk_table_set_col_spacings(GtkTable *table, quint spacing);

Damit können Sie die Abstände einzelner Widgets auf alle Reihen bzw. Spalten ändern.

Weiter mit Widgets erzeugen