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 Widgets Callbacks Container GUI gtk gtk+ Gimp Toolkit Widgets Callbacks Container Widgets

Widgets erzeugen           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Sie haben nun schon des öfteren gesehen, wie wir Widgets erstellet haben bzw. wie wir diese anzeigen können. Im Prinzip werden immer folgende 5 Schritte unternommen um ein Widget zu erzeugen ...

Zu Punkt 5 muss man natürlich anmerken, dass man ein Widget nicht gleich anzeigen muss, man kann es auch noch mit der Funktion gtk_widget_hide() verstecken. Hierzu der Syntax dieser beiden Funktionen ...

void gtk_widget_show(GtkWidget *widget);
void gtk_widget_hide(GtkWidget *widget);

Nun kann man natürlich anstatt, bei jedem erzeugtem Widget gtk_widget_show() bzw. gtk_widget_hide(), aufzurufen, alles mit einer Funktion anzeigen bzw. verstecken lassen ...

void gtk_widget_show_all(GtkWidget *widget);
void gtk_widget_hide_all(GtkWidget *widget);

Damit wird rekursiv die Funktion gtk_widget_show() bzw. gtk_widget_hide() auf alle Kindern-Widgets die sich im Container befinden aufgerufen.

Nun folgt ein kleiner Abschnitt bei dem Sie etwas mehr über GTK+ erfahren der aber nicht Entscheidend für das weitere Verständnis dieses Tutorials ist.

Um GTK+ zu verstehen, müssen sie das X-Window-System ein wenig verstehen. Ich gehen jetzt einfach mal davon aus, dass Sie ein wenig vom X-Window-System verstehen. Sie sollten wenigstens wissen was ein X-Server ist, das ein X Netzwerk- Transparent ist, was ein Window Manager ist usw.

X-Window ist dabei der "Boss" aller Windows (Fenster) von dem alle anderen Fenster und Libs abhängen. Ohne X-Window gäbe es auf Linux kein KDE oder GTK+. Dies soll jetzt aber nicht heißen, dass GtkWindow ein X-Window ist, sondern darauf basiert. Genauso wie unter MS-Windows die MFC-Bibliothek auf die Windowsprogrammierung (windows.h) basiert.

Der X-Server ist das Hauptfenster (root window), welcher kein Eltern-Fenster mehr hat. Somit sind die Kinder-Fenster (child window) meistens die Window Manager welche schön bunt sind, eine Titelleiste haben und auf der viele Applikationen laufen. Einfach halt das Look & Feel welches man heute kennt.

Wichtig ist auch, dass sie wissen, dass GTK+ nicht X-Window direkt anspricht, sondern die Gdk-Library, welche dazwischen liegt. Die Gdk-Lib ist also die Basis von GTK+ wenn sie zum Beispiel eine Grafik auf dem Bildschirm zeichnen wollen.

Ich will, das ganze nicht noch mehr hinausziehen, aber ich finde ein wenig Hintergrundwissen kann nicht Schaden.

Der Lebenszyklus eines Widgets           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Natürlich sollen Sie auch wissen, wie so ein Widget "überlebt". Das allozieren des Speichers und wieder freigeben, geschieht meistens Automatisch.

Wenn Sie Beispielsweise ein Widget "zerstören" wollen, rufen Sie einfach die Funktion gkt_widget_destroy() auf. Damit wird das Widget aus dem Container entfernt und der Speicher und andere Ressourcen werden freigegeben.

Hierzu der Syntax ...

void gtk_widget_destroy(GtkWidget *widget);

Und hierzu ein Programmbeispiel ...

#include <gtk/gtk.h>
#include <gtk/gtkwidget.h>

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

void weg_damit_cb(GtkWidget *widget, gpointer data)
{
 gtk_widget_destroy(widget);
}

