La barre de progression
Parfois un programme doit faire de gros calculs, et il est utile davertir
lutilisateur sur l'avancement du calcul afin quil soit au courant
et ne pense pas que le programme est bloqué. Nous allons donc étudierle
widget GtkProgressBar qui sert justement à cela.

1. Utilisation d'une GtkProgressBar
1.1 Création
Ce widget étant comme tous les autres widgets de GTK+ sa
fonction de création est très simple :
GtkWidget* gtk_progress_bar_new(void)
Voila, nous avons maintenant notre GtkProgressBar, maintenant
vous avez besoin de ne connaître que peu de fonctions pour la faire marcher.
1.2 Modification de la progression
Tout d'abord nous allons voir comment connaître la position de la GtkProgressBar
:
gdouble gtk_progress_bar_get_fraction(GtkProgressBar *pbar);
Cette fonction renvoie un double qui sera compris entre 0.0 et 1.0, c'est-à-dire
un pourcentage. Pour ce qui est du paramètre pbar, il faut
utiliser la macro de conversion GTK_PROGRESS_BAR().
A l'inverse, pour fixer la position de la GtkProgressBar, la fonction est :
void gtk_progress_bar_set_fraction(GtkProgressBar *pbar, gdouble
fraction);
Là aussi, le paramètre fraction doit être
compris entre 0.0 et 1.0.
1.3 Exemple.
Notre premier exemple, très simple, sera fait d'une fenêtre (bien
entendu) avec à l'intérieur une barre de progression et un bouton
qui permettra de faire avancer la barre de progression de 10%. Et lorsque la
barre de progression sera à 100%, nous la réinitialiserons à
0%.
1.4 Programme exemple
#include <stdlib.h>
#include <gtk/gtk.h> void
OnButton(GtkWidget *pWidget, gpointer data);
int main(int
argc,char **argv)
{
GtkWidget* pWindow;
GtkWidget *pMainVBox;
GtkWidget *pProgress;
GtkWidget *pButton;
gtk_init(&argc,&argv);
pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(pWindow), "GtkProgressBar");
gtk_window_set_default_size(GTK_WINDOW(pWindow), 320,
200);
gtk_container_set_border_width(GTK_CONTAINER(pWindow),
4);
pMainVBox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(pWindow), pMainVBox);
/* Creation de la barre de progression
*/
pProgress = gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(pMainVBox), pProgress, TRUE,
FALSE, 0);
pButton = gtk_button_new_with_label("Ajouter 10%");
gtk_box_pack_start(GTK_BOX(pMainVBox), pButton, TRUE,
FALSE, 0);
g_signal_connect_swapped(G_OBJECT(pButton), "clicked",
G_CALLBACK(OnButton), pProgress);
gtk_widget_show_all(pWindow);
g_signal_connect(G_OBJECT(pWindow), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return EXIT_SUCCESS;
}
void OnButton(GtkWidget *pWidget, gpointer
data)
{
gdouble dFraction;
/* Recuperation de la valeur
de la barre de progression */
dFraction = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(pWidget));
dFraction += 0.1;
if(dFraction > 1.0)
dFraction = 0.0;
/* Modification de la valeur
de la barre de progression */
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pWidget),
dFraction);
} |
| Résultat :

