Page suivante Page précédente Table des matières

8. Widgets containers

8.1 Bloc-notes

Le widget bloc-notes est un ensemble de « pages » qui se chevauchent. Chaque page contient des informations différentes. Récemment, ce widget est devenu plus commun dans la programmation des interfaces graphiques et c'est un bon moyen de montrer des blocs d'information similaires qui justifient une séparation de leur affichage.

Le premier appel de fonction que l'on doit connaître est, vous l'aviez deviné, celui qui crée un widget bloc-notes.

GtkWidget* gtk_notebook_new (void);

Lorsque le bloc-notes a été créé, il y a 12 fonctions permettant de travailler sur les blocs-notes. Étudions-les séparément.

La première permet de positionner les indicateurs de pages. Ceux-ci (désignés par le mot « tab » (signet)), peuvent se trouver en haut, en bas, à gauche ou à droite des pages.

void gtk_notebook_set_tab_pos (GtkNotebook *notebook, GtkPositionType pos);

GtkPositionType peut prendre les valeurs suivantes qu'il n'est pas nécessaire d'expliquer :

GTK_POS_TOP est la valeur par défaut.

La fonction suivante permet d'ajouter des pages à un bloc-notes. Il y a trois façons d'ajouter des pages. Regardons les deux premières qui sont très semblables.

void gtk_notebook_append_page (GtkNotebook *notebook, GtkWidget *child, 
                               GtkWidget *tab_label);

void gtk_notebook_prepend_page (GtkNotebook *notebook, GtkWidget *child, 
                                GtkWidget *tab_label);

Ces fonctions ajoutent des pages au bloc-notes*notebook en les insérant à la fin (append) ou au début (prepend). *child est le widget qui est placé dans la page du bloc-notes, et *tab_label est le label de la page qui est ajoutée.

La troisième fonction ajoutant une page à un bloc-notes conserve toutes les propriétés des deux précédentes, mais elle nous permet en plus de spécifier la position où l'on désire insérer cette page.

void gtk_notebook_insert_page (GtkNotebook *notebook, GtkWidget *child, 
                               GtkWidget *tab_label, gint position);

Les paramètres sont les mêmes que _append_ et _prepend_ sauf qu'il y en a un de plus : position. Celui-ci sert à spécifier l'endroit où cette page sera insérée.

Maintenant que nous savons insérer une page, voyons comment en supprimer une.

void gtk_notebook_remove_page (GtkNotebook *notebook, gint page_num);

Cette fonction ôte la page spécifiée par page_num du widget *notebook.

Pour connaître la page courante d'un bloc-notes, on dispose de la fonction :

gint gtk_notebook_current_page (GtkNotebook *notebook);

Les deux fonctions suivantes permettent de passer à la page suivante ou précédente d'un bloc-notes. Il suffit de faire l'appel de la fonction adéquate avec le widget sur lequel on veut opérer. Remarque : lorsqu'on est sur la dernière page du bloc-notes et que l'on appelle gtk_notebook_next_page, on revient à la première page. De même, si l'on est sur la première page et que l'onappelle gtk_notebook_prev_page, on se retrouve sur sa dernière page.

void gtk_notebook_next_page (GtkNoteBook *notebook);
void gtk_notebook_prev_page (GtkNoteBook *notebook);

La fonction qui suit permet de choisir la page « active ». Si vous voulez ouvrir le bloc-notes à la page 5, par exemple, vous utiliserez cette fonction. Sans elle, le bloc-notes s'ouvre sur sa première page par défaut.

void gtk_notebook_set_page (GtkNotebook *notebook, gint page_num);

Les deux fonctions suivantes ajoutent ou ôtent les indicateurs de page et le contour du bloc-notes, respectivement.

void gtk_notebook_set_show_tabs (GtkNotebook *notebook, gint show_tabs);
void gtk_notebook_set_show_border (GtkNotebook *notebook, gint show_border);

show_tabs et show_border peuvent valoir TRUE ou FALSE (0 ou 1).

Voyons maintenant un exemple, il est tiré du code de testgtk.c de la distribution GTK et montre l'utilisation des 13 fonctions. Ce petit programme crée une fenêtre contenant un bloc-notes et six boutons. Le bloc-notes contient 11 pages, ajoutées par trois moyens différents : à la fin, au milieu et au début. Les boutons permettent de faire tourner les indicateurs de page, ajouter/ôter les indicateurs et le contour, ôter une page, passer à la page suivante et précédente, et sortir du programme.


#include <gtk/gtk.h>

/* Rotation des indicateurs de page  */

void rotate_book (GtkButton *button, GtkNotebook *notebook)
{
    gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
}

/* Ajout/Suppression des indicateurs de pages et des contours */