int main(int argc, char **argv)
{
 GtkWidget *fenster;
 GtkWidget *button1, *button2;
 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("gtk_widget_destroy");
 button2  = gtk_button_new_with_label("Quit");

 /*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);
 gtk_signal_connect(GTK_OBJECT(button1), "clicked",
                    GTK_SIGNAL_FUNC(weg_damit_cb), NULL);
 gtk_signal_connect_object(GTK_OBJECT(button2), "clicked",
                           GTK_SIGNAL_FUNC(gtk_main_quit), GTK_OBJECT(fenster));
 /*Fenstertitel*/
 gtk_window_set_title(GTK_WINDOW(fenster), "gtk_widget_destroy");
 /*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_EXPAND, 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 ...

Und nach dem Klick auf dem Button gtk_widget_destroy welcher die Callback- Funktion weg_damit_cb aufruft ...

Intern besitzt jedes Widget einen Referenz-Zähler. Haben wir zum Beispiel ein Widget erzeugt, ist dieser Zähler auf 1. Wenn wir das Widget wieder aus dem Container entfernen, wird der Zähler wieder auf 0 dekrementiert. Wenn also eine Referenz den Wert 0 erreicht, ist das Widget "zerstört". Die bedeutet auch, wenn Sie ein Widget zerstören, welches viele andere Widget beinhaltet, wird dieser Inhalt auch mitzerstört. Dies sollten Sie beachten wenn Sie ein Programm schreiben und ein Widget entfernen wollen.

Nun will man manch mal ein Widget aus dem Container entfernen und es später wieder hinzufügen. Für solch einen Fall könnten Sie eine Referenz auf ein Widget einrichten mit ...

void gtk_object_ref(GtkObject *object);

Wenn Sie nun eine Widget aus dem Container entfernen, gehen sie folgendermaßen vor ...

gtk_object_ref(widget);
gtk_containter_remove(container,widget);

Wenn Sie das Widget nicht mehr benötigen, müssen Sie es un-referenzieren mit gtk_object_unref().

Sinn macht dies aber nur, wenn Sie Beispielsweise ein Widget aus einem Container entfernen und in einem anderen wieder einfügen. Wenn Sie ein Widget kurz entfernen und später wieder hinzufügen wollen, empfehle ich Ihnen die schnelleren Funktionen gtk_widget_hide() und gtk_widget_show() zu verwenden. Hier ein Beispiel wie Sie das machen können ...

#include <gtk/gtk.h>
#include <gtk/gtkwidget.h>


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


int main(int argc, char **argv)
{
 GtkWidget *fenster;
 GtkWidget *button1, *button2;
 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("Verstecke mich");
 button2  = gtk_button_new_with_label("Zeig ihn wieder");

 /*Tabelle erstellen...*/
 table = gtk_table_new(2,2,TRUE);

 /*Signale registrieren*/
 gtk_signal_connect(GTK_OBJECT(fenster), "delete_event",
                    GTK_SIGNAL_FUNC(ende_cb), NULL);
 gtk_signal_connect_object(GTK_OBJECT(button1), "clicked",
                    GTK_SIGNAL_FUNC(gtk_widget_hide), GTK_OBJECT(button1));
 gtk_signal_connect_object(GTK_OBJECT(button2), "clicked",
                    GTK_SIGNAL_FUNC(gtk_widget_show), GTK_OBJECT(button1));
 /*Fenstertitel*/
 gtk_window_set_title(GTK_WINDOW(fenster), "gtk_widget_destroy");
 /*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_defaults(GTK_TABLE(table),button1, 0,1, 0,1);
 gtk_table_attach_defaults(GTK_TABLE(table), button2, 1,2, 1,2);


 gtk_container_add(GTK_CONTAINER(fenster),table);

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

 gtk_main();

 return 0;
}

Es gibt natürlich noch eine Menge weiterer Widget Konzepte. Alle hier aufzuzählen währe zu Umfangreich. Sie finden viele dieser Widgets Funktionen in der GTK-Referenz, welche meist schon anhand des Namens eindeutig zu verstehen sind. Wir werden natürlich viele von diesen im Laufe des Tutorials noch kennen lernen.

Weiter mit Normale Buttons