|
2. Utilisation dans une boucle for.
2.1 Problème
Si nous modifions légèrement le programme précédent
pour insérer une boucle qui fera avancer automatiquement la barre de
progression (par exemple une boucle de 2000 itérations) cela ne fonctionnera
pas. La seule raison pour laquelle cela ne fonctionnera pas est que GTK+
ne reprend pas la main car le programme reste dans la boucle for alors GTK+
ne peut pas mettre à jour les widgets affichés.
2.2 Solution
La solution, est de dire clairement à GTK+ quil doit
remettre à jour grâce à la fonction suivante :
gboolean gtk_main_iteration (void);
Cette fonction permet de faire une itération comme son nom lindique,
une est une seul donc à ce moment là GTK+ va reprendre
la main puis la rendre aussitôt, si bien quil pourra mettre à
jour les widgets. Donc il suffit dajouter cette fonction après
gtk_progress_bar_set_fraction pour faire fonctionner correctement
notre programme.
Ce problème étant réglé, nous allons faire face
à un deuxième problème, ou plutôt pseudo-problème.
En général, lorsque le programme fait un gros calcul, lapplication
doit être "bloquer" pendant ce temps. Donc tant que le traitement
nest pas fini, il faut éviter que lutilisateur ne puisse
change des données. Prenons le cas dun correcteur dorthographe,
disons quil le fasse automatiquement. Pendant quil vérifie
lorthographe il serai bête que lutilisateur puisse modifier
le texte, ce qui fausserai alors toute la correction. Pourquoi cet exemple?
Et bien le fait de rendre la main a GTK+ lui donne le pouvoir de traiter dautres
évènements, comme un clic de sourie et autres. Donc à tout
moment pendant ce calcul lutilisateur peut modifier quelque chose (ici
pas grand choses si ce nest que re-cliquer sur le bouton de démarrage
de la boucle), donc il faut pouvoir lempêcher de faire une quelconque
action.
Nous allons pouvoir bloquer l'utilisateur à l'aide de ces deux fonctions
:
void gtk_grab_add (GtkWidget *widget);
void gtk_grab_remove (GtkWidget *widget);
Nous allons faire une description rapide des ces deux fonctions à l'aide
d'un exemple. Prenons le cas ou l'utilisateur fait dans une application (de
dessin par exemple) une sélection par glissement, quand il quitte la
zone pour atterrir à coté voir en dehors de la fenêtre,
la sélection continue, et bien cest parce que lapplication
se focalise sur la fenêtre de sélection, cest un peut ce
que fait gtk_grab_add. Nous lui donnons un widget et seuls les
évènements de ce widget seront traiter par GTK+, et cela tant
que gtk_grab_remove na pas été invoqué.
Si bien que quand l'utilisateur fait une sélection et qu'il passe au-dessus
dun autre widget, il est ignorer.
Voilà maintenant nous avons tout pour que pendant la boucle la barre
de progression soit remise à jour et sans que lutilisateur ne puisse
cliquer ailleurs.
2.3 Exemple
Nous réutilisons donc l'exemple précédant en modifiant
la fonction du bouton qui sert maintenant à démarrer la progression
de la barre qui sera effectuer dans la fonction callback.
2.4 Programme exemple
#include <stdlib.h>
#include <gtk/gtk.h> void
OnButton(GtkWidget *pWidget, gpointer data);
int main(int
argc,char **argv)
{
GtkWidget* pWindow;
GtkWidget *pMainVBox;
GtkWidget *pProgress;
GtkWidget *pButton;
gtk_init(&argc,&argv);
pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(pWindow), "GtkProgressBar");
gtk_window_set_default_size(GTK_WINDOW(pWindow), 320,
200);
gtk_container_set_border_width(GTK_CONTAINER(pWindow),
4);
pMainVBox = gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(pWindow), pMainVBox);
/* Creation de la barre de progression
*/
pProgress = gtk_progress_bar_new();
gtk_box_pack_start(GTK_BOX(pMainVBox), pProgress, TRUE,
FALSE, 0);
pButton = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
gtk_box_pack_start(GTK_BOX(pMainVBox), pButton, TRUE,
FALSE, 0);
g_signal_connect_swapped(G_OBJECT(pButton), "clicked",
G_CALLBACK(OnButton), pProgress);
gtk_widget_show_all(pWindow);
g_signal_connect(G_OBJECT(pWindow), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return EXIT_SUCCESS;
}
void OnButton(GtkWidget *pWidget, gpointer
data)
{
gdouble dFraction;
gint i;
gint iTotal = 2000;
/* Initialisation */
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pWidget),
0.0);
/* Ici on grab sur la barre de
progression pour 2 raisons : */
/* - cela evite a GTK+ de regarder tous les evenements
ce qui rend plus rapide */
/* l'utilisation de gtk_main_iteration() */
/* - on empeche toute action de l'utilisateur */
gtk_grab_add(pWidget);
for(i = 0 ; i < iTotal ; ++i)
{
dFraction = (gdouble)i / (gdouble)iTotal;
/* Modification
de la valeur de la barre de progression */
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pWidget),
dFraction);
/* On donne
la main a GTK+ */
gtk_main_iteration ();
}
/* On supprime le grab sur la
barre de progression */
gtk_grab_remove(pWidget);
} |
| Résultat :

|
3. En savoir plus.
3.1 Fonctions documentées
| void gtk_progress_bar_set_text (GtkProgressBar *pbar,
const gchar *text); |
Permet d'afficher du texte dans la barre de progression.
Entrée(s) : pbar : objet GtkProgressBar.
text : texte à afficher. Sortie : rien. |
| G_CONST_RETURN gchar* gtk_progress_bar_get_text(GtkProgressBar
*pbar); |
Permet d'obtenir le texte affiché dans la barre
de progression. Entrée(s) : pbar
: objet GtkProgressBar. Sortie : le texte affiché. |
| void gtk_progress_bar_set_orientation(GtkProgressBar *pbar,
GtkProgressBarOrientation orientation); |
Permet de définir le sens de progression de la
GtkProgressBar. Entrée(s) :
pbar : objet GtkProgressBar. orientation : une des valeurs
suivante *GTK_PROGRESS_LEFT_TO_RIGHT -> de gauche à
droite *GTK_PROGRESS_RIGHT_TO_LEFT -> de droite à
gauche *GTK_PROGRESS_BOTTOM_TO_TOP -> de bas en haut
*GTK_PROGRESS_TOP_TO_BOTTOM -> de haut en bas. Sortie
: rien |
| GtkProgressBarOrientation gtk_progress_bar_get_orientation(GtkProgressBar
*pbar); |
Permet d'obtenir le sens de progression de la GtkProgressBar.
Entrée(s) :
pbar : objet GtkProgressBar. Sortie : le sens de
progression. |
Date de mise à jour : 01 mai 2003