Vous avez probablement noté certaines choses qui nécessitent des
explications dans les exemples précédents. les gint, gchar,
etc. que vous avez pu voir sont des redéfinitions de int et
char, respectivement. Leur raison d'être est de s'affranchir des
dépendances ennuyeuses concernant la taille des types de données
simples lorsqu'on réalise des calculs. Un bon exemple est gint32
qui désignera un entier codé sur 32 bits pour toutes les plateformes,
que ce soit une station Alpha 64 bits ou un PC i386 32 bits. Les
redéfinitions de type sont très simples et intuitives. Elles sont
toutes décrites dans le fichier glib/glib.h (qui est inclus
par gtk.h).
On notera aussi la possibilité d'utiliser un GtkWidget lorsque la
fonction attend un GtkObject. GTK possède une architecture
orientée objet, et un widget est un objet.
Vous avez remarqué que le valeur de retour est de type gint ? Il
s'agit d'un marqueur qui identifie votre fonction de rappel. Comme on
le disait plus haut, on peut avoir autant de fonctions de rappel que
l'on a besoin, par signal et par objet, et chacune sera exécutée à son
tour, dans l'ordre dans lequel elle a été attachée. Ce marqueur vous
permet d'ôter ce rappel de la liste en faisant &;:
Ainsi, en passant le widget dont on veut supprimer le gestionnaire et
le marqueur ou identificateur retourné par l'une des fonctions
signal_connect, on peut déconnecter un gestionnaire de signal.
Une autre fonction permettant de supprimer tous les gestionnaires de
signaux pour un objet est :
gtk_signal_handlers_destroy (GtkObject *object);
Cet appel n'a pas trop besoin d'explications. Il ôte simplement tous
les gestionnaires de signaux de l'objet passé en paramètre.
Étudions une version légèrement améliorée avec de meilleurs exemples
de fonctions de rappel. Ceci permettra aussi d'introduire le sujet
suivant : le placement des wigdets.
#include <gtk/gtk.h>
/* Notre nouveau rappel amélioré. La donnée passée à cette fonction est
* imprimée sur stdout. */
void rappel (GtkWidget *widget, gpointer *data)
{
g_print ("Re-Bonjour - %s a été pressé\n", (char *) data);
}
/* Un autre rappel */
void delete_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
{
gtk_main_quit ();
}
int main (int argc, char *argv[])
{
/* GtkWidget est le type pour déclarer les widgets */
GtkWidget *window;
GtkWidget *button;
GtkWidget *box1;
/* Cette fonction est appelée dans toutes les applications GTK.
* Les paramètre passés en ligne de commande sont analysés et
* retournés à l'application. */
gtk_init (&argc, &argv);
/* Création d'une nouvelle fenêtre. */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/* Nouvel appel qui intitule notre nouvelle fenêtre
* "Salut les boutons !" */
gtk_window_set_title (GTK_WINDOW (window), "Salut les boutons !");
/* Configuration d'un gestionnaire pour "delete_event" afin de
* quitter immédiatement GTK. */
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (delete_event), NULL);
/* Configuration de la largeur du contour de la fenêtre. */
gtk_container_border_width (GTK_CONTAINER (window), 10);
/* Création d'une boîte pour y placer les widgets.
* Ceci est décrit en détails plus loin dans la section
* « placement ». La boîte n'est pas matérialisée, elle est juste
* utilisée comme moyen d'arranger les widgets. */
box1 = gtk_hbox_new(FALSE, 0);
/* On met la boîte dans la fenêtre principale. */
gtk_container_add (GTK_CONTAINER (window), box1);
/* On crée un nouveau bouton portant le label « Bouton 1 ». */
button = gtk_button_new_with_label ("Bouton 1");
/* Lorsque le bouton est cliqué, on appelle la fonction « rappel »
* avec un pointeur sur la chaîne « Bouton 1 » comme paramètre. */
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (rappel), (gpointer) "Bouton 1");
/* Au lieu d'utiliser gtk_container_add, on place ce bouton dans
* la boîte invisible qui a été placée dans la fenêtre. */
gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
/* N'oubliez jamais cette étape qui indique à GTK que la configuration
* de ce bouton est terminée et qu'il peut être affiché. */
gtk_widget_show(button);
/* On fait la même chose pour créer un deuxième bouton. */
button = gtk_button_new_with_label ("Bouton 2");
/* On appelle la même fonction de rappel avec un paramètre différent,
* un pointeur sur la chaîne « Bouton 2 ». */
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (rappel), (gpointer) "Bouton 2");
gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
/* L'ordre dans lequel on affiche les boutons n'est pas vraiment
* important, mais il est préférable d'afficher la fenêtre en dernier
* pour qu'elle surgisse d'un coup. */
gtk_widget_show(button);
gtk_widget_show(box1);
gtk_widget_show (window);
/* Le reste est dans gtk_main et on attend que la fête commence ! */
gtk_main ();
return 0;
}
Compilez ce programme en utilisant les mêmes paramètres que pour
l'exemple précédent. Vous remarquerez que, maintenant, il est plus
difficile de quitter le programme : vous devez utiliser le
gestionnaire de fenêtres ou une commande shell pour le détruire. Un
bon exercice pour le lecteur serait d'insérer un troisième bouton «
Quitter » qui permettrait de sortir du programme. Vous pouvez aussi
jouer avec les options de gtk_box_pack_start() en lisant la
section suivante. Essayez de redimensionner la fenêtre, et observez
son comportement.
Juste une remarque : il existe une autre constante utilisable
avec gtk_window_new() - GTK_WINDOW_DIALOG. Ceci permet
d'interagir de façon un peu différente avec le gestionnaire de
fenêtres et doit être utilisé pour les fenêtres temporaires comme les
boîtes de dialogue, par exemple.