IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Cours GTK 2

Date de publication : 20 Février 2007



Les entrées de saisie

Vous pouvez à présent faire interagir l'utilisateur avec des boutons, mais il peut aussi être utile de lui faire saisir des données. Nous allons utiliser pour cela le widget GtkEntry qui défini une zone de texte (une ligne) dans lequel l'utilisateur peut taper du texte ou alors dans lequel le programme peut afficher une information.

1. Création et utilisation d'un GtkEntry

1.1 Création

Pour créer un GtkEntry, nous avons à notre disposition deux fonctions différentes :

GtkWidget* gtk_entry_new(void);
GtkWidget* gtk_entry_new_with_max_length(gint max);

La première fonction crée un widget GtkEntry de base, tandis que la seconde permet en plus de définir le nombre maximum de caractère que l'utilisateur peut taper (paramètre max de type gint).

1.2 Utilisation

Nous allons maintenant comment utiliser les deux fonctions principales de ce widget.

void gtk_entry_set_text(GtkEntry *entry, const gchar *text);
G_CONST_RETURN gchar* gtk_entry_get_text(GtkEntry *entry);

La première fonction nous permet d'insérer du texte dans le GtkEntry. Le paramètre entry correspond bien sur au GtkEntry dans lequel on veut insérer le texte text. A noter, que cette fonction nécessite que entry soit de type GtkEntry*, il faudra donc utiliser la macro de conversion GTK_ENTRY().

La deuxième fonction permet de récupérer le texte qui a été tapé par l'utilisateur dans le GtkEntry entry. La valeur de retour est de type G_CONST_RETURN gchar*, c'est à dire qu'il faudra récupérer le texte dans une variable de type const gchar*. De plus, il est inutile d'allouer de la mémoire pour la variable qui va recevoir le texte, et donc de ne surtout pas libérer la mémoire car cela rendrait votre application instable.

1.3 Exemple

Comme exemple, nous allons créer une fenêtre comportant un GtkEntry, un GtkButton et un GtkLabel. Le but sera d'afficher le texte du GtkEntry dans le GtkLabel. Cette opération s'effectuera lorsque l'utilisateur appuie sur la touche ENTREE à la fin de sa saisie (interception du signal "activate") ou lorsqu'il cliquera sur le GtkButton (interception du signal "clicked").

Ensuite, les fonctions callback récupèreront le texte du GtkEntry pour l'afficher dans le GtkLabel. Si cette opération ne pose aucun problème pour le signal "activate" du GtkEntry, un problème existe lorsque l'on clique sur le GtkButton.

En effet, pour faire son travail correctement, la fonction callback doit connaître le GtkEntry et le GtkLabel. Dans le cas du signal "activate", le GtkEntry est envoyé en paramètre principal de la fonction callback (widget émetteur du signal) et l'on rajoute le GtkLabel en paramètre supplémentaire. Par contre, pour le signal "clicked", le widget émetteur est le GtkButton et l'on ne pourra passer qu'un seul widget en donnée supplémentaire.

La solution consiste à utiliser les listes du chapitre précédent (VII. Les listes chaînées) ainsi qu'une fonction du widget GtkContainer :

GList* gtk_container_get_children(GtkContainer *container);

Cette fonction crée une liste doublement chaînée contenant tous les widgets qui ont été insérés dans le widget container. Dans notre cas, il nous suffira de passer la GtkBox contenant tous les widgets à la fonction callback pour avoir accès à tout ce dont nous avons besoin.

1.4 Programme exemple

#include <stdlib.h>
#include <gtk/gtk.h>

void on_activate_entry(GtkWidget *pEntry, gpointer data);
void on_copier_button(GtkWidget *pButton, gpointer data);

int main(int argc, char **argv)
{
    GtkWidget *pWindow;
    GtkWidget *pVBox;
    GtkWidget *pEntry;
    GtkWidget *pButton;
    GtkWidget *pLabel;

    gtk_init(&argc, &argv);

    pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(pWindow), "Le widget GtkEntry");
    gtk_window_set_default_size(GTK_WINDOW(pWindow), 320, 200);
    g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL);

    pVBox = gtk_vbox_new(TRUE, 0);
    gtk_container_add(GTK_CONTAINER(pWindow), pVBox);

    /* Creation du GtkEntry */
    pEntry = gtk_entry_new();
    /* Insertion du GtkEntry dans la GtkVBox */
    gtk_box_pack_start(GTK_BOX(pVBox), pEntry, TRUE, FALSE, 0);

    pButton = gtk_button_new_with_label("Copier");
    gtk_box_pack_start(GTK_BOX(pVBox), pButton, TRUE, FALSE, 0);

    pLabel = gtk_label_new(NULL);
    gtk_box_pack_start(GTK_BOX(pVBox), pLabel, TRUE, FALSE, 0);

    /* Connexion du signal "activate" du GtkEntry */
    g_signal_connect(G_OBJECT(pEntry), "activate", G_CALLBACK(on_activate_entry), (GtkWidget*) pLabel);

    /* Connexion du signal "clicked" du GtkButton */
    /* La donnee supplementaire est la GtkVBox pVBox */

    g_signal_connect(G_OBJECT(pButton), "clicked", G_CALLBACK(on_copier_button), (GtkWidget*) pVBox);

    gtk_widget_show_all(pWindow);

    gtk_main();

    return EXIT_SUCCESS;
}

