Date de publication : 20 Février 2007
Nous allons dans ce chapitre étudier trois widgets différents qui vont nous permettre de définir une valeur numérique sans avoir à la saisir au clavier. Le premier widget que nous allons étudier est GtkScrollbar qui se dérive en deux widgets différents, un qui est vertical et l'autre horizontal. Puis nous étudierons le widget GtkScale qui lui aussi se décline en un widget vertical et un horizontal. Et nous terminerons avec le widget GtkSpinButton.
Ces trois widgets permettent de choisir une valeur numérique à l'intérieur d'une fourchette de valeurs bien définies. Le fonctionnement similaire de ces trois widgets est rendu possible par l'utilisation de l'objet GtkAdjustment. Nous allons donc tout d'abord acquérir les notions nécessaires sur ce widget pour comprendre les widgets de sélection.
struct _GtkAdjustment
{
GtkObject parent_instance;
gdouble lower;
gdouble upper;
gdouble value;
gdouble step_increment;
gdouble page_increment;
gdouble page_size;
}
La propriété parent_instance
nous dit tout simplement
que l'objet GtkAdjustment
dérive directement de GtkObject
.
Les valeurs lower
et upper
déterminent respectivement
la valeur minimale et la valeur maximale que peut prendre le widget qui utilise
cet objet. La valeur value
donne la valeur actuelle telle qu'elle
est définie par le widget. Les valeurs step_increment
et
page_increment
définissent de combien value sera modifiée
à chaque fois que l'utilisateur demande d'augmenter ou de diminuer la
valeur. Nous verrons la différence entre ces deux valeurs avec l'étude
des widgets GtkScrollbar
et GtkScale
. La dernière
propriété page_size
définit la taille d'une
page, mais là aussi cela deviendra plus clair avec l'étude des
widgets qui va suivre.
La première fonction de base est bien sûr la fonction qui permet de créer un tel objet :
GtkObject* gtk_adjustment_new (gdouble value, gdouble lower, gdouble upper, gdouble step_increment, gdouble page_increment, gdouble page_size);
Nous retrouvons ici tous les paramètres définis précédemment.
Ensuite pour modifier ou récupérer la valeur actuelle de l'objet, il y a ces deux fonctions :
void gtk_adjustment_set_value(GtkAdjustment *adjustment, gdouble
value);
gdouble gtk_adjustment_get_value(GtkAdjustment *adjustment);
Bien entendu la première fonction change le widget utilisateur pour
que sa position représente la valeur value
, et la deuxième
fonction récupère cette valeur.
Et pour terminer voici la fonction qui permet de modifier les valeurs limites de l'objet :
void gtk_adjustment_clamp_page (GtkAdjustment *adjustment, gdouble lower, gdouble upper);
Nous avons vu l'essentiel des fonctions de l'objet GtkAdjustment
,
mais en règle générale, il n'est pas nécessaire
de les utiliser, car les widgets qui nécessitent cet objet, ont leurs
propres fonctions d'accès et de modification des paramètres.
Comme nous l'avons dit dans la présentation, ce widget se décline en deux variantes différentes :
Mais nous allons voir que mise à part les fonctions de création, toutes les autres opérations se font avec les mêmes fonctions quel que soit le widget utilisé.
Voici donc les deux fonctions de création disponibles :
GtkWidget* gtk_vscrollbar_new(GtkAdjustment *adjustment);
GtkWidget* gtk_hscrollbar_new(GtkAdjustment *adjustment);
La première fonction crée donc une GtkVScrollbar
et la seconde une GtkHScrollbar
. De plus, nous voyons qu'il faut
obligatoirement un GtkAdjustment
pour définir les paramètres
du widget. Il va donc falloir dans un premier temps créer un GtkAdjustment
et définir ses valeurs.
Pour ce qui est des valeurs lower
, upper
, et value
,
il n'y a pas de problème. Par contre pour les valeurs step_increment
et page_increment
, il faut connaître un peu le fonctionnement
de ce widget. Regardons d'abord à quoi ressemble un widget GtkHScrollbar.
La zone 1 est en fait l'afficheur de la valeur actuelle prise par la GtkScrollbar
.
Elle permet aussi de sélectionner une valeur en le déplaçant
à l'aide de la souris. Les deux zones 2 permettent de modifier la valeur
de la zone 1. Un clic de souris sur une de ces zones modifiera la valeur de
plus ou moins la valeur de step_increment
. Les zones 3 ont le même
objectif que les zones 2 mais cette fois avec une modification de valeur de
page_increment
.
Il reste encore le dernier paramètre à configurer. Ce dernier,
page_size
, détermine la taille de la zone 1. Si, par exemple
le widget GtkScrollbar
a une valeur minimale de 0 et une valeur
maximale de 100, et nous définissons page_size
comme ayant
une valeur de 50, la zone 1 du widget aura une longueur égale à
la moitié de celle du widget. Le dernier point sur ce paramètre
est qu'il détermine aussi la valeur qu'il faut donner à upper
.
Ce widget fonctionnant en utilisant des pages, la valeur upper
n'est jamais atteinte. Si l'on veut pouvoir choisir une valeur entre 0 et 100
avec un page_size
égale à 50, il faudra mettre upper
à 150 soit le upper
théorique plus page_size
.
En effet, ce widget n'a pas comme vocation première de permettre de sélectionner
des valeurs numériques mais plutôt l'affichage d'autre widget dont
la hauteur (ou la largeur) est supérieure à la zone d'affichage.
Ainsi lorsque la barre de sélection est complètement à
gauche, la valeur de la GtkScrollbar
est bien de 0, mais elle considère
qu'elle affiche une zone allant de 0 à page_size
(50 dans
notre exemple). De ce fait, si la barre de sélection est complètement
à droite la valeur de la GtkScrollbar sera égale à upper-page_size
et considèrera qu'elle affiche une zone allant de upper-page_size
à upper
(50 à 100 dans notre exemple). Pour conclure,
il faut toujours donner à upper
la valeur maximale que nous
souhaitons pouvoir sélectionner plus la valeur de page_size
.
Nous savons maintenant comment configurer le GtkAdjustment
afin
de créer proprement une GtkScrollbar
.
Nous allons maintenant traiter les fonctions de gestion d'une GtkScrollbar
.
Pour cela, nous n'allons pas utiliser les widgets GtkHScrollbar
et GtkVScrollbar
car il n'y a pour chaque widget qu'une seule fonction
de création, ni le widget GtkScrollbar
car il ne possède
aucune fonction, mais le widget GtkRange
dont dérive toute
cette panoplie.
Tout d'abord pour fixer la valeur d'une GtkScrollbar
, nous avons
à notre disposition la fonction suivante :
void gtk_range_set_value(GtkRange *range, gdouble value);
Bien sûr le premier paramètre est la GtkScrollbar
dont nous voulons fixer la valeur. Il faut pour cela utiliser la macro de conversion
GTK_RANGE()
. Le deuxième paramètre est la valeur
que nous voulons donner à notre GtkScrollbar
.
A l'inverse, la fonction nous permettant de connaître la valeur de la
GtkScrollbar
est :
gdouble gtk_range_get_value(GtkRange *range);
Ensuite le widget GtkRange
nous offre la possibilité de
modifier les bornes du widget ainsi que les différents pas avec ces deux
fonctions :
void gtk_range_set_increments (GtkRange *range, gdouble step,
gdouble page);
void gtk_range_set_range (GtkRange *range, gdouble min, gdouble max);
La première fonction modifie les pas de modification. Les paramètres
step
et page
correspondent aux paramètres step_increment
et page_increment
du GtkAdjustment associé au widget.
La deuxième fonction permet de modifié les valeurs minimale et
maximale que le widget peut prendre. Là encore, il faut penser au problème
de la valeur maximale pour bien configurer max
.
Une autre possibilité pour modifier ces paramètres est de créer un nouveau GtkAdjustment et de l'associer à la GtkScrollbar avec cette fonction :
void gtk_range_set_adjustment (GtkRange *range, GtkAdjustment *adjustment);
Notre premier exemple de ce chapitre va nous permettre de sélection les valeurs RGB que nous souhaitons affecter. La couleur formée par ces valeurs ne sera pas affichée car nous nous contenterons d'afficher ces valeurs dans un label.
Pour modifier les valeurs des labels en fonction des modifications des GtkScrollbar, nous allons capturer le signal "value-changed" de chaque GtkScrollbar.
#include <stdlib.h> #include <gtk/gtk.h> void OnScrollbarChange(GtkWidget *pWidget, gpointer data); int main(int
argc,char **argv) gtk_init(&argc,&argv); pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); pMainVBox = gtk_vbox_new(TRUE, 0); pFrame = gtk_frame_new("Rouge"); /* Label d'affichage de valeur
R*/ /* Idem pour G */ pLabel = gtk_label_new("0"); /* Idem pour B */ pLabel = gtk_label_new("0"); gtk_widget_show_all(pWindow); g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_main(); return EXIT_SUCCESS; void OnScrollbarChange(GtkWidget *pWidget,
gpointer data) /* Recuperation de la valeur
de la scrollbar */ |
Résultat : |
Les widgets GtkHScale
et GtkVScale
ont un fonctionnement
quasi identique aux widget GtkHScrollbar
et GtkVScrollbar
mais sont plus simple d'utilisation. Un des avantages de ce widget est qu'il
offre la possibilité d'afficher tout seul sa valeur.
Comme pour les GtkScrollbar
, nous pouvons créer des GtkScale
à l'aide de GtkAdjustment
avec ces fonctions :
GtkWidget* gtk_vscale_new(GtkAdjustment *adjustment);
GtkWidget* gtk_hscale_new (GtkAdjustment *adjustment);
La première fonction crée donc un GtkScale
vertical
alors la deuxième un GtkScale
horizontal.
Mais pour ne pas avoir à créer un objet GtkAdjustment
,
les créateurs de GTK+
ont pensé à nous fournir
une fonction qui n'en a pas besoin :
GtkWidget* gtk_vscale_new_with_range (gdouble min, gdouble
max, gdouble step);
GtkWidget* gtk_hscale_new_with_range (gdouble min, gdouble max, gdouble step);
Avec ces quatre fonctions, la signification de step
(ou step_increment
si l'on utilise un GtkAdjustment
) est un peu différente
car le widget GtkScale
n'a pas de bouton fléché comme
GtkScrollbar
. Cette valeur est utilisée pour un déplacement
à l'aide des touches fléchées lorsque le widget a le focus.
De plus, si nous n'utilisons pas de GtkAdjustment, la valeur de page_increment
est égale à dix fois celle de step
.
Pour récupérer ou fixer les différentes valeurs d'un widget
GtkScale
il faut, comme pour le widget GtkScrollbar
,
utiliser les fonctions du widget GtkRange
qui ont été
décrites plus haut. Nous n'allons donc pas revenir dessus.
Comme nous l'avons dit dans la présentation de ce widget, il s'occupe
seul d'afficher et de mettre à jour un label qui affiche la valeur du
widget. Par défaut, le label est affiché au-dessus du GtkScale
.
Etudions les quelques fonctions qui nous sont fournis pour gérer cet
affichage.
void gtk_scale_set_draw_value (GtkScale *scale, gboolean draw_value);
gboolean gtk_scale_get_draw_value (GtkScale *scale);
La première fonction nous permet de décider si nous voulons qu'un
label s'affiche ou pas. Pour cela il suffit de mettre le paramètre draw_value
à TRUE
si nous souhaitons qu'il s'affiche ou FALSE
si nous ne le souhaitons pas. En ce qui concerne le premier paramètre,
il faut utiliser la macro de conversion GTK_SCALE()
.
La deuxième fonction permet de savoir si le label est affiché
ou pas.
Ensuite nous avons la possibilité de gérer le nombre de chiffre après la virgule qui sont affichés :
void gtk_scale_set_digits (GtkScale *scale, gint digits);
gint gtk_scale_get_digits (GtkScale *scale);
Dans la première fonction, digit est bien sûr le nombre de chiffre après la virgule à afficher.
Et pour terminer, nous allons voir comment gérer la position du label par rapport à la barre de sélection :
void gtk_scale_set_value_pos (GtkScale *scale, GtkPositionType
pos);
GtkPositionType gtk_scale_get_value_pos (GtkScale *scale);
Le paramètre pos (de la première fonction) peut prendre une de ces quatre valeurs :
Nous allons reprendre l'exemple précédent que nous allons transformer pour l'utilisation de widget GtkHScale ce qui le rendra plus simple. Cependant, pour utiliser les fonctions du widget GtkScale, le premier GtkHScale aura un label au dessus, le second aura un label en dessous et le troisième pas du tout.
#include <stdlib.h> #include <gtk/gtk.h> int
main(int argc,char
**argv) gtk_init(&argc,&argv); pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); pMainVBox = gtk_vbox_new(TRUE, 0); pFrame = gtk_frame_new("Rouge"); pFrame = gtk_frame_new("Vert"); pFrame = gtk_frame_new("Bleu"); gtk_widget_show_all(pWindow); g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_main(); return EXIT_SUCCESS; |
Résultat : |
Ce widget est un peu différent des deux précédents dans
le sens ou il s'agit en fait d'un widget GtkEntry
et de deux GtkButton
assemblés pour former un tout. De plus il permet de sélectionner
une valeur soit en utilisant les boutons soit en entrant directement la valeur
au clavier. Mais voyons tout cela en détail.
Il existe là aussi deux fonctions de créations :
GtkWidget* gtk_spin_button_new (GtkAdjustment *adjustment,
gdouble climb_rate, guint digits);
GtkWidget* gtk_spin_button_new_with_range (gdouble min, gdouble max, gdouble
step);
La première fonction permet de créer un GtkSpinButton
à partir d'un GtkAdjustment
, mais il faut cependant préciser
le paramètre climb_rate
qui correspond au paramètre
step_increment
du GtkAdjustment
et digits
qui représente le nombre de chiffre après la virgule de la valeur
que nous allons pouvoir sélectionner.
La deuxième fonction permet de se passer de GtkAdjustment
car nous fixons les valeurs minimales et maximales (paramètres min
et max
) ainsi que la valeur de modification avec le paramètre
step
. En ce qui concerne le nombre de chiffres après la
virgule, il sera identique à celui de step
.
Pour ce widget, le clavier permet aussi de modifier sa valeur. Les touches
fléchées HAUT
et BAS
permettent de modifier
la valeur de step_increment
(dans le cas de l'utilisation d'un
GtkAdjustment
) ou de step
. De plus les touches PAGE_UP
et PAGE_DOWN
permettent de modifier la valeur de page_increment
avec une création utilisant un GtkAdjustment
ou de step*10
dans l'autre cas.
Voyons tout d'abord comment récupérer ou modifier la valeur en cours d'un GtkSpinButton à l'aide d'une de ces trois fonctions :
void gtk_spin_button_set_value (GtkSpinButton *spin_button,
gdouble value);
gdouble gtk_spin_button_get_value (GtkSpinButton *spin_button);
gint gtk_spin_button_get_value_as_int(GtkSpinButton *spin_button);
La première fonction permet donc de modifier la valeur d'un GtkSpinButton
.
Il faut pour le premier paramètre utiliser la macro de conversion GTK_SPIN_BUTTON()
.
La deuxième fonction permet de récupérer la valeur d'un
GtkSpinButton
tout simplement.
La dernière fonction a le même but que la deuxième mais
celle-ci renvoie un entier alors que la deuxième renvoie un double.
Nous pouvons nous occuper du nombre de chiffre après la virgule avec ces deux fonctions :
guint gtk_spin_button_get_digits (GtkSpinButton *spin_button);
void gtk_spin_button_set_digits (GtkSpinButton *spin_button, guint digits);
La première fonction permettant de connaître le nombre de chiffre après la virgule alors que la seconde permet de le modifier.
Et pour terminer voici les fonctions qui permettent de modifier les bornes des valeurs :
void gtk_spin_button_get_range (GtkSpinButton *spin_button,
gdouble *min, gdouble *max);
void gtk_spin_button_set_range (GtkSpinButton *spin_button, gdouble min, gdouble
max);
Comme d'habitude, la première fonction permet de connaître les
bornes du GtkSpinButton
et la seconde permet de les modifier.
Mais bien sûr, tout cela peut se modifier à l'aide des GtkAdjustment avec ces deux fonctions :
GtkAdjustment* gtk_spin_button_get_adjustment(GtkSpinButton
*spin_button);
void gtk_spin_button_set_adjustment (GtkSpinButton *spin_button, GtkAdjustment
*adjustment);
Le programme exemple sera identique aux deux premiers, c'est à dire qu'il va permettre de sélectionner une valeur RGB à l'aide de trois widget GtkSpinButton.
#include <stdlib.h> #include <gtk/gtk.h> int
main(int argc,char
**argv) gtk_init(&argc,&argv); pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); pMainVBox = gtk_vbox_new(TRUE, 0); pFrame = gtk_frame_new("Rouge"); pFrame = gtk_frame_new("Vert"); pFrame = gtk_frame_new("Bleu"); gtk_widget_show_all(pWindow); g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_main(); return EXIT_SUCCESS; |
Résultat : |
GtkAdjustment
changed |
Prototype fonction callback : void user_function (GtkAdjustment
*adjustment, gpointer user_data); Ce signal est émis lorsqu'un paramètre autre que value
est modifié. |
value-changed |
Prototype fonction callback : void user_function (GtkAdjustment
*adjustment, gpointer user_data); Ce signal est émis lorsque le paramètre value
est modifié. |
GtkScale
format-value |
Prototype fonction callback : gchar* user_function (GtkScale *scale, gdouble arg1, gpointer user_data); |
GtkRange
adjust-bounds |
Prototype fonction callback : void user_function(GtkRange *range, gdouble arg1, gpointer user_data); |
move-slider |
Prototype fonction callback : void user_function(GtkRange *range, GtkScrollType arg1, gpointer user_data); |
value-changed |
Prototype fonction callback : void user_function(GtkRange *range, gpointer user_data); |
GtkSpinButton
change-value |
Prototype fonction callback : void user_function(GtkSpinButton *spinbutton, GtkScrollType arg1, gpointer user_data); |
input |
Prototype fonction callback : gint user_function(GtkSpinButton *spinbutton, gpointer arg1, gpointer user_data); |
output |
Prototype fonction callback : gboolean user_function(GtkSpinButton *spinbutton, gpointer user_data); |
value-changed |
Prototype fonction callback : gboolean user_function(GtkSpinButton *spinbutton, gpointer user_data); |
GtkAdjustment
void gtk_adjustment_changed (GtkAdjustment *adjustment);
void gtk_adjustment_value_changed (GtkAdjustment *adjustment);
GtkRange
GtkAdjustment* gtk_range_get_adjustment (GtkRange *range);
void gtk_range_set_update_policy (GtkRange *range, GtkUpdateType policy);
gboolean gtk_range_get_inverted (GtkRange *range);
void gtk_range_set_inverted (GtkRange *range, gboolean setting);
GtkUpdateType gtk_range_get_update_policy (GtkRange *range);
GtkSpinButton
void gtk_spin_button_configure (GtkSpinButton *spin_button, GtkAdjustment *adjustment,
gdouble climb_rate, guint digits);
void gtk_spin_button_set_increments (GtkSpinButton *spin_button, gdouble step,
gdouble page);
void gtk_spin_button_set_update_policy(GtkSpinButton *spin_button, GtkSpinButtonUpdatePolicy
policy);
void gtk_spin_button_set_numeric (GtkSpinButton *spin_button, gboolean numeric);
void gtk_spin_button_spin (GtkSpinButton *spin_button, GtkSpinType direction,
gdouble increment);
void gtk_spin_button_set_wrap (GtkSpinButton *spin_button, gboolean wrap);
void gtk_spin_button_set_snap_to_ticks(GtkSpinButton *spin_button, gboolean
snap_to_ticks);
void gtk_spin_button_update (GtkSpinButton *spin_button);
void gtk_spin_button_get_increments (GtkSpinButton *spin_button, gdouble *step,
gdouble *page);
gboolean gtk_spin_button_get_numeric (GtkSpinButton *spin_button);
gboolean gtk_spin_button_get_snap_to_ticks(GtkSpinButton *spin_button);
GtkSpinButtonUpdatePolicy gtk_spin_button_get_update_policy(GtkSpinButton *spin_button);
gboolean gtk_spin_button_get_wrap (GtkSpinButton *spin_button);