void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
{
    gint tval = FALSE;
    gint bval = FALSE;
    if (notebook->show_tabs == 0)
            tval = TRUE; 
    if (notebook->show_border == 0)
            bval = TRUE;
    
    gtk_notebook_set_show_tabs (notebook, tval);
    gtk_notebook_set_show_border (notebook, bval);
}

/* Suppression d'une page */

void remove_book (GtkButton *button, GtkNotebook *notebook)
{
    gint page;
    
    page = gtk_notebook_current_page(notebook);
    gtk_notebook_remove_page (notebook, page);

    /* Il faut rafraîchir  le widget --
     * ce qui force le widget à se redessiner. */

      gtk_widget_draw(GTK_WIDGET(notebook), NULL);
}

void delete (GtkWidget *widget, GdkEvent *event, gpointer *data)
{
    gtk_main_quit ();
}

int main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *table;
    GtkWidget *notebook;
    GtkWidget *frame;
    GtkWidget *label;
    GtkWidget *checkbutton;
    int i;
    char bufferf[32];
    char bufferl[32];
    
    gtk_init (&argc, &argv);
    
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    
    gtk_signal_connect (GTK_OBJECT (window), "delete_event",
                        GTK_SIGNAL_FUNC (delete), NULL);
    
    gtk_container_border_width (GTK_CONTAINER (window), 10);
    
    table = gtk_table_new(2,6,TRUE);
    gtk_container_add (GTK_CONTAINER (window), table);
    
    /* Création d'un bloc-notes, placement des indicateurs de page. */

    notebook = gtk_notebook_new ();
    gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
    gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
    gtk_widget_show(notebook);
    
    /* Ajoute un groupe de pages à la fin du bloc-notes. */

    for (i=0; i < 5; i++) {
        sprintf(bufferf, "Append Frame %d", i+1);
        sprintf(bufferl, "Page %d", i+1);
        
        frame = gtk_frame_new (bufferf);
        gtk_container_border_width (GTK_CONTAINER (frame), 10);
        gtk_widget_set_usize (frame, 100, 75);
        gtk_widget_show (frame);
        
        label = gtk_label_new (bufferf);
        gtk_container_add (GTK_CONTAINER (frame), label);
        gtk_widget_show (label);
        
        label = gtk_label_new (bufferl);
        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
    }
    
    
    /* Ajoute une page à un endroit précis. */

    checkbutton = gtk_check_button_new_with_label ("Cochez moi !");
    gtk_widget_set_usize(checkbutton, 100, 75);
    gtk_widget_show (checkbutton);
    
    label = gtk_label_new ("Emplacement de la nouvelle page");
    gtk_container_add (GTK_CONTAINER (checkbutton), label);
    gtk_widget_show (label);
    label = gtk_label_new ("Ajout de page");
    gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
    
    /* Ajout de pages au début du bloc-notes */

    for (i=0; i < 5; i++) {
        sprintf(bufferf, "Prepend Frame %d", i+1);
        sprintf(bufferl, "Page %d", i+1);
        
        frame = gtk_frame_new (bufferf);
        gtk_container_border_width (GTK_CONTAINER (frame), 10);
        gtk_widget_set_usize (frame, 100, 75);
        gtk_widget_show (frame);
        
        label = gtk_label_new (bufferf);
        gtk_container_add (GTK_CONTAINER (frame), label);
        gtk_widget_show (label);
        
        label = gtk_label_new (bufferl);
        gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
    }
    
    /* Configuration de la page de départ (page 4) */

    gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
    
    
    /* Création des boutons */

    button = gtk_button_new_with_label ("Fermer");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               GTK_SIGNAL_FUNC (delete), NULL);
    gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
    gtk_widget_show(button);
    
    button = gtk_button_new_with_label ("Page suivante");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               (GtkSignalFunc) gtk_notebook_next_page,
                               GTK_OBJECT (notebook));
    gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
    gtk_widget_show(button);
    
    button = gtk_button_new_with_label ("Page précédente");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               (GtkSignalFunc) gtk_notebook_prev_page,
                               GTK_OBJECT (notebook));
    gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
    gtk_widget_show(button);
    
    button = gtk_button_new_with_label ("Position des indicateurs");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
    gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
    gtk_widget_show(button);
    
    button = gtk_button_new_with_label ("Indicateurs/Contours oui/non");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               (GtkSignalFunc) tabsborder_book,
                               GTK_OBJECT (notebook));
    gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
    gtk_widget_show(button);
    
    button = gtk_button_new_with_label ("Oter page");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               (GtkSignalFunc) remove_book,
                               GTK_OBJECT(notebook));
    gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
    gtk_widget_show(button);
    
    gtk_widget_show(table);
    gtk_widget_show(window);
    
    gtk_main ();
    
    return 0;
}

En espérant que ceci vous aide à créer des blocs-notes pour vos applications GTK.

8.2 Fenêtres avec barres de défilement