/* Fonction callback execute lors du signal "activate" */
void on_activate_entry(GtkWidget *pEntry, gpointer data)
{
    const gchar *sText;

    /* Recuperation du texte contenu dans le GtkEntry */
    sText = gtk_entry_get_text(GTK_ENTRY(pEntry));

    /* Modification du texte contenu dans le GtkLabel */
    gtk_label_set_text(GTK_LABEL((GtkWidget*)data), sText);
}

/* Fonction callback executee lors du signal "clicked" */
void on_copier_button(GtkWidget *pButton, gpointer data)
{
    GtkWidget *pTempEntry;
    GtkWidget *pTempLabel;
    GList *pList;
    const gchar *sText;

    /* Recuperation de la liste des elements que contient la GtkVBox */
    pList = gtk_container_get_children(GTK_CONTAINER((GtkWidget*)data));

    /* Le premier element est le GtkEntry */
    pTempEntry = GTK_WIDGET(pList->data);

    /* Passage a l element suivant : le GtkButton */
    pList = g_list_next(pList);

    /* Passage a l element suivant : le GtkLabel */
    pList = g_list_next(pList);

    /* Cet element est le GtkLabel */
    pTempLabel = GTK_WIDGET(pList->data);

    /* Recuperation du texte contenu dans le GtkEntry */
    sText = gtk_entry_get_text(GTK_ENTRY(pTempEntry));

    /* Modification du texte contenu dans le GtkLabel */
    gtk_label_set_text(GTK_LABEL(pTempLabel), sText);

    /* Liberation de la memoire utilisee par la liste */
    g_list_free(pList);
}

Résultat :

2. Saisie d'un mot de passe

2.1 La visibilité du texte

Généralement, lorsque nous tapons un mot de passe, nous souhaitons que celui-ci reste secret. Le widget GtkEntry permet cela grâce à cette fonction :

void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible);

Il suffit donc de mettre le paramètre visible à FALSE pour cacher le texte qui sera entré.

A l'inverse, pour savoir si le texte entré sera visible ou pas, il faut utiliser cette fonction :

gboolean gtk_entry_get_visibility(GtkEntry *entry);

La valeur de retour sera, bien sûr, égale à TRUE si le texte est visible et à FALSE dans le cas contraire.

2.2 Le caractère affiché

Par défaut, lorsque l'on ajoute du texte à un GtkEntry qui a son paramètre visible à FALSE, GTK+ remplacera toutes les lettres par des '*'. Pour modifier celui-ci, il faut utiliser cette fonction :

void gtk_entry_set_invisible_char(GtkEntry *entry, gunichar ch);

Le paramètre ch correspond au caractère de remplacement que nous souhaitons. Celui-ci est de type gunichar qui correspond à l'encodage UCS-4. Bien que l'affichage de GTK+ se fasse avec l'encodage UTF-8, cela ne pose aucun problème car cette fois-ci, la conversion est faite automatiquement.

Et pour terminer, la fonction permettant de connaître le caractère de remplacement est :

gunichar gtk_entry_get_invisble_char(GtkEntry *entry);

2.3 Exemple

Cette fois, nous allons reprendre l'exemple précédent en activant le mode "mot de passe" et en limitant la saisie à huit caractères. Nous modifierons aussi le caractère de remplacement '*' par '$'.

2.4 Programme exemple

#include <stdlib.h>
#include <gtk/gtk.h>

void on_activate_entry(GtkWidget *pEntry, gpointer data);
void on_copier_button(GtkWidget *pButton, gpointer data);

int main(int argc, char **argv)
{
    GtkWidget *pWindow;
    GtkWidget *pVBox;
    GtkWidget *pEntry;
    GtkWidget *pButton;
    GtkWidget *pLabel;

    gtk_init(&argc, &argv);

    pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(pWindow), "Le widget GtkEntry");
    gtk_window_set_default_size(GTK_WINDOW(pWindow), 320, 200);
    g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(gtk_main_quit), NULL);

    pVBox = gtk_vbox_new(TRUE, 0);
    gtk_container_add(GTK_CONTAINER(pWindow), pVBox);

    /* Creation du GtkEntry avec 8 caracteres maximum */
    pEntry = gtk_entry_new_with_max_length(8);
    /* Mode mot de passe */
    gtk_entry_set_visibility(GTK_ENTRY(pEntry), FALSE);
    /* Modification du caractere affiche */
    gtk_entry_set_invisible_char(GTK_ENTRY(pEntry), '$');
    /* Insertion du GtkEntry dans la GtkVBox */
    gtk_box_pack_start(GTK_BOX(pVBox), pEntry, TRUE, FALSE, 0);

    pButton = gtk_button_new_with_label("Copier");
    gtk_box_pack_start(GTK_BOX(pVBox), pButton, TRUE, FALSE, 0);

    pLabel = gtk_label_new(NULL);
    gtk_box_pack_start(GTK_BOX(pVBox), pLabel, TRUE, FALSE, 0);

    /* Connexion du signal "activate" du GtkEntry */
    g_signal_connect(G_OBJECT(pEntry), "activate", G_CALLBACK(on_activate_entry), (GtkWidget*) pLabel);

    /* Connexion du signal "clicked" du GtkButton */
    /* La donnee supplementaire est la GtkVBox pVBox */

    g_signal_connect(G_OBJECT(pButton), "clicked", G_CALLBACK(on_copier_button), (GtkWidget*) pVBox);

    gtk_widget_show_all(pWindow);

    gtk_main();

    return EXIT_SUCCESS;
}

