Création de signaux pour vos widgets GTK+Date de publication : 27/09/2006
Par
Franck.H (Mon blog) (retour aux articles)
Création d'un signal pour un widget personnel !
I. Introduction II. Pré-requis III. Les signaux III-A. Un bref rappel III-B. Plan de route de notre signal IV. Modification du code source IV-A. Le fichier gtkled.h IV-B. Le fichier gtkled.c IV-C. Signature de notre callback V. Conclusion VI. Code source complet VII. Remerciements I. Introduction
Dans le cours précédent Créer son widget GTK+ en Langage C (qu'il convient de lire avant de suivre ce tutoriel), nous avons créé un widget à partir de rien ; en fait plus ou moins car on part tout de même d'un GtkWidget.
Un widget personnel c'est bien, dans notre cas, GtkLed nous permet d'afficher Deux états: Eteint et Allumé ... Tout ceci est bien me direz-vous mais il faut passer par un GtkButton pour pouvoir lui changer l'état courant.
Dans ce tutoriel je vais vous expliquer comment créer un signal personnel qui nous permettra de changer l'état de notre GtkLed par un simple clic sur ce widget !
Si vous avez des questions concernant GTK+ l'équipe de developpez.com sera ravie de vous aider, rendez-vous sur le Forum GTK+ de developpez.com
II. Pré-requis
III. Les signauxIII-A. Un bref rappel
Si vous savez ce que sont exactement les signaux GTK+ vous pouvez sauter ce chapitre et pour les autres...
Les signaux GTK+ sont plus ou moins identiques aux messages d'événements de l'API Win32 ; Si vous avez un peu étudié cette API, vous savez que ce sont des constantes symboliques représentant des entiers (non signés, longs ... c'est suivant l'API en fait). Ces constantes permettent de gérer un événement utilisateur (clic sur un bouton par exemple) ou des événements du système lui même (dessin du contenu d'une fenêtre).
Avec GTK+, nous nous référons aux signaux par le biais d'une chaîne constante mais les signaux eux-mêmes n'en restent pas moins que des entiers ; pour être plus exacte, ce sont des guint (unsigned int, entiers non signés).
Il faut savoir que les signaux GTK+ sont internes à cette bibliothèque mais sont reliés directement avec les signaux du système sous-jacent ; les signaux internes au noyau d'un système passent par des tubes (pipes) comme c'est le cas des signaux du serveur X11 (serveur graphique de Linux).
La différence essentielle avec le traitement des événements avec GTK+ (par rapport à l'API Win32 par exemple), est que nous pouvons lier chaque signal à une fonction unique ce qui offre l'avantage de découper le comportement de l'application, cela rend également le code plus lisible alors que sous l'API Win32 nous n'avons qu'une unique fonction qui récupère tous les messages (utilisateurs et système).
Il nous suffit d'utiliser la fonction:
pour lier une fonction à un signal GTK+. Il est à noter également que chaque signal GTK+ possède un comportement par défaut qui la plupart du temps est de rien faire, sauf pour certains événements comme par exemple le signal expose-event qui permet de faire redessiner le widget lorsque l'API le lui demande mais, nous pouvons bien sûr redéfinir son comportement nous même en connectant ce signal avec une fonction de rappel (ou callback) personnelle !
Nous ne faisons ici que gratter la surface et nous voyons déjà la puissance et la souplesses de la gestion des signaux de GTK+ !
III-B. Plan de route de notre signal
Comment va fonctionner notre signal ? En réalité, nous allons le faire appeler par un autre événement, voyons d'abord un petit schéma qui nous montre son cheminement:
![]()
Notre widget GtkLed héritant de GtkWidget, nous avons une pléthore de signaux à notre disposition ; nous, nous allons faire reconnaître les signaux button-press-event et button-release-event par notre widget (par défaut notre widget ne gère pas les événements utilisateurs). Sur le schéma vous pouvez voir que l'événement button-press-event est barré ! En effet, nous devons le faire intercepter par notre widget mais nous n'allons pas le gérer, nous laisserons donc ce signal à son comportement par défaut: Rien faire !
Donc comment cela va-t-il se passer ... Nous allons connecter notre widget GtkLed au signal button-release-event qu'il hérite de GtkWidget ; ce signal étant directement relié à une fonction privée gtk_led_button_release, que nous verrons plus loin dans ce cours, nous allons simplement faire déclencher notre signal swtich-state par un appel de la fonction g_signal_emit dans notre callback privé (gtk_led_button_release).
Cette façon de procéder va vous faire croire que c'est notre signal personnel qui va nous permettre de directement cliquer sur le widget alors qu'en fait c'est un autre signal qui se trouve dans GtkWidget qui va gérer le tout mais de façon transparente !
Vous me direz sans doute: Quel intérêt de faire un signal de ce genre car nous disposons déjà de fonctions pour changer l'état du widget ? En fait, c'est d'une part déjà plus intuitif et d'un autre côté, cela nous permet de faire d'autres actions relatives au changement d'état du widget sans devoir également gérer le changement de ces états !
IV. Modification du code sourceIV-A. Le fichier gtkled.h
Ouvrez le fichier gtkled.h et rendez-vous dans la structure _GtkLedClass. Ici, il nous suffit d'ajouter un pointeur de fonction pour notre signal. Ci-dessous notre structure complète:
Voilà, c'est tout pour ce fichier ! La signature des signaux sont toujours sous cette forme, une fonction qui renvoie (ou ne renvoie pas) de valeur et qui prend comme paramètre un pointeur sur le type du widget.
IV-B. Le fichier gtkled.c
Nous allons maintenant créer notre signal, nous le nommerons switch-state tout simplement, je pense que c'est un nom assez explicite donc pas la peine de donner des explications !
Commençons par créer la signature de notre fonction qui va gérer en interne le changement d'état de notre widget. Au début de la liste des fonctions statiques, ajoutez notre nouvelle fonction:
Pour notre signal, il nous faut un tableau d'entiers non signés, soit, créons-le ; à la fin de la liste des prototypes des fonctions privées, ajoutez donc ceci:
J'ai ajouté une énumération de constantes pour une question de compréhension du code source, habitude à prendre surtout si vous créez plus d'un signal. Nous déclarons ensuite simplement un tableau de guint (unsigned int) puis nous initialisons tous ses indices à la valeur zéro. Ce tableau servira en réalité à stocker l'identifiant unique de notre signal une fois créé.
Nous allons maintenant implémenter notre fonction gtk_led_button_release juste en-dessous de la fonction gtk_led_new comme suit:
Rien de bien compliqué ici ! Nous inversons l'état courant de notre widget puis nous le faisons se redessiner en appelant la fonction gtk_led_paint.
La nouveauté réside dans l'appel à la fonction g_signal_emit. En fait, nous demandons à ce que notre signal switch-state soit déclenché à partir du signal button-release-event ce qui nous permettra de faire changer l'état du widget en cliquant simplement dessus !
Nous entrons maintenant dans le vif du sujet en créant notre signal personnel. La création de notre signal va se faire dans la fonction gtk_led_class_init comme suit à la fin de la fonction:
Cette fonction peut sembler compliqué au premier abord mais il n'en est rien. Voici son prototype:
Pour nous permettre de pouvoir cliquer sur notre widget, nous devons le lier à un signal, c'est ce que nous faisons dans la fonction gtk_led_init, à la fin de la fonction:
Pour finir, nous devons donner la possibilité à notre widget d'intercepter le signal button-press-event et button-release-event ; rendez-vous pour cela dans la fonction gtk_led_realize, retrouvez la propriété attributes.event_mask puis changez-la par celle-ci:
IV-C. Signature de notre callback
Nous y arrivons, vous avez enfin le droit de connaître la signature de votre premier signal. Ici rien de nouveau, nous reprenons simplement la signature de la plupart des signaux:
Comme à l'accoutumée, vous remplacez juste user_function par un nom plus explicite lorsque vous utiliserez ce signal ... comme d'habitude vous me direz ;)
V. Conclusion
Et voilà, nous en avons fini avec ce tutoriel, j'espère qu'il vous aura bien servi et éclairci les choses !
Comme vous avez pu le voir, il n'y a vraiment rien d'insurmontable mais certaines choses sont effectivement à savoir pour pouvoir créer vos propres signaux.
VI. Code source complet
Ici, vous pouvez télécharger le code source complet du widget livré avec un programme d'exemple, ainsi que le Makefile Linux et un projet Code::Blocks version Windows: GtkLed-2.zip
VII. Remerciements
Merci à gege2061 pour ses conseils et à fearyourself pour sa relecture et correction !
|
Copyright © 2006 Franck Hecht. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.