GTK - Référence

publicité
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
La bibliothèque GTK
Polycopié de référence
Dans ce document vous trouverez les principaux élément de la bibliothèque GTK.
Table des matières
1
Introduction
2
2
Positionnement de Widgets
5
3
Les boutons
6
4
Les Widgets ajustables
7
5
Entrée de données
8
6
Les fenêtres
8
7
Les éléments d'affichage
11
8
Les listes et arbres
13
9
Les menus
15
10 Les zones de dessin
Eric Guérin
[email protected]
16
15 décembre 2004
1/20
Année scolaire 2003-2004
La bibliothèque GTK
1
Bourg-en-Bresse
Première année
Introduction
GTK (The Gimp Toolkit) est une librairie permettant de gérer une interface graphique. Initialement destinée au monde unix et à
X-Window, celle-ci a été portée sous Windows. De nombreux couplages avec des langages ont été faits (comme Perl ou Python).
Des outils de développement d'interface graphique rapide existent. Glade, par exemple permet de générer automatiquement du code
pour le C, Perl ou Python. De nombreux logiciels libres sont construits sur la base de GTK (Gimp, le projet Gnome, Glade, Gnumeric,
Abiword,. . .).
1.1
Mise en ÷uvre sous linux
La dernière version de GTK (GTK+ 2.0) fonctionne avec l'outil pkg-config. Si GTK est bien installé, la commande suivante doit
fonctionner :
$ pkg-config --cflags gtk+-2.0
De même, l'option --libs vous donne les options à inclure pour que les librairies nécessaires à l'édition des liens d'un programme
utilisant GTK fonctionne :
$ pkg-config --libs gtk+-2.0
Ainsi, le Makefile d'un programme utilsant GTK sera du type :
default: programme
programme: programme.o
gcc -Wall -g programme.c -o programme ‘pkg-config --cflags --libs gtk+-2.0‘
Ici, comme il n'y a qu'un code source, on peut compiler et faire l'édition des liens dans la même ligne de commande, d'où la présence
des deux options --cflags et --libs.
1.2
Mise en ÷uvre sous Windows
Vous devez d'abord installer toutes les librairies, ainsi qu'un compilateur adéquate. Je recommande MinGW et l'environnement MSYS
qui fournissent un environnement GNU assez complet.
Le Makefile ressemblera beaucoup à celui sous linux, la seule différence étant que les options -fnative-struct et/ou
-mms-bitfields doivent être activées.
Attention : Les versions des librairies sont différentes pour MinGW, Cygwin où d'autres compilateurs, veillez à bien lire la
documentation.
1.3
Widgets, signaux et évènements
GTK est une librairie d'interfaçage graphique. C'est une surcouche de Glib et GDK. L'interface est composée de Widgets (exemples :
une fenêtre, un bouton, un menu,. . .). Ces objets communiquent avec l'extérieur grâce à des signaux (gérés par Glib). Lorsque
l'utilisateur clique sur un bouton par exemple, le signal correspondant va être émis. Ce signal, s'il n'est pas connecté ne va avoir
aucune influence. Pour le connecter, il faut utiliser la fonction g_signal_connect :
gulong g_signal_connect( gpointer
const gchar
GCallback
gpointer
*object,
*name,
func,
func_data );
Le premier argument est l'objet concerné, le deuxième est le nom du signal, le troisième est le pointeur sur la fonction qui doit être
appelée. Le dernier argument concerne des données eventuelles passées à la fonction.
La fonction qui doit être appelée est du type :
void callback_func( GtkWidget *widget,
gpointer
callback_data );
Les signaux qui sont liés à l'interfaçage graphique sont appelés évènements (events), ils sont gérés par GDK. En voici la liste :
2/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
event
button_press_event
button_release_event
scroll_event
motion_notify_event
delete_event
destroy_event
expose_event
key_press_event
key_release_event
enter_notify_event
leave_notify_event
configure_event
focus_in_event
focus_out_event
map_event
unmap_event
property_notify_event
Année scolaire 2003-2004
La bibliothèque GTK
selection_clear_event
selection_request_event
selection_notify_event
proximity_in_event
proximity_out_event
visibility_notify_event
client_event
no_expose_event
window_state_event
Il existe aussi des évènements liés au drag-and-drop qui sont déclenchés par le widget source ou destination :
selection_received
selection_get
drag_begin_event
drag_end_event
drag_data_delete
drag_motion
drag_drop
drag_data_get
drag_data_received
Dans le cas des évènements, on utilisera comme fonction de retour le type suivant :
gint callback_func( GtkWidget *widget,
GdkEvent *event,
gpointer
callback_data );
Exemple de connexion de l'évènement button_press_event d'un bouton à la fonction button_press_callback :
g_signal_connect (G_OBJECT (button), "button_press_event",
G_CALLBACK (button_press_callback), NULL);
1.4
Forçage de type
Dans l'exemple précédent, on utilise des macros prédéfinies G_OBJECT et G_CALLBACK pour faire des forçages de type. Par
exemple, G_CALLBACK est définie ainsi :
#define
G_CALLBACK(f)
((GCallback) (f))
Cela fait apparaître un forçage de type comme une fonction mais ne vous y trompez pas !
1.5
Exemple complet
Le code ci dessous permet de générer une interface très simple contenant une fenêtre, un bouton qui lorsque l'on
clique dessus ferme la fenêtre (capture d'écran ci-contre).
Ici, pas vraiment de surprise, on doit inclure gtk.h qui se charge lui-même d'inclure bien d'autres fichiers.
#include <gtk/gtk.h>
Définition d'une fonction de retour, ici les données passées en argument sont tout simplement ignorées.
static void hello( GtkWidget *widget,
gpointer
data )
{
g_print ("Hello World\n");
}
Dans la gestion d'un évènement de type delete_event, on doit retourner FALSE si l'on veut que l'évènement
destroy_event soit déclenché, et TRUE pour ne pas le déclencher.
Eric Guérin
[email protected]
15 décembre 2004
3/20
Année scolaire 2003-2004
La bibliothèque GTK
Bourg-en-Bresse
Première année
static gboolean delete_event( GtkWidget *widget,
GdkEvent *event,
gpointer
data )
{
g_print ("delete event occurred\n");
return TRUE;
}
Lorsque l'évènement destroy_event est capté, une bonne idée est de mettre fin au programme. . .
static void destroy( GtkWidget *widget,
gpointer
data )
{
gtk_main_quit ();
}
int main( int
argc,
char *argv[] )
{
Les deux pointeur suivants vont servir à stocker les Widgets d'une fenêtre et d'un bouton.
GtkWidget *window;
GtkWidget *button;
La fonction gtk_init doit être appelée à chaque début de programme en GTK. Elle traite les arguments en ligne
de commande destinés à GTK et initialise l'environnement. Exemple d'option en ligne de commande : --gtk-debug. Les options
destinées à GTK seront lues et supprimées de la liste.
gtk_init (&argc, &argv);
On affecte window grâce à la fonction gtk_window_new. Plusieurs types de fenêtres peuvent être créés grâce
à l'argument passé à cette fonction.
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
On connecte les évènements delete_event et destroy_event à la fenêtre grâce aux fonctions de retour
définies précédemment.
g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK (delete_event), NULL);
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (destroy), NULL);
On donne une largeur au bord de la fenêtre.
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
Création du bouton avec la connexion aux fonctions de retour.
button = gtk_button_new_with_label ("Hello World");
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (hello), NULL);
g_signal_connect_swapped (G_OBJECT (button), "clicked",
G_CALLBACK (gtk_widget_destroy),
G_OBJECT (window));
Le bouton se trouve (physiquement) dans la fenêtre.
gtk_container_add (GTK_CONTAINER (window), button);
On montre les Widgets et on appelle gtk_main qui lance le début de l'attente d'évènements.
4/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
gtk_widget_show (button);
gtk_widget_show (window);
gtk_main ();
return 0;
}
2
Positionnement de Widgets
Plutôt que de dire qu'un Widget se trouve de manière stricte à tel endroit dans une fenêtre, GTK est basé sur une hiérarchie
de conteneurs. Ces conteneurs permettent de placer les Widgets verticalement, horizontalement ou bien en tables. Des options
autorisent de modifier l'alignement des objets, et le comportement en cas de redimensionnement. Il est à noter que ce genre de
positionnement hiérarchique est maintenant très utilisé (comme dans la librairie Swing de java). Il permet de beaucoup mieux gérer
les redimensionnements de fenêtres, et par conséquent les diverses résolutions graphiques disponibles.
2.1
Positionnement vertical ou horizontal
Deux étapes sont nécessaires pour mettre en ÷uvre ce type de positionnement :
1. La création de la boîte
GtkWidget *gtk_hbox_new ( gboolean
gint
GtkWidget *gtk_vbox_new ( gboolean
gint
homogeneous,
spacing );
homogeneous,
spacing );
2. L'ajout de Widgets dans la boîte
void gtk_box_pack_start( GtkBox
*box,
GtkWidget *child,
gboolean
expand,
gboolean
fill,
guint
padding );
2.2
Positionnement en tables
Là encore, il y a deux étapes :
1. La création de la table
GtkWidget *gtk_table_new( guint
rows,
guint
columns,
gboolean homogeneous );
2. L'ajout de Widgets dans la table
void gtk_table_attach( GtkTable
GtkWidget
guint
guint
guint
guint
GtkAttachOptions
GtkAttachOptions
guint
guint
*table,
*child,
left_attach,
right_attach,
top_attach,
bottom_attach,
xoptions,
yoptions,
xpadding,
ypadding );
En créant une table de 2 lignes et 2 colonnes, les coordonnées iront de 0 à deux pour x et y. On peut donc faire déborder un widget
sur plusieurs cases du tableau.
2.3
Autres gestionnaires de positionnement
Il existe d'autres gestionnaires de positionnement, vous les aborderez en TP.
Eric Guérin
[email protected]
15 décembre 2004
5/20
Année scolaire 2003-2004
La bibliothèque GTK
3
Bourg-en-Bresse
Première année
Les boutons
3.1
Le bouton standard GtkButton
Signaux associés : activate, clicked, enter, leave, pressed et released.
Essentiellement deux fonctions permettent de créer des boutons :
GtkWidget*
GtkWidget*
gtk_button_new
gtk_button_new_with_label
(void);
(const gchar *label);
La première va créer un bouton vide, la deuxième un bouton avec un label.
Astuce : Comme le bouton est un conteneur il est possible de créer un bouton vide, puis d'ajouter une image et du texte,
arrangés grâce à une boîte par exemple.
3.2
Le bouton à mémoire GtkToggleButton
Signaux associés : activate, clicked, enter, leave, pressed, released et toggled.
Il fonctionne de la même façon que le bouton normal. Pour le créer :
GtkWidget *gtk_toggle_button_new( void );
GtkWidget *gtk_toggle_button_new_with_label( const gchar *label );
Dans une fonction de retour associée, on peut retrouver l'état du bouton en faisant ainsi :
void toggle_button_callback (GtkWidget *widget, gpointer data)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
{
/* Dans ce cas là, le bouton est appuyé */
} else {
/* Dans ce cas là, le bouton est relaché */
}
}
Pour forcer l'état du bouton :
void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
gboolean
is_active );
3.3
La case à cocher GtkCheckButton
Elle hérite beaucoup de chose de GtkToggleButton. Pour la créer :
GtkWidget *gtk_check_button_new( void );
GtkWidget *gtk_check_button_new_with_label ( const gchar *label );
3.4
Les boutons radio GtkRadioButton
Ici, le fonctionnement est légèrement différent. En effet, on parle de groupe de boutons. Au sein du
groupe, un seul des boutons peut être dans l'état appuyé au même instant. Pour créer un bouton radio :
GtkWidget *gtk_radio_button_new( GSList *group );
GtkWidget *gtk_radio_button_new_with_label( GSList *group,
const gchar *label );
La première fois, on donne comme paramètre de groupe la valeur NULL. Pour créer les autres boutons
dans le même groupe, on a le choix entre deux solutions :
1. Récupérer le groupe grâce à :
6/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
GSList *gtk_radio_button_get_group( GtkRadioButton *radio_button );
2. Utiliser l'une des deux fonctions suivantes :
GtkWidget *gtk_radio_button_new_from_widget( GtkRadioButton *group );
GtkWidget* gtk_radio_button_new_with_label_from_widget( GtkRadioButton *group,
const gchar
*label );
Astuce : Dans le deuxième cas, on évite un appel de fonction et le stockage du groupe.
4
Les Widgets ajustables
Il existe toute un série de Widgets qui peuvent être ajustés. Cela signifie qu'ils ont une propriété de type numérique que l'utilisateur ou
le programme peuvent modifier avec un changement d'aspect du Widget. L'exemple le plus connu est la barre de défilement, mais il
en existe d'autres comme la barre d'échelle. Ces Widgets ont un point commun : GtkAdjustment.
4.1
Les ajustements GtkAdjustment
Signaux associés : changed et value-changed.
Ce ne sont pas des Widgets, ce sont des objets représentant une valeur ajustable. Les propriétés qui caractérisent un ajustable sont :
1. Sa valeur
2. Sa valeur minimale
3. Sa valeur maximale
4. Son incrément
5. Son incrément de page
6. Sa largeur de page
On crée un ajustement de la manière suivante :
GtkObject*
gtk_adjustment_new (gdouble
gdouble
gdouble
gdouble
gdouble
gdouble
value,
lower,
upper,
step_increment,
page_increment,
page_size);
On peut lire et écrire la valeur grâce à :
gdouble gtk_adjustment_get_value (GtkAdjustment *adjustment);
void
gtk_adjustment_set_value (GtkAdjustment *adjustment,
gdouble value);
4.2
Les barres de défilement GtkHScrollBar et GtkVScrollBar
Comme évoqué précédemment, leur création est liée à un ajustement :
GtkWidget*
GtkWidget*
4.3
gtk_hscrollbar_new (GtkAdjustment *adjustment);
gtk_vscrollbar_new (GtkAdjustment *adjustment);
Les barres d'echelle GtkHScale et GtkVScale
Le fonctionnement est identique à celui des barres de défilement.
GtkWidget*
GtkWidget*
gtk_hscale_new (GtkAdjustment *adjustment);
gtk_vscale_new (GtkAdjustment *adjustment);
Eric Guérin
[email protected]
15 décembre 2004
7/20
Année scolaire 2003-2004
La bibliothèque GTK
5
Bourg-en-Bresse
Première année
Entrée de données
Il est important dans une interface de pouvoir rentrer des données textuelles.
5.1
Zone de texte GtkEntry
Signaux associés : activate, copy-clipboard, cut-clipboard, delete-from-cursor, insert-at-cursor, move-cursor,
paste-clipboard, populate-popup et toggle-overwrite.
Il s'agit là de la plus simple des zones de saisie de texte. On la crée avec l'une des deux fonctions
suivantes :
GtkWidget* gtk_entry_new
GtkWidget* gtk_entry_new_with_max_length
(void);
(gint max);
On peut modifier ou lire le texte avec :
void gtk_entry_set_text
(GtkEntry *entry,
const gchar *text);
gchar* gtk_entry_get_text (GtkEntry *entry);
Il existe bien d'autres fonctions. Se reporter à la documentation pour une liste exhaustive.
5.2
Zone de texte multilignes GtkTextBuffer et GtkTextView
Ces deux objets sont assez complexes, nous ne rentrerons pas dans leur détail. GtkTextBuffer permet de stocker un texte avec des
attributs de formatage (taille, police, couleur, justification,. . .). GtkTextView, comme son nom l'indique permet d'afficher le contenu
d'un GtkTextBuffer, il s'agit donc d'un Widget. Sachant que les possiblités sont assez énormes, voici uniquement un exemple simple
de mise en ÷uvre. Pour plus de détail, reportez vous à la documentation.
GtkWidget *view;
GtkTextBuffer *buffer;
view = gtk_text_view_new ();
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, "Voici du texte", -1);
En mettant tout ça dans une fenêtre on obtient :
6
Les fenêtres
Les fenêtres sont les éléments de base d'une interface graphique. Il existe des fenêtres génériques GtkWindow, mais aussi des
fenêtres ayant des fonctionnalités bien précises comme GtkDialog.
6.1
La fenêtre simple GtkWindow
Signaux associés : activate-default, activate-focus, frame-event, keys-changed, move-focus et set-focus.
Pour créer une fenêtre on utilise :
8/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
GtkWidget* gtk_window_new (GtkWindowType type);
Le type est GTK_WINDOW_TOPLEVEL ou GTK_WINDOW_POPUP. Les fenêtres du premier type sont des fenêtres normales pour
le gestionnaire de fenêtres. Les autres n'ont pas d'ornementations (barre de titre) et sont souvent ignorées par le gestionnaire de
fenêtres. On peut en faire par exemple des boîtes à outils. Lorsque la fenêtre est créée, on lui donne un nom :
void
gtk_window_set_title (GtkWindow *window,
const gchar *title);
De nombreuses fonctions permettent d'iconifier, maximiser, etc., en voici quelques exemples :
void
void
void
void
gtk_window_iconify
gtk_window_stick
gtk_window_maximize
gtk_window_fullscreen
(GtkWindow
(GtkWindow
(GtkWindow
(GtkWindow
*window);
*window);
*window);
*window);
Il existe aussi deux fonctions permettant de récupérer ou de forcer le Widget qui a le focus dans la fenêtre :
GtkWidget*
void
gtk_window_get_focus
gtk_window_set_focus
(GtkWindow *window);
(GtkWindow *window,
GtkWidget *focus);
Il existe bien d'autres fonctions, reportez-vous à la documentation.
6.2
La fenêtre de dialogue GtkDialog
Signaux associés : close et response.
Il s'agit d'une fenêtre de type Popup. Ce n'est pas une fenêtre principale, elle est en général appelée par une autre fenêtre et permet
d'obtenir une réponse à une question simple. GtkDialog offre une interface commune aux boîtes de dialogue. Pour créer une boîte de
dialogue :
GtkWidget* gtk_dialog_new (void);
GtkWidget* gtk_dialog_new_with_buttons (const gchar *title,
GtkWindow *parent,
GtkDialogFlags flags,
const gchar *first_button_text,
gint first_response_id,
...);
Le deuxième fonction permet d'ajouter directement des boutons ainsi qu'un titre. Elle est donc à privilégier. Les valeurs
possibles pour flags sont une combinaison logique de GTK_DIALOG_MODAL, GTK_DIALOG_DESTROY_WITH_PARENT et
GTK_DIALOG_NO_SEPARATOR. Voir la documentation. pour plus de détails. first_button_text peut être une référence à un
StockItem, soit directement le texte a insérer à l'intérieur du bouton. En complément à ce texte, on donne un identificateur de réponse
qui sera renvoyé si l'utilisateur clique sur le bouton en question. Gtk a prédéfini plusieurs constantes d'identificateurs de réponse :
GTK_RESPONSE_NONE
GTK_RESPONSE_REJECT
GTK_RESPONSE_ACCEPT
GTK_RESPONSE_DELETE_EVENT
GTK_RESPONSE_OK
GTK_RESPONSE_CANCEL
GTK_RESPONSE_CLOSE
GTK_RESPONSE_YES
GTK_RESPONSE_NO
GTK_RESPONSE_APPLY
GTK_RESPONSE_HELP
On peut ajouter autant de boutons que l'on veut en rajoutant des paires d'arguments à la fonction gtk_dialog_new_with_buttons.
Une fois que le dialogue est créé, on peut le lancer, et récupérer le résultat (c'est à dire l'identificateur du bouton qui a été validé) :
gint gtk_dialog_run (GtkDialog *dialog);
Eric Guérin
[email protected]
15 décembre 2004
9/20
Année scolaire 2003-2004
La bibliothèque GTK
6.3
Bourg-en-Bresse
Première année
Affichage d'un message GtkMessageDialog
Dans une boîte de dialogue du type GtkMessageDialog, le but est d'afficher un message destiné à l'utilisateur, et de récupérer
éventuellement une réponse. La création d'une telle fenêtre se fait grâce à :
GtkWidget* gtk_message_dialog_new
(GtkWindow *parent,
GtkDialogFlags flags,
GtkMessageType type,
GtkButtonsType buttons,
const gchar *message_format,
...);
Le paramètre type permet de donner une sémantique à la boîte de dialogue, il peut prendre les valeurs suivantes :
GTK_MESSAGE_INFO, GTK_MESSAGE_WARNING, GTK_MESSAGE_QUESTION, GTK_MESSAGE_ERROR. Le paramètre buttons
permet de gérer les boutons qui vont être automatiquement ajoutés à la boîte de dialogue. Il peut prendre les valeurs suivantes : GTK_BUTTONS_NONE, GTK_BUTTONS_OK, GTK_BUTTONS_CLOSE, GTK_BUTTONS_CANCEL, GTK_BUTTONS_YES_NO
ou GTK_BUTTONS_OK_CANCEL. Le paramètre message_format permet de décrire le format du message à afficher dans le style
de printf.
Le code suivant est une fonction de retour associée au signal delete d'une fenêtre. Une boîte de dialogue est ouverte, demandant
de confirmer cette fermeture. Si la réponse est GTK_RESPONSE_YES, alors la fonction renvoie FALSE, ce qui provoque l'évènement
destroy.
gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data)
{
GtkWidget * dialog;
gint reponse;
dialog = gtk_message_dialog_new (GTK_WINDOW(widget),
GTK_DIALOG_MODAL,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
"Etes-vous sur de vouloir quiter ?");
reponse = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
if (reponse==GTK_RESPONSE_YES)
return FALSE;
else
return TRUE;
}
La boîte de dialogue affichée ressemblera à :
6.4
Sélection d'un fichier GtkFileSelection
On crée ce type de dialogue avec la fonction :
GtkWidget* gtk_file_selection_new (const gchar *title);
Auncun signal n'est associé à cette boite de dialogue (elle n'est pas basée sur GtkDialog d'ailleurs). Pour la faire fonctionner, il faut
faire comme avec un Widget normal, c'est à dire gtk_widget_show. Avant cela, il faut connecter le clic sur les boutons ok et cancel
à des fonctions de retour :
10/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
g_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_selector)->ok_button),
"clicked",
G_CALLBACK (store_filename),
(gpointer) file_selector);
On ne peut pas se servir du Widget appelant pour récupérer le nom du fichier, c'est pourquoi on a ajouté comme données de la
fonction de retour file_selector. Ainsi, dans la fonction de retour on pourra faire appel à la fonction suivante :
const gchar *selected_filename;
selected_filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector));
Attention : On n'oubliera pas de fermer la boîte de dialogue lorsque l'utilisateur clique sur ok ou sur cancel.
Voici un exemple de fenêtre :
6.5
Les boîtes de dialogue GtkColorSelectionDialog et GtkFontSelectionDialog
Il s'agit de deux boîtes de dialogue permettant respectivement de selectionner une couleur et une fonte. Pour les créer :
GtkWidget* gtk_color_selection_dialog_new (const gchar *title);
GtkWidget* gtk_font_selection_dialog_new (const gchar *title);
Chacun de ces dialogues contient comme propriété les trois boutons ok_button, cancel_button et help_button dont il faudra
connecter les évènement clicked. En complément, il est bien sûr possible de récupérer la couleur et la fonte sélectionnées. Dans le
premier cas, il faut utiliser la propriété colorsel du type GtkColorSelection et la fonction associée :
void gtk_color_selection_get_current_color
(GtkColorSelection *colorsel,
GdkColor *color);
Dans le deuxième cas, un accès direct a été prévu :
GdkFont* gtk_font_selection_dialog_get_font
(GtkFontSelectionDialog *fsd);
Astuce : On peut aussi connecter le Widget colorsel à des évènements comme color-changed. Dans ce cas là,
l'utilisateur pourra avoir une prévisualisation des modifications qu'il a apportées.
7
Les éléments d'affichage
Les éléments d'affichage sont des Widgets qui n'ont pas d'interaction avec l'utilisateur, ils n'ont donc pas ou peu de signaux associés.
Eric Guérin
[email protected]
15 décembre 2004
11/20
Année scolaire 2003-2004
La bibliothèque GTK
7.1
Bourg-en-Bresse
Première année
Le texte GtkLabel
Signaux associés : copy-clipboard, move-cursor et populate-popup.
Il s'agit d'un texte non modifiable par l'utilisateur. On peut simplement par programme donner une valeur à ce texte, ainsi que des
attributs comme la fonte utilisée. Pour créer une label et modifier son texte :
GtkWidget* gtk_label_new
(const char *str);
void
gtk_label_set_text (GtkLabel *label,
const char *str);
Pour modifier les attributs de fontes :
void gtk_label_set_attributes (GtkLabel *label,
PangoAttrList *attrs);
Référez vous à la documentation pour connaître la construction d'une liste d'attributs. Il existe une fonction qui permet d'insérer
beaucoup plus facilement du texte avec des attributs de mise en forme :
void gtk_label_set_markup (GtkLabel *label,
const gchar *str);
qui prend comme paramètre une chaîne de caractères contenant des balises. Exemple : "<b>Texte</b>" pour mettre en gras.
La justification du texte ne fait pas partie des attributs Pango, pour régler celle-ci, il faudra utiliser :
void gtk_label_set_justify (GtkLabel *label,
GtkJustification jtype);
Où jtype prend l'une des valeurs suivantes : GTK_JUSTIFY_LEFT, GTK_JUSTIFY_RIGHT, GTK_JUSTIFY_CENTER ou
GTK_JUSTIFY_FILL.
7.2
Une image GtkImage
GtkImage permet d'afficher une image. Dans la théorie, cette image doit être mise dans un buffer grâce à l'objet GtkPixBuf. En pratique,
une fonction permet de court-circuiter cette étape et directement charger une image depuis son nom de fichier :
GtkWidget* gtk_image_new_from_file (const gchar *filename);
Les deux étapes qu'effectue cette fonction sont :
GdkPixbuf* gdk_pixbuf_new_from_file (const char *filename,
GError **error);
GtkWidget* gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf);
Attention : Vous aurez remarqué que lorsqu'on utilise la fonction raccourcie, la gestion d'erreur n'est pas faite. Ainsi, si le
fichier n'existe pas une image spéciale montrant que le fichier n'a pas été trouvé sera mise à la place de l'image. Il n'y a donc
pas de contrôle logiciel possible.
7.3
La barre de progression GtkProgressBar
Très importante lorsqu'un élément de programmation est susceptible de prendre du temps, elle permet d'indiquer à l'utilisateur la
progression de la tâche en question par un indicateur visuel. Pour la créer, on utilise :
GtkWidget* gtk_progress_bar_new (void);
Ensuite, pour indiquer à l'utilisateur où l'on en est, il existe deux méthodes qui sont complémentaires. La première consiste à donner
la fraction écoulée :
void gtk_progress_bar_set_fraction (GtkProgressBar *pbar,
gdouble fraction);
où fraction est compris entre 0 et 1 (inclus). La deuxième consiste à superposer à la barre un texte :
12/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
void gtk_progress_bar_set_text (GtkProgressBar *pbar,
const gchar *text);
On pourra par exemple indiquer dans cette zone un pourcentage associé à la fraction :
8
Les listes et arbres
L'affichage de listes et d'arbres est modulaire. Son concept tourne autour de deux objets, l'un représentant les données (GtkTreeModel)
et l'autre la vue de ces données (GtkTreeView). Entre ces deux objets viennent s'interposer deux autres objets qui vont rendre
plus souple l'affichage : un objet de regroupement de colonnes (GtkTreeViewColumn) et un gestionnaire d'affichage de cellule
(GtkCellRenderer). L'avantage évident de cette conception modulaire est l'affichage multiple d'un même modèle. Les modèles sont de
deux types : listes simples (GtkListStore) et arbres (GtkTreeStore).
8.1
Le modèle de liste GtkListStore
Il se crée ainsi :
GtkListStore* gtk_list_store_new (gint n_columns,
...);
n_columns représente le nombre de colonnes, les arguments suivants sont les types des colonnes. Par exemple : G_TYPE_INT,
G_TYPE_LONG, G_TYPE_ENUM, G_TYPE_FLOAT, G_TYPE_DOUBLE, G_TYPE_STRING, etc. Voir la documentation pour plus de
renseignements. Une fois que la liste est créée, il faut ajouter des données. Pour cela, il faut se positionner dans la liste. Ceci se fait
grâce à un itérateur GtkTreeIter. Pour créer celui-ci :
void gtk_list_store_append (GtkListStore *list_store,
GtkTreeIter *iter);
Dans cet exemple, l'itérateur est positionné à la fin de la liste, et une nouvelle ligne est créée. Pour ajouter une ligne au début, il faut
utiliser gtk_list_store_prepend. On peut aussi insérer à une position précise :
void gtk_list_store_insert(GtkListStore *list_store,
GtkTreeIter *iter,
gint position);
Bien d'autres possibilités sont envisageables, voir la documentation. Une fois positionné, on change la valeur grâce à :
void gtk_list_store_set (GtkListStore *list_store,
GtkTreeIter *iter,
...);
Les ... représentent des paires numéro/valeur de la colonne. À la fin, on ajoute un -1. Exemple :
/* création d’un type énuméré pour faciliter
le nommage des colonnes */
enum
{
TITLE_COLUMN,
AUTHOR_COLUMN,
CHECKED_COLUMN,
N_COLUMNS
};
/* création de la liste */
Eric Guérin
[email protected]
15 décembre 2004
13/20
Année scolaire 2003-2004
La bibliothèque GTK
Bourg-en-Bresse
Première année
GtkListStore *store = gtk_list_store_new (N_COLUMNS,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
/* création d’un ligne, et positionnement de l’itérateur */
gtk_list_store_append (store, &iter);
/* définition des trois colonnes */
gtk_list_store_set (store, &iter,
TITLE_COLUMN, "The Principle of Reason",
AUTHOR_COLUMN, "Martin Heidegger",
CHECKED_COLUMN, FALSE
-1);
8.2
Le modèle d'arbre GtkTreeStore
Le fonctionnement est très proche mais avec le concept de hiérarchie. Pour créer un arbre :
GtkTreeStore* gtk_tree_store_new (gint n_columns,
...);
Pour acquérir un itérateur, on va cette fois ci utiliser un troisième argument dans la fonction gtk_tree_store_append par exemple.
Celui-ci correspond à l'itérateur père. Exemple :
/* création de l’arbre */
GtkTreeStore *store = gtk_tree_store_new (N_COLUMNS,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
/* acquisition d’un itérateur au niveau supérieur */
gtk_tree_store_append (store, &iter1, NULL);
gtk_tree_store_set (store, &iter1,
TITLE_COLUMN, "The Art of Computer Programming",
AUTHOR_COLUMN, "Donald E. Knuth",
CHECKED_COLUMN, FALSE,
-1);
/* acquisition d’unitérateur fils */
gtk_tree_store_append (store, &iter2, &iter1);
gtk_tree_store_set (store, &iter2,
TITLE_COLUMN, "Volume 1: Fundamental Algorithms",
-1);
8.3
Composant de visualisation GtkTreeView
C'est le composant (widget) qui est associé à un modèle de données. Pour le créer, il faut tout simplement faire :
GtkWidget *tree;
tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
Une fois que l'association est faite, il suffit de décrire comment doivent être rendue visuellement les cellules.
8.4
Rendu de cellules
Il existe trois types de rendu de cellules par défaut : GtkCellRendererText pour du texte, GtkCellRendererPixbuf pour une image et
GtkCellRendererToggle pour une case à cocher. Il est possible de créer soi-même un objet de rendu de cellules, nous n'en parlerons
14/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
pas ici. Ces objets de rendu sont groupés en colonnes grâce à GtkTreeViewColumn. Ce dernier va contenir le nom de la colonne à
afficher, quel type de rendu il faut utiliser, et quelles sont les données associées. Voici un exemple simple :
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Author",
renderer,
"text", AUTHOR_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column));
8.5
Association de signaux
Lorsque l'on ne veut pas uniquement afficher des données mais avoir une interraction réelle avec l'utilisateur, on peut utiliser l'objet
GtkTreeSelection, qui va permettre de gérer des signaux comme changed. Voir la documentation pour plus de détails.
9
Les menus
Il y a deux façons de faire des menus. La première est la plus complète mais un peu plus complexe, la deuxième est plus simple mais
a moins de fonctionnalités.
9.1
Création de menus à la main
Un menu comporte 3 composants imbriqués les uns dans les autres :
1. Un élément de menu (par exemple « Enregistrer sous... »)
2. Un menu (par exemple le menu Fichier)
3. Une barre de menu contenant tous les menus
Les étapes pour créer un menu complet sont les suivantes :
Créer un nouveau menu avec gtk_menu_new()
Créer les éléments qui vont apparaître dans ce menu grâce à plusieurs appels à gtk_menu_item_new()
Créer un élément de menu qui va être la racine du menu avec gtk_menu_item_new()
Attacher l'élément racine du menu avec le menu avec gtk_menu_item_set_submenu()
Créer une barre de menu avec gtk_menu_bar_new
Attacher la barre de menu à l'élément racine avec gtk_menu_bar_append()
Pour un exemple complet de mise en ÷uvre, consultez le tutorial GTK+-2.0.
9.2
Création de menus grâce à GtkItemFactory
Grâce à une structure prédéfinie (GtkItemFactoryEntry), le widget GtkItemFactory va créer automatiquement tous les menus, éléments,
et la barre de menu. La structure GtkItemFactoryEntry est définie ainsi :
struct GtkItemFactoryEntry
{
gchar *path;
gchar *accelerator;
GtkItemFactoryCallback callback;
guint
callback_action;
gchar
*item_type;
};
Voici la signification de chacun des éléments de la structure :
path est une chaîne de caractère contenant le chemin pour accéder au menu
Eric Guérin
[email protected]
15 décembre 2004
15/20
Année scolaire 2003-2004
La bibliothèque GTK
Bourg-en-Bresse
Première année
accelerator est une chaîne contenant le raccourci clavier associé au menu
callback est la fonction associée au menu
callback_action est un entier qui est communiqué à la fonction de callback
item_type est une chaîne de caractère donnant le type de l'élément de menu
Si callback_action est égal à 0, alors la fonction de callback a la forme suivante :
void callback(void);
Sinon, voici sa forme :
void callback( gpointer
guint
GtkWidget
callback_data,
callback_action,
*widget );
La touche de raccourci est tout simplement la touche (exemple "a" pour la touche a) avec des éventuels modificateurs comme
<ALT>, <CTRL> ou <SHIFT>.
Les types d'éléments sont les suivants :
NULL ou "" ou "<Item>"
"<Title>"
"<CheckItem>"
"<ToggleItem>"
"<RadioItem>"
"Path"
"<Tearoff>"
"<Separator>"
"<StockItem>"
-
un
un
un
un
un
un
un
un
un
simple élément
élément de titre
élément à cocher
élément à bascule
élément radio
élément radio jumelé avec un autre
élément détachable
élément séparateur
élément avec une image
Un exemple complet de création de menu par GtkItemFactory peut être trouvé dans le tutorial GTK+-2.0.
10
Les zones de dessin
10.1 Mise en ÷uvre
On utilise le Widget GtkDrawingArea pour faire des opérations graphiques librement. On crée une zone de dessin avec :
GtkWidget*
gtk_drawing_area_new (void);
Une fois que la zone est créée, il faut bien penser à trois choses :
Connecter au signal realize qui sera déclenché à chaque instanciation sur un affichage. Â ce genre de signal, on associe en
général une allocation de ressources. Par exemple, la création d'un buffer d'affichage.
Connecter au signal configure qui est appelé quand le Widget reçoit une requête de changement de taille.
Connecter au signal expose qui est appelé quand le Widget doit être retracé. Celui-ci sera appelé quand la fenêtre est minimisée
puis remaximisée.
En plus de ces trois signaux, on peut vouloir de l'interaction entre la souris et la zone de dessin. Dans ce cas, on utilisera la fonction
gtk_widget_add_events :
void gtk_widget_add_events (GtkWidget *widget,
gint events);
10.2 Primitives de dessin
Pour tracer du contenu dans la zone de dessin, on utilise la propriété window de celle-ci. Grâce à elle, on a la possibilité d'utiliser toutes
les fonctions de la bibliothèque GDK. Les primitives de dessin GDK prennent toujours deux paramètres : un de type GdkDrawable (qui
va être la propriété window) et le deuxième du type GdkGC. Ce dernier indique le contexte graphique (Graphic Context) dans lequel
on se situe. Il est attaché à un objet de type GdkDrawable. On le crée des deux manières suivantes :
GdkGC* gdk_gc_new
(GdkDrawable *drawable);
GdkGC* gdk_gc_new_with_values (GdkDrawable *drawable,
GdkGCValues *values,
GdkGCValuesMask values_mask);
16/20
15 décembre 2004
Eric Guérin
[email protected]
Bourg-en-Bresse
Première année
Année scolaire 2003-2004
La bibliothèque GTK
La deuxième manière permet de donner des valeurs au contexte graphique (couleurs de traits, style de traits, etc.). Voir la documentation
de GdkGCValues pour plus de détails. Pour éviter de créer ces contextes graphiques, on peut utiliser de manière plus simple les
contextes graphiques par défaut qui existent pour tous les widgets. Pour cela, on utilise la propriété style du widget, qui contient elle
même des tableaux de contextes :
GdkGC
GdkGC
GdkGC
GdkGC
GdkGC
GdkGC
GdkGC
GdkGC
*fg_gc[5];
*bg_gc[5];
*light_gc[5];
*dark_gc[5];
*mid_gc[5];
*text_gc[5];
*base_gc[5];
*text_aa_gc[5];
et des contextes :
GdkGC *black_gc;
GdkGC *white_gc;
Dans l'exemple suivant, widget est un GtkDrawingArea dans lequel on trace un cercle :
gdk_draw_arc (widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
TRUE,
0, 0, widget->allocation.width, widget->allocation.height,
0, 64 * 360);
Voici maintenant une liste de primitives simples :
Tracer un point
void gdk_draw_point (GdkDrawable *drawable,
GdkGC *gc,
gint x,
gint y);
Tracer une ligne
void gdk_draw_line (GdkDrawable *drawable,
GdkGC *gc,
gint x1_,
gint y1_,
gint x2_,
gint y2_);
Tracer un arc de cercle
void gdk_draw_arc (GdkDrawable *drawable,
GdkGC *gc,
gboolean filled,
gint x,
gint y,
gint width,
gint height,
gint angle1,
gint angle2);
Tracer un polygône
gdk_draw_polygon (GdkDrawable *drawable,
GdkGC *gc,
gboolean filled,
GdkPoint *points,
gint npoints);
Copie une portion d'un autre GdkDrawable
void gdk_draw_drawable (GdkDrawable *drawable,
Eric Guérin
[email protected]
15 décembre 2004
17/20
Année scolaire 2003-2004
La bibliothèque GTK
Bourg-en-Bresse
Première année
GdkGC *gc,
GdkDrawable *src,
gint xsrc,
gint ysrc,
gint xdest,
gint ydest,
gint width,
gint height);
Pour d'autres primitives de dessin, voir documentation de GDK.
10.3 Utilisation d'un buffer de visualisation
Dans la dernière fonction qui a été présentée, gtk_draw_drawable, on voit qu'il est possible de disposer d'un autre objet de type
GdkDrawable, dans lequel on peut donc dessiner, mais que ne sera pas rendu directement. Ceci peut servir à faire des opérations
graphiques plus complexes, qui vont cacher le fait qu'elle sont longues, et ne les afficher qu'à la fin lorsqu'elles sont terminées. C'est
ce que l'on appelle un buffer d'affichage. Dans l'autre sens, cette opération peut servir à sauvegarder l'image pour pouvoir la réafficher
plus tard sans réutiliser toutes les primitives de dessin (lorsqu'un signal expose intervient par exemple).
10.4 Exemple
Voici un exemple qui se contente de connecter la zone de dessin à une fonction d'affichage d'un cercle lorsque le signal expose est
appelé.
gboolean
expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
gdk_draw_arc (widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
TRUE,
0, 0,
widget->allocation.width,
widget->allocation.height,
0, 64 * 360);
return TRUE;
}
[..]
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_widget_set_size_request (drawing_area, 100, 100);
g_signal_connect (G_OBJECT (drawing_area), "expose_event",
G_CALLBACK (expose_event_callback), NULL);
18/20
15 décembre 2004
Eric Guérin
[email protected]
Index
GtkAdjustment, 7
gtk_adjustment_get_value, 7
gtk_adjustment_new, 7
gtk_adjustment_set_value, 7
ajustables, 7
gtk_image_new_from_pixbuf, 12
gtk_init, 4
GtkItemFactory, 15
GtkLabel, 12
gtk_label_new, 12
gtk_label_set_attributes, 12
gtk_label_set_justify, 12
gtk_label_set_markup, 12
gtk_label_set_text, 12
Liste des signaux, 2
GtkListStore, 13
gtk_list_store_append, 13
gtk_list_store_insert, 13
gtk_list_store_new, 13
gtk_list_store_set, 13
gtk_box_pack_start, 5
GtkButton, 6
gtk_button_new, 6
gtk_button_new_with_label, 6
GtkCellRenderer, 14
GtkCheckButton, 6
gtk_check_button_new, 6
gtk_check_button_new_with_label, 6
GtkColorSelectionDialog, 11
gtk_container_add, 4
gtk_main, 4
gtk_main_quit, 4
Makefile, 2
gtk_menu_bar_append, 15
gtk_menu_bar_new, 15
gtk_menu_item_new, 15
gtk_menu_item_set_submenu, 15
gtk_menu_new, 15
GtkMessageDialog, 10
gtk_message_dialog_new, 10
MinGW, 2
GtkDialog, 9
gtk_dialog_new, 9
gtk_dialog_new_with_buttons, 9
gtk_dialog_run, 9
GdkDrawable, 16
gdk_draw_arc, 17
gdk_draw_drawable, 17
GtkDrawingArea, 16
gtk_drawing_area_new, 16
gdk_draw_line, 17
gdk_draw_point, 17
gdk_draw_polygon, 17
gdk_pixbuf_new_from_file, 12
pkg-config, 2
GtkProgressBar, 12
gtk_progress_bar_new, 12
gtk_progress_bar_set_fraction, 12
gtk_progress_bar_set_text, 12
GtkEntry, 8
gtk_entry_get_text, 8
gtk_entry_new, 8
gtk_entry_set_text, 8
Exemple complet, 3
GtkRadioButton, 6
gtk_radio_button_get_group, 6
gtk_radio_button_new, 6
gtk_radio_button_new_from_widget, 7
gtk_radio_button_new_with_label, 6
GtkFileSelection, 10
gtk_file_selection_get_filename, 11
GtkFontSelectionDialog, 11
Forçage de type, 3
GtkTable, 5
gtk_table_attach, 5
gtk_table_new, 5
GtkTextBuffer, 8
gtk_text_buffer_set_text, 8
GtkTextView, 8
gtk_text_view_get_buffer, 8
gtk_text_view_new, 8
GtkToggleButton, 6
gtk_toggle_button_get_active, 6
gtk_toggle_button_new, 6
gtk_toggle_button_new_with_label, 6
gdk_gc_new, 16
g_signal_connect, 2
GtkHBox, 5
gtk_hbox_new, 5
GtkHScale, 7
gtk_hscale_new, 7
GtkHScrollBar, 7
gtk_hscrollbar_new, 7
GtkImage, 12
gtk_image_new_from_file, 12
19
Année scolaire 2003-2004
La bibliothèque GTK
Bourg-en-Bresse
Première année
gtk_toggle_button_set_active, 6
GtkTreeStore, 14
gtk_tree_store_append, 14
gtk_tree_store_new, 14
GtkTreeView, 14
gtk_tree_view_new_with_model, 14
GtkVBox, 5
gtk_vbox_new, 5
gtk_vscale_new, 7
GtkVScrollBar, 7
gtk_vscrollbar_new, 7
gtk_widget_add_events, 16
gtk_widget_show, 4
GtkWindow, 8
gtk_window_new, 4, 8
windows, 2
gtk_window_set_title, 9
20/20
15 décembre 2004
Eric Guérin
[email protected]
Téléchargement