Les labels sont très utilisés dans GTK et sont relativement
simples. Ils n'émettent pas de signaux car ils n'ont pas de fenêtre X
qui leur est associée. Si vous avez besoin de capturer des signaux ou
de faire des coupures (« clippings »), utilisez un widget EventBox.
Pour créer un label, on utilise :
GtkWidget* gtk_label_new (char *str);
Où l'unique paramètre est la chaîne de caractères que l'on veut que le
label affiche.
Pour changer le texte d'un label après sa création, on utilise la fonction :
void gtk_label_set (GtkLabel *label,
char *str);
où le premier paramètre est le label que l'on veut modifier, que l'on
convertit en utilisant la macro GTK_LABEL(), et le second est la
nouvelle chaîne.
L'espace nécessaire à la nouvelle chaîne sera automatiquement ajusté
si nécessaire.
Pour récupérer la chaîne courante, on utilise la fonction :
void gtk_label_get (GtkLabel *label,
char **str);
où le premier paramètre est le label dont on veut récupérer la chaîne
et le second sert à retourner cette chaîne.
Ce sont les petits textes qui surgissent lorsque vous laissez votre
pointeur sur un bouton ou un autre widget pendant quelques secondes.
Ils sont faciles à utiliser, on ne donnera donc pas d'exemple. Si vous
voulez voir du code, consultez le programme testgtk.c distribué
avec GTK.
Certains widgets (comme les labels) ne fonctionnent pas avec les
bulles d'aide.
Le premier appel que vous utiliserez sera pour créer une nouvelle
bulle d'aide. Vous n'avez besoin que de le faire une fois dans une
fonction donnée. Le GtkTooltip que cette fonction retourne peut
être utilisé pour créer plusieurs bulles d'aide.
GtkTooltips *gtk_tooltips_new (void);
Lorsque vous avez créé une nouvelle bulle d'aide et le widget sur lequel vous
voulez l'utiliser, vous n'avez qu'à faire cet appel pour la configurer :
Les paramètres sont la bulle d'aide déjà créée, suivi du widget pour
lequel vous voulez voir apparaître cette bulle et le texte que vous
voulez qu'elle contienne.
Configure le nombre de millisecondes pendant lequel
le pointeur soit se trouver sur le widget avant que la bulle d'aide
n'apparaisse. Par défaut, ce délai est de 1000 millisecondes, soit 1
seconde.
Les barres de progression sont utilisées pour afficher la progression
d'une opération. Elles sont très simple à utiliser comme vous pourrez
le constater en étudiant le code ci-dessous. Commençons d'abord par
l'appel permettant de créer une nouvelle barre.
GtkWidget *gtk_progress_bar_new (void);
Maintenant que la barre est créée, nous pouvons l'utiliser.
Le premier paramètre est la barre de progression sur laquelle on veut
agir, et le second est le pourcentage « effectué », signifiant le
remplissage de la barres de 0 à 100 % (réel compris entre 0 et 1).
Les barres de progression sont généralement utilisées avec les délais
d'expiration ou autres fonctions identiques (voir la section sur
Expirations, fonctions d'E/S et d'attente)
pour donner l'illusion du multi-tâches. Toutes emploient la fonction
gtk_progress_bar_update de la même façon.
Voici un exemple de barre de progression mise à jour par des
expirations. Ce code montre aussi comment réinitialiser une barre.
#include <gtk/gtk.h>
static int ptimer = 0;
int pstat = TRUE;
/* Cette fonction incrémente et met à jour la barre de progression,
* elle la réinitialise si pstat vaut FALSE */
gint progress (gpointer data)
{
gfloat pvalue;
/* récupération de la valeur courante de la barre */
pvalue = GTK_PROGRESS_BAR (data)->percentage;
if ((pvalue >= 1.0) || (pstat == FALSE)) {
pvalue = 0.0;
pstat = TRUE;
}
pvalue += 0.01;
gtk_progress_bar_update (GTK_PROGRESS_BAR (data), pvalue);
return TRUE;
}
/* Cette fonction signale une réinitialisation de la barre */
void progress_r (void)
{
pstat = FALSE;
}
void destroy (GtkWidget *widget, gpointer *data)
{
gtk_main_quit ();
}
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *label;
GtkWidget *table;
GtkWidget *pbar;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (destroy), NULL);
gtk_container_border_width (GTK_CONTAINER (window), 10);
table = gtk_table_new(3,2,TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
label = gtk_label_new ("Exemple de barre de progression");
gtk_table_attach_defaults(GTK_TABLE(table), label, 0,2,0,1);
gtk_widget_show(label);
/* Crée une barre, la place dans la table et l'affiche */
pbar = gtk_progress_bar_new ();
gtk_table_attach_defaults(GTK_TABLE(table), pbar, 0,2,1,2);
gtk_widget_show (pbar);
/* Configure le délai d'expiration pour gérer automatiquement la
* mise à jour de la barre */
ptimer = gtk_timeout_add (100, progress, pbar);
/* Ce bouton indique à la barre qu'elle doit se réinitialiser */
button = gtk_button_new_with_label ("Reset");
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (progress_r), NULL);
gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,2,3);
gtk_widget_show(button);
button = gtk_button_new_with_label ("Annuler");
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (destroy), NULL);
gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,2,3);
gtk_widget_show (button);
gtk_widget_show(table);
gtk_widget_show(window);
gtk_main ();
return 0;
}
Dans ce petit programme, il y a quatre parties concernant le
fonctionnement général des barres de progression, nous les étudierons
dans l'ordre de leurs appels.
pbar = gtk_progress_bar_new ();
Cet appel crée une nouvelle barre, nommée pbar.
ptimer = gtk_timeout_add (100, progress, pbar);
Cet appel utilise des délais d'expiration pour permettre un intervalle
de temps constant. ces délais ne sont pas nécessaires à l'utilisation
des barres de progression.
pvalue = GTK_PROGRESS_BAR (data)->percentage;
Ce code assigne à pvalue la valeur du pourcentage de la barre.
Les widgets boîtes de dialogue sont très simples : ce sont
simplement des fenêtres avec plusieurs choses déjà placées dedans. La
structure d'une boîte de dialogue est :
Comme vous le voyez, cela crée simplement une fenêtre et la place dans
une vbox suivie d'un séparateur et d'une hbox pour la « zone d'action ».
Le widget boîte de dialogue peut servir à produire des messages pour
l'utilisateur ainsi qu'à d'autres tâches. Il est vraiment rudimentaire
et il n'y a qu'une seule fonction pour les boîtes de dialogue :
GtkWidget* gtk_dialog_new (void);
Ainsi, pour créer un nouveau dialogue, on utilise :
GtkWidget window;
window = gtk_dialog_new ();
Ceci créera la boîte de dialogue et c'est maintenant à vous de
l'utiliser. Vous pouvez, par exemple, placer un bouton dans la zone
d'action en faisant quelque chose comme :
Et vous pouvez aussi ajouter un label à la zone de la vboxb :
label = gtk_label_new ("Les boîtes de dialogues sont pratiques");
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, TRUE,
TRUE, 0);
gtk_widget_show (label);
Comme exemple d'utilisation d'une boîte de dialogue, vous pourriez
mettre deux boutons dans la zone d'action (un bouton « Annuler » et un
bouton « Ok ») et un label dans la zone de la vbox posant une question
à l'utilisateur ou signalant une erreur, etc. Vous pouvez alors
attacher un signal différent à chacun des boutons et réaliser
l'opération que l'utilisateur a choisie.
Les pixmaps sont des structures de données contenant des
images. Celles-ci peuvent être utilisées à différents endroits, mais
le plus souvent comme icônes dans le bureau X Window. Un bitmap est un
pixmap de 2 couleurs.
Pour utiliser des pixmaps avec GTK, on doit d'abord construire une
structure GdkPixmap en utilisant les fonctions de la couche
GDK. Les pixmaps peuvent soit être créés à partir de données en
memoire, ou à partir de données lues dans un fichier. Nous utiliserons
chacun des appels pour créer un pixmap.
Cette fonction sert à créer un pixmap mono-plan (2 couleurs) à partir
de données en mémoire. Chaque bit de la donnée data. width
et height sont exprimés en pixels. Le pointeur vers un
GdkWindow pointe sur la fenêtre courante car les ressources d'un
pixmap n'ont de signification que dans le contexte de l'écran où il
doit s'afficher.
Cette fonction est utilisée pour créer un pixmap d'une profondeur
donnée (nombre de couleurs) à partir de la donnée spécifiée pas
data. fg et bg sont les couleurs à utiliser pour
l'avant et l'arrière-plan.
Le format XPM est une représentation des pixmaps reconnue par le système X Window. Il est largement utilisé et de nombreux utilitaires pour créer des fichiers d'images à ce format sont disponibles. Le fichier filename doit contenir une image dans ce format qui sera chargée dans la structure pixmap. Le masque mask indique quels sont les bits opaques du pixmap. Tous les autres bits sont colorisés en utilisant la couleur spécifiée par transparent_color. Un exemple d'utilisation est présenté ci-dessous.
De petites images peuvent être intégrées dans un programme sous la forme de
données data au format XPM. Un pixmap est créé en utilisant ces données au
lieu de les lire dans un fichier. Un exemple de telles données est :
Lorsqu'on a utilisé un pixmap et que l'on en a plus besoin tout de suite, il est préférable de libérer la ressource en utilisant un appel à gdk_pixmap_destroy. Les pixmaps doivent être considérées comme une ressource précieuse.
Quand le pixmap est créé, on peut l'afficher comme un widget GTK. On
doit créer un widget pixmap qui contiendra le pixmap GDK. Ceci est
réalisé de la façon suivante :
gtk_pixmap_set sert à changer le pixmap pris en charge par le widget. val est le pixmap créé par le GDK.
Voici un exemple illustrant l'utilisation d'un pixmap dans un bouton :
#include <gtk/gtk.h>
/* données XPM d'une icône "Ouvrir fichier" */
static const char * xpm_data[] = {
"16 16 3 1",
" c None",
". c #000000000000",
"X c #FFFFFFFFFFFF",
" ",
" ...... ",
" .XXX.X. ",
" .XXX.XX. ",
" .XXX.XXX. ",
" .XXX..... ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" ......... ",
" ",
" "};
/* Termine l'application lorsqu'elle est appelée
* via le signal "delete_event" */
void close_application( GtkWidget *widget, GdkEvent *event, gpointer *data )
{
gtk_main_quit();
}
/* Invoquée lorsque le bouton est cliqué. Affiche simplement
* un message. */
void button_clicked( GtkWidget *widget, gpointer *data )
{
printf( "bouton cliqué\n" );
}
int main( int argc, char *argv[] )
{
/* GtkWidget est le type pour déclarer les widgets */
GtkWidget *window, *pixmapwid, *button;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkStyle *style;
/* Crée la fenêtre principale et attache le signal "delete_event" pour
* terminer l'application */
gtk_init( &argc, &argv );
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_signal_connect( GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (close_application), NULL );
gtk_container_border_width( GTK_CONTAINER (window), 10 );
gtk_widget_show( window );
/* Utilisation de GDK pour créer le pixmap */
style = gtk_widget_get_style( window );
pixmap = gdk_pixmap_create_from_xpm_d( window->window, &mask,
&style->bg[GTK_STATE_NORMAL],
(gchar **)xpm_data );
/* Création d'un widget pixmap GTK pour contenir le pixmap GDK */
pixmapwid = gtk_pixmap_new( pixmap, mask );
gtk_widget_show( pixmapwid );
/* Création d'un bouton pour contenir le widget pixmap */
button = gtk_button_new();
gtk_container_add( GTK_CONTAINER(button), pixmapwid );
gtk_container_add( GTK_CONTAINER(window), button );
gtk_widget_show( button );
gtk_signal_connect( GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(button_clicked), NULL );
/* Affichage de la fenêtre */
gtk_main ();
return 0;
}
Pour charger un fichier à partir d'un fichier XPM appelé
icon0.xpm se trouvant dans le répertoire courant, on aurait créé
le pixmap ainsi :
/* Charge un pixmap à partir d'un fichier */
pixmap = gdk_pixmap_create_from_xpm( window->window, &mask,
&style->bg[GTK_STATE_NORMAL],
"./icon0.xpm" );
pixmapwid = gtk_pixmap_new( pixmap, mask );
gtk_widget_show( pixmapwid );
gtk_container_add( GTK_CONTAINER(window), pixmapwid );
Utilisation des formes
Un désavantage de l'utilisation des pixmaps est que l'objet affiché
est toujours rectangulaire, quelle que soit l'image. On voudrait
pouvoir créer des bureaux et des applications avec des icônes ayant
des formes plus naturelles. Par exemple, pour une interface de jeu, on
aimerait avoir des boutons ronds à pousser. Pour faire cela, on doit
utiliser des fenêtres avec des formes.
Une fenêtre avec forme est simplement un pixmap dont les pixels du
fond sont transparents. Ainsi, lorsque l'image d'arrière-plan est
multicolore, on ne la cache pas avec le bord de notre icône. L'exemple
suivant affiche une image de brouette sur le bureau.
#include <gtk/gtk.h>
/* XPM */
static char * WheelbarrowFull_xpm[] = {
"48 48 64 1",
" c None",
". c #DF7DCF3CC71B",
"X c #965875D669A6",
"o c #71C671C671C6",
"O c #A699A289A699",
"+ c #965892489658",
"@ c #8E38410330C2",
"# c #D75C7DF769A6",
"$ c #F7DECF3CC71B",
"% c #96588A288E38",
"& c #A69992489E79",
"* c #8E3886178E38",
"= c #104008200820",
"- c #596510401040",
"; c #C71B30C230C2",
": c #C71B9A699658",
"> c #618561856185",
", c #20811C712081",
"< c #104000000000",
"1 c #861720812081",
"2 c #DF7D4D344103",
"3 c #79E769A671C6",
"4 c #861782078617",
"5 c #41033CF34103",
"6 c #000000000000",
"7 c #49241C711040",
"8 c #492445144924",
"9 c #082008200820",
"0 c #69A618611861",
"q c #B6DA71C65144",
"w c #410330C238E3",
"e c #CF3CBAEAB6DA",
"r c #71C6451430C2",
"t c #EFBEDB6CD75C",
"y c #28A208200820",
"u c #186110401040",
"i c #596528A21861",
"p c #71C661855965",
"a c #A69996589658",
"s c #30C228A230C2",
"d c #BEFBA289AEBA",
"f c #596545145144",
"g c #30C230C230C2",
"h c #8E3882078617",
"j c #208118612081",
"k c #38E30C300820",
"l c #30C2208128A2",
"z c #38E328A238E3",
"x c #514438E34924",
"c c #618555555965",
"v c #30C2208130C2",
"b c #38E328A230C2",
"n c #28A228A228A2",
"m c #41032CB228A2",
"M c #104010401040",
"N c #492438E34103",
"B c #28A2208128A2",
"V c #A699596538E3",
"C c #30C21C711040",
"Z c #30C218611040",
"A c #965865955965",
"S c #618534D32081",
"D c #38E31C711040",
"F c #082000000820",
" ",
" .XoO ",
" +@#$%o& ",
" *=-;#::o+ ",
" >,<12#:34 ",
" 45671#:X3 ",
" +89<02qwo ",
"e* >,67;ro ",
"ty> 459@>+&& ",
"$2u+ ><ipas8* ",
"%$;=* *3:.Xa.dfg> ",
"Oh$;ya *3d.a8j,Xe.d3g8+ ",
" Oh$;ka *3d$a8lz,,xxc:.e3g54 ",
" Oh$;kO *pd$%svbzz,sxxxxfX..&wn> ",
" Oh$@mO *3dthwlsslszjzxxxxxxx3:td8M4 ",
" Oh$@g& *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B* ",
" Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5& ",
" Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM* ",
" OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
" 2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
" :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
" +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
" *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&en",
" p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
" OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
" 3206Bwxxszx%et.eaAp77m77mmmf3&eeeg* ",
" @26MvzxNzvlbwfpdettttttttttt.c,n& ",
" *;16=lsNwwNwgsvslbwwvccc3pcfu<o ",
" p;<69BvwwsszslllbBlllllllu<5+ ",
" OS0y6FBlvvvzvzss,u=Blllj=54 ",
" c1-699Blvlllllu7k96MMMg4 ",
" *10y8n6FjvllllB<166668 ",
" S-kg+>666<M<996-y6n<8* ",
" p71=4 m69996kD8Z-66698&& ",
" &i0ycm6n4 ogk17,0<6666g ",
" N-k-<> >=01-kuu666> ",
" ,6ky& &46-10ul,66, ",
" Ou0<> o66y<ulw<66& ",
" *kk5 >66By7=xu664 ",
" <<M4 466lj<Mxu66o ",
" *>> +66uv,zN666* ",
" 566,xxj669 ",
" 4666FF666> ",
" >966666M ",
" oM6668+ ",
" *4 ",
" ",
" "};
/* Termine l'application lorsqu'elle est appelée
* (via le signal "delete_event"). */
void close_application( GtkWidget *widget, GdkEvent *event, gpointer *data )
{
gtk_main_quit();
}
int main (int argc, char *argv[])
{
GtkWidget *window, *pixmap, *fixed;
GdkPixmap *gdk_pixmap;
GdkBitmap *mask;
GtkStyle *style;
GdkGC *gc;
/* crée la fenêtre principale et attache le signal "delete_event"
* pour terminer l'application. On notera que la fenêtre principale
* n'a pas de barre de titre car nous la faisons surgir. */
gtk_init (&argc, &argv);
window = gtk_window_new( GTK_WINDOW_POPUP );
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (close_application), NULL);
gtk_widget_show (window);
/* Création du pixmap et du widget pixmap */
style = gtk_widget_get_default_style();
gc = style->black_gc;
gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &mask,
&style->bg[GTK_STATE_NORMAL],
WheelbarrowFull_xpm );
pixmap = gtk_pixmap_new( gdk_pixmap, mask );
gtk_widget_show( pixmap );
/* Pour afficher le pixmap, on utilise un widget fixe pour placer
* le pixmap */
fixed = gtk_fixed_new();
gtk_widget_set_usize( fixed, 200, 200 );
gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
gtk_container_add( GTK_CONTAINER(window), fixed );
gtk_widget_show( fixed );
/* On masque tout sauf l'image elle-même */
gtk_widget_shape_combine_mask( window, mask, 0, 0 );
/* Affichage de la fenêtre */
gtk_widget_set_uposition( window, 20, 400 );
gtk_widget_show( window );
gtk_main ();
return 0;
}
Pour rendre l'image de la brouette sensible aux clics, on peut lui
attacher le signal "button_press_event" pour lui faire faire quelque
chose. Les quelques lignes suivantes font que l'image sera sensible à
un clic souris qui provoquera l'arrêt de l'application.