/* Fonction callback execute lors du signal "activate" */
void on_activate_entry(GtkWidget *pEntry, gpointer data)
{
    const gchar *sText;

    /* Recuperation du texte contenu dans le GtkEntry */
    sText = gtk_entry_get_text(GTK_ENTRY(pEntry));

    /* Modification du texte contenu dans le GtkLabel */
    gtk_label_set_text(GTK_LABEL((GtkWidget*)data), sText);
}

/* Fonction callback executee lors du signal "clicked" */
void on_copier_button(GtkWidget *pButton, gpointer data)
{
    GtkWidget *pTempEntry;
    GtkWidget *pTempLabel;
    GList *pList;
    const gchar *sText;

    /* Recuperation de la liste des elements que contient la GtkVBox */
    pList = gtk_container_get_children(GTK_CONTAINER((GtkWidget*)data));

    /* Le premier element est le GtkEntry */
    pTempEntry = GTK_WIDGET(pList->data);

    /* Passage a l element suivant : le GtkButton */
    pList = g_list_next(pList);

    /* Passage a l element suivant : le GtkLabel */
    pList = g_list_next(pList);

    /* Cet element est le GtkLabel */
    pTempLabel = GTK_WIDGET(pList->data);

    /* Recuperation du texte contenu dans le GtkEntry */
    sText = gtk_entry_get_text(GTK_ENTRY(pTempEntry));

    /* Modification du texte contenu dans le GtkLabel */
    gtk_label_set_text(GTK_LABEL(pTempLabel), sText);

    /* Liberation de la memoire utilisee par la liste */
    g_list_free(pList);
}

Résultat :

3. En savoir plus :

3.1 Signaux

activate
Prototype fonction callback : void user_function(GtkEntry *entry, gpointer user_data);
copy-clipboard
Prototype fonction callback : void user_function(GtkEntry *entry, gpointer user_data);
cut-clipboard
Prototype fonction callback : void user_function(GtkEntry *entry, gpointer user_data);
delete-from-cursor
Prototype fonction callback : void user_function(GtkEntry *entry, GtkDeleteType arg1, gint arg2, gpointer user_data);
insert-at-cursor
Prototype fonction callback : void user_function(GtkEntry *entry, gchar *arg1, gpointer user_data);
move-cursor
Prototype fonction callback : void user_function(GtkEntry *entry, GtkMovementStep arg1, gint arg2, gboolean arg3, gpointer user_data);
paste-clipboard
Prototype fonction callback : void user_function(GtkEntry *entry, gpointer user_data);
populate-popup
Prototype fonction callback : void user_function(GtkEntry *entry, GtkMenu *arg1, gpointer user_data);
toggle-overwrite
Prototype fonction callback : void user_function (GtkEntry *entry, gpointer user_data);

3.2 Fonction documentées

void gtk_entry_set_max_length (GtkEntry *entry, gint max);
Définit le nombre maximum de caractère que l'utilisateur peut saisir.
Entrée(s) :
entry : le GtkEntry.
max : le nombre de caractère.
Sortie : rien.
gint gtk_entry_get_max_length (GtkEntry *entry);
Récupère le nombre maximum de caractère que l'utilisateur peut saisir.
Entrée(s) :
entry : le GtkEntry.
Sortie : le nombre maximum de caractères.

3.3 Fonctions non documentées

gboolean gtk_entry_get_activates_default (GtkEntry *entry);
void gtk_entry_set_activates_default (GtkEntry *entry, gboolean setting);
gboolean gtk_entry_get_has_frame (GtkEntry *entry);
void gtk_entry_set_has_frame (GtkEntry *entry, gboolean setting);
gint gtk_entry_get_width_chars (GtkEntry *entry);
void gtk_entry_set_width_chars (GtkEntry *entry, gint n_chars);
PangoLayout* gtk_entry_get_layout (GtkEntry *entry);
void gtk_entry_get_layout_offsets (GtkEntry *entry, gint *x, gint *y);

Date de mise à jour : 10 janvier 2003.