Date de publication : 20 Février 2007
Nous allons étudier cette fois-ci trois nouveaux types de boutons qui dérivent du widget GtkButton (chapitre V). L'étude de ces widgets sera rapide car ils ne comportent que très peu de fonctions.
Il s'agit ici d'un bouton poussoir qui ne peut prendre que deux états : enfoncé ou relâché. Ce widget dérive de GtkButton.
Vous allez voir ici, il n'y a rien de bien compliqué vu que c'est toujours le même principe :
GtkWidget* gtk_toggle_button_new(void);
GtkWidget* gtk_toggle_button_new_with_label(const gchar* label);
GtkWidget* gtk_toggle_button_new_with_mnemonics(const gchar* label);
La première fonction crée un nouveau bouton vide, alors que la seconde ajoute du texte à l'intérieur et la troisième ajoute en plus un raccourci clavier.
Il peut être intéressant de connaître l'état du bouton pour agir en conséquence. Une fois encore, rien de plus simple on utilise la fonction :
gboolean gtk_toggle_button_get_active (GtkToggleButton *toggle_button);
Cette dernière nous renvoie TRUE
si le bouton est enfoncé
et FALSE
sinon. Afin de pouvoir utiliser le paramètre toggle_button
qui est le bouton dont on veut connaître l'état, il faut utiliser
la macro GTK_TOGGLE_BUTTON()
.
Pour modifier l'état du bouton, c'est aussi simple :
void gtk_toggle_button_set_active (GtkToggleButton *toggle_button, gboolean is_active);
Il suffit de mettre le paramètre is_active
à TRUE
si l'on veut enfoncer le bouton ou à FALSE
pour le relâcher.
Il existe cependant un troisième état qui n'est pas accessible en cliquant sur le bouton mais par une fonction spécifique. Ce troisième état, vous le connaissez sûrement. Le meilleur exemple est celui des éditeurs de texte :
Vous avez une phrase dans laquelle il y a du texte normal et du texte en gras. Si vous sélectionnez le texte en gras, le bouton permettant justement de le mettre en gras s'enfonce (en général B). Par contre si vous sélectionnez le texte normal, ce même bouton repasse à son état relâché. Venons en au troisième état, qui apparaît lorsque vous sélectionnez la phrase entière. Le bouton ne change pas d'état mais seulement d'aspect, il donne l'impression d'être inactif.
Ce changement d'aspect doit se faire manuellement, et s'effectue avec cette fonction :
void gtk_toggle_button_set_inconsistent(GtkToggleButton *toggle_button, gboolean setting);
Il suffit de mettre le paramètre setting
à TRUE
pour donner au bouton l'aspect inactif.
Et pour connaître l'aspect du bouton, il y a tout naturellement la fonction :
gboolean gtk_toggle_button_get_inconsistent(GtkToggleButton *toggle_button);
Evidemment, toutes les fonctions du widget GtkButton
sont utilisables
avec ce type de bouton.
Nous allons construire une application contenant un GtkToggleButton
qui changera d'état (bien sûr) lorsque nous cliquerons dessus,
mais aussi lorsque nous cliquerons sur un deuxième bouton (le changement
d'état entraînera la modification du label). De plus, il y aura
un troisième bouton pour changer l'aspect du bouton (idem, on change
aussi le label).
La création des widgets étant classique, nous n'allons donc pas revenir dessus.
Il va donc nous falloir trois fonctions callback. La première pour changer
le texte lorsque l'on clique sur le GtkToggleButton
, la deuxième
pour changer son état lorsque l'on clique sur le deuxième bouton,
et la troisième pour changer l'aspect.
Pour la première fonction callback, il faut intercepter le signal "toggled"
qui est émis lorsque le bouton change d'état :
g_signal_connect(G_OBJECT(pToggleBtn), "toggled", G_CALLBACK(OnToggle), NULL);
Dans cette fonction nous allons récupérer l'état du bouton ainsi que son aspect afin de changer le label en fonction des valeurs de retour.
Pour la deuxième, on interceptera le signal "clicked"
:
g_signal_connect(G_OBJECT(pEtatBtn), "clicked", G_CALLBACK(OnEtatBtn), pToggleBtn);
Lorsque l'on changera l'état du bouton toggle, le signal "toggled"
sera émis pour celui-ci et le texte se changera automatiquement.
Pour la troisième, le signal à intercepter et le même ("clicked"
)
:
g_signal_connect(G_OBJECT(pAspectBtn), "clicked", G_CALLBACK(OnAspectBtn), pToggleBtn);
Cette fois, lorsque l'on change l'aspect du bouton, le signal "toggled"
n'est pas émis et le texte ne changera donc pas. Il faut donc émettre
soit même ce signal avec la fonction :
void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
Cette fonction ne change en aucun cas l'état du bouton, elle ne fait qu'émettre le signal.
Mais le plus simple est de regarder le code source suivant.
#include <stdlib.h> #include <gtk/gtk.h> void
OnToggle(GtkWidget *pToggle, gpointer data); int main(int
argc, char **argv) gtk_init(&argc,&argv); pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); pVBox = gtk_vbox_new(TRUE, 0); /* Creation du label du
bouton */ gtk_box_pack_start(GTK_BOX(pVBox), pToggleBtn, FALSE, FALSE, 0); pEtatBtn = gtk_button_new_with_label("CHANGER
ETAT"); pAspectBtn = gtk_button_new_with_label("CHANGER
ASPECT"); gtk_widget_show_all(pWindow); /* Connexion des signaux
*/ gtk_main(); return EXIT_SUCCESS; void OnEtatBtn(GtkWidget *pWidget, gpointer
pToggle) /* Recuperation de l etat
du bouton */ /* Modification de l etat
du bouton */ void OnAspectBtn(GtkWidget *pEtatBtn, gpointer
pToggle) /* Recuperation de l aspect
du bouton */ /* Modification de l aspect
du bouton */ /* On emet le signal "toggle"
pour changer le texte du bouton */ void OnToggle(GtkWidget *pToggle, gpointer
data) /* Recuperation de l etat
du bouton */ /* Construction du label
du bouton */ /* Modification du label
du bouton */ /* Les chaines sLabel et
sLabelUtf8 n'ont plus d'utilite */ |
Résultat : |
Sous ce nom se cachent tout simplement les cases à cocher que tout le
monde connaît. Il s'agit là aussi d'un type de bouton binaire,
d'ailleurs ce widget dérive de GtkToggleButton
:
Une fois encore, la syntaxe et l'utilisation des fonctions de création restent classiques :
GtkWidget* gtk_check_button_new (void);
GtkWidget* gtk_check_button_new_with_label (const gchar *label);
GtkWidget* gtk_check_button_new_with_mnemonic(const gchar *label);
Il n'existe pas d'autres fonctions pour ce widget, il faut donc utiliser les
fonctions des widgets GtkToggleButton
et GtkButton
pour récupérer les propriétés du widget (état,
aspect, label, ...).
Nous n'allons pas ici créer de programme exemple pour ce widget car
il suffit juste de remplacer gtk_toggle_button_new_with_label
par
gtk_check_button_new_with_label
dans l'exemple précédent
pour obtenir ceci :
Nous passons maintenant au widget GtkRadioButton qui se différencie par la possibilité d'en grouper plusieurs. De ce fait, lors que par exemple nous avons un groupe de trois boutons, il n'y en a qu'un seul qui peut être actif. On pourrait très bien faire cela avec le widget GtkCheckButton mais cela serait beaucoup plus long à programmer. Dans la hiérarchie des widgets, GtkRadioButton dérive de GtkCheckButton.
Afin de grouper les boutons radio, GTK+ utilise les listes simplement chaînées de GLib. Pour créer le premier bouton radio du groupe, il faut obligatoirement passer par une de ces fonctions :
GtkWidget* gtk_radio_button_new (GSList *group);
GtkWidget* gtk_radio_button_new_with_label (GSList *group, const gchar *label);
GtkWidget* gtk_radio_button_new_with_mnemonic(GSList *group, const gchar *label);
Au moment de la création, le bouton radio est automatiquement ajouté
à la liste group
. Cependant, ce paramètre n'est pas
obligatoire. Nous pouvons très bien mettre NULL
comme valeur
et cela marchera de la même manière, sauf que nous n'aurons pas
de pointeur sur la liste. La valeur de retour de cette fonction sera aussi copiée
dans la variable data
de la liste chaînée.
Ensuite pour rajouter les autres boutons au groupe, il y a plusieurs possibilités. La première est d'utiliser une des trois fonctions précédentes mais ce n'est pas tout, car autant pour le premier bouton du groupe, il n'est pas nécessaire d'avoir une liste, autant pour les autres boutons cela devient obligatoire. Pour cela, GTK+ nous fournit une fonction qui permet d'obtenir la liste dans laquelle les boutons du groupe sont ajoutés :
GSList* gtk_radio_button_get_group(GtkRadioButton *radio_button);
Avec cette fonction, nous pouvons donc connaître la liste à laquelle appartient le bouton radio_button, ce qui va nous permettre d'ajouter de nouveau bouton au groupe. Mais là où cela se complique, c'est qu'il faut récupérer la liste avant chaque ajout de bouton avec le dernier bouton ajouté comme paramètre. Voici ce que cela donnerai pour un groupe de trois boutons :
pRadio1 = gtk_radio_button_new_with_label(NULL, "Radio
1");
pGroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(pRadio1));
pRadio2 = gtk_radio_button_new_with_label(pGroup, "Radio 2");
pGroup = gtk_radio_button_get_group(GTK_RADIO_BUTTON(pRadio2));
pRadio3 = gtk_radio_button_new_with_label(pGroup, "Radio 3");
Ce système peut donc s'avérer lourd lors de la création du groupe, surtout s'il contient un grand nombre de boutons. Heureusement, les concepteurs de GTK+ ont pensé à nous simplifier la vie en ajoutant ces trois fonctions :
GtkWidget* gtk_radio_button_new_from_widget(GtkRadioButton
*group);
GtkWidget* gtk_radio_button_new_with_label_from_widget(GtkRadioButton *group,
const gchar *label);
GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget(GtkRadioButton *group,
const gchar *label);
Cette fois group ne correspond pas à la liste mais à un des boutons du groupe. A chaque appel d'une de ces fonctions GTK+ va s'occuper de récupérer correctement la liste à laquelle appartient le bouton group et ajouter le nouveau bouton. Cela aura pour conséquence, dans le cas d'un groupe de trois boutons, de réduire le nombre de lignes de code de 5 à 3 (et oui, une ligne de code c'est une ligne de code).
Nous savons maintenant tout ce qu'il faut pour créer un groupe de GtkRadioButton.
Le programme exemple se présente sous la forme d'un mini sondage à trois choix :
La possibilité de choisir parmi une de ces valeurs est rendue possible par l'utilisation des GtkRadioButton. Un autre bouton (tout ce qu'il y a de plus normal) permet de valider le choix fait par l'utilisateur ainsi que d'afficher le résultat dans une boîte de dialogue.
#include <stdlib.h> #include <gtk/gtk.h> void OnValider(GtkWidget *pBtn, gpointer data); int main(int
argc, char **argv) gtk_init(&argc, &argv); pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); pVBox = gtk_vbox_new(TRUE, 0); pLabel = gtk_label_new("Votre choix :"); /* Creation du premier
bouton radio */ pValider = gtk_button_new_from_stock(GTK_STOCK_OK); gtk_widget_show_all(pWindow); /* Connexion des signaux
*/ gtk_main(); return EXIT_SUCCESS; void OnValider(GtkWidget *pBtn, gpointer
data) /* Recuperation de la liste
des boutons */ /* Parcours de la liste
*/ /* On recupere la fenetre
principale */ pInfo = gtk_message_dialog_new (GTK_WINDOW(pWindow), gtk_dialog_run(GTK_DIALOG(pInfo)); gtk_widget_destroy(pInfo); |
Résultat : |
void gtk_toggle_button_set_mode (GtkToggleButton *toggle_button, gboolean draw_indicator); |
Définit si le bouton est visible ou pas. Entrée(s) : toggle_button : le bouton. draw_indicator : TRUE pour visible, FALSE pour invisible. Sortie : rien |
gboolean gtk_toggle_button_get_mode (GtkToggleButton *toggle_button); |
Pour savoir si le bouton est visible ou pas. Entrée(s) : toggle_button : le bouton. Sortie : TRUE si le bouton est visible, FALSE sinon. |
void gtk_radio_button_set_group (GtkRadioButton *radio_button, GSList *group); |
Pour changer un bouton radio de groupe. Entrée(s) : toggle_button : le bouton. group : le nouveau groupe du bouton. Sortie : rien |