Les fenêtres avec barres de défilement servent à créer des zones défilantes à l'intérieur d'une vraie fenêtre. On peut insérer n'importe quel widget dans ces fenêtres, ils seront accessibles quelle que soit leur taille en utilisant les barres de défilement.

La fonction suivante sert à créer une fenêtre avec barre de défilement :

GtkWidget* gtk_scrolled_window_new (GtkAdjustment *hadjustment,
                                    GtkAdjustment *vadjustment);

Le premier paramètre est l'ajustement horizontal, et le second l'ajustement vertical. Ils sont presque toujours positionnés à NULL.

void gtk_scrolled_window_set_policy      (GtkScrolledWindow *scrolled_window,
                                          GtkPolicyType      hscrollbar_policy,
                                          GtkPolicyType      vscrollbar_policy);

Cela permet de configurer le fonctionnement des barres de défilement. Le premier paramètre est la fenêtre à défilement que l'on veut modifier, le second configure le fonctionnement de la barre horizontale et le troisième celui de la barre verticale.

Ce fonctionnement peut être GTK_POLICY AUTOMATIC ou GTK_POLICY_ALWAYS. GTK_POLICY_AUTOMATIC décidera automatiquement de votre besoin en barres de défilement, alors que GTK_POLICY_ALWAYS mettra toujours celles-ci.

Voici un exemple simple qui place 100 boutons commutateurs dans une fenêtre à défilement. Je n'ai commenté que les parties qui sont nouvelles pour vous.

#include <gtk/gtk.h>

void destroy(GtkWidget *widget, gpointer *data)
{
    gtk_main_quit();
}

int main (int argc, char *argv[])
{
    static GtkWidget *window;
    GtkWidget *scrolled_window;
    GtkWidget *table;
    GtkWidget *button;
    char buffer[32];
    int i, j;
    
    gtk_init (&argc, &argv);
    
    /* Création d'une boîte de dialogue pour y placer la fenêtre à défilement.
     * Une boîte de dialogue est une fenêtre comme les autres sauf qu'elle contient
     * une vbox et un séparateur horizontal. Ce n'est qu'un raccourci pour créer des
     * zones de dialogue. */

    window = gtk_dialog_new ();
    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        (GtkSignalFunc) destroy, NULL);
    gtk_window_set_title (GTK_WINDOW (window), "dialog");
    gtk_container_border_width (GTK_CONTAINER (window), 0);
    
    /* Création d'une fenêtre à défilement. */

    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
    
    gtk_container_border_width (GTK_CONTAINER (scrolled_window), 10);
    
    /* La gestion des barres est soit GTK_POLICY AUTOMATIC, soit  GTK_POLICY_ALWAYS.
     * GTK_POLICY_AUTOMATIC décide automatiquement s'il faut ou non des barres,
     * GTK_POLICY_ALWAYS met toujours des barres
     * Le premier paramètre correspond à la barre horizontale,
     * le second à la barre verticale. */

    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
                                    GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);

    /* Création d'une boîte de dialogue */

    gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
                        TRUE, TRUE, 0);
    gtk_widget_show (scrolled_window);
    
    /* Création d'une table de 10x10 cases. */

    table = gtk_table_new (10, 10, FALSE);
    
    /* Configure l'espace des lignes et des colonnes de 10 pixels */

    gtk_table_set_row_spacings (GTK_TABLE (table), 10);
    gtk_table_set_col_spacings (GTK_TABLE (table), 10);
    
    /* Place la table fans la fenêtre à défilement */

    gtk_container_add (GTK_CONTAINER (scrolled_window), table);
    gtk_widget_show (table);
    
    /* Crée une grille de boutons commutateurs dans la table */

    for (i = 0; i < 10; i++)
            for (j = 0; j < 10; j++) {
                sprintf (buffer, "bouton (%d,%d)\n", i, j);
                button = gtk_toggle_button_new_with_label (buffer);
                gtk_table_attach_defaults (GTK_TABLE (table), button,
                                           i, i+1, j, j+1);
                gtk_widget_show (button);
            }
    
    /* Ajoute un bouton « Fermer » en bas de la boîte de dialogue */

    button = gtk_button_new_with_label ("Fermer");
    gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                               (GtkSignalFunc) gtk_widget_destroy,
                               GTK_OBJECT (window));
    
    /* On met ce bouton en « bouton par défaut ». */
    
    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
    
    /* Récupère le bouton par défaut. Le fait de presser la touche « Entrée »
     * activera le bouton. */

    gtk_widget_grab_default (button);
    gtk_widget_show (button);
    
    gtk_widget_show (window);
    
    gtk_main();
    
    return(0);
}

Essayez de changer la taille de la fenêtre et faites attention aux réactions des barres de défilement. On peut aussi utiliser la fonction gtk_widget_set_usize() pour configurer la taille par défaut de la fenêtre et des autres widgets.


Page suivante Page précédente Table des matières