Programmation GTK2 en Pascal

Présentation modifier

Le contrôle GtkRadioButton, appelé bouton radio est également un bouton poussoir qui fait partie d'un groupe de boutons radio dans lequel un seul peut-être enfoncé. Dès qu'on enfonce un des boutons du groupe, celui qui était enfoncé redevient normal. Comme sur un poste de radio quand on choisit, grandes ondes, petites ondes ou modulation de fréquence, le nom vient de là.

Hiérarchie modifier

Hiérarchie
GObject
  └─GtkObject
      └─GtkWidget
          └─GtkContainer
              └─GtkBin
                  └─GtkButton
                      └─GtkToggleButton
                          └─GtkCheckButton
                              └─GtkRadioButton

Utilisation de base modifier

Création modifier

Afin de grouper les boutons radio, Gtk+ utilise les listes simplement chaînées de GLib. Pour créer le premier bouton radio du groupe, il faut obligatoirement passer par une de ces fonctions :

function gtk_radio_button_new(group : PGSList) : PGtkWidget;
function gtk_radio_button_new_with_label(group : PGSList; _label : Pgchar) : PGtkWidget;
function gtk_radio_button_new_with_mnemonic(group : PGSList; _label : Pgchar) : PGtkWidget;

Au moment de la création, le bouton radio est automatiquement ajouté à la liste group. Cependant, ce paramètre n'est pas obligatoire. Nous pouvons très bien mettre NULL comme valeur et cela marchera de la même manière, sauf que nous n'aurons pas de pointeur sur la liste. La valeur de retour de cette fonction sera aussi copiée dans la variable data de la liste chaînée.

Ensuite pour rajouter les autres boutons au groupe, il y a plusieurs possibilités. La première est d'utiliser une des trois fonctions précédentes mais ce n'est pas tout, car autant pour le premier bouton du groupe, il n'est pas nécessaire d'avoir une liste, autant pour les autres boutons cela devient obligatoire. Pour cela, Gtk+ nous fournit une fonction qui permet d'obtenir la liste dans laquelle les boutons du groupe sont ajoutés :

function gtk_radio_button_get_group(radio_button : PGtkRadioButton) : PGSList;

Avec cette fonction, nous pouvons donc connaître la liste à laquelle appartient le bouton radio_button, ce qui va nous permettre d'ajouter de nouveau bouton au groupe. Mais là où cela se complique, c'est qu'il faut récupérer la liste avant chaque ajout de bouton avec le dernier bouton ajouté comme paramètre. Voici ce que cela donnerai pour un groupe de trois boutons :

pRadio1 := gtk_radio_button_new_with_label(NULL, 'Radio 1');
pGroup := gtk_radio_button_get_group(GTK_RADIO_BUTTON(pRadio1));
pRadio2 := gtk_radio_button_new_with_label(pGroup, 'Radio 2');
pGroup := gtk_radio_button_get_group(GTK_RADIO_BUTTON(pRadio2));
pRadio3 := gtk_radio_button_new_with_label(pGroup, 'Radio 3');

Ce système peut donc s'avérer lourd lors de la création du groupe, surtout s'il contient un grand nombre de boutons. Heureusement, les concepteurs de Gtk+ ont pensé à nous simplifier la vie en ajoutant ces trois fonctions :

function gtk_radio_button_new_from_widget(group : PGtkRadioButton) : PGtkWidget;
function gtk_radio_button_new_with_label_from_widget(group : PGtkRadioButton; _label : Pgchar) : PGtkWidget;
function gtk_radio_button_new_with_mnemonic_from_widget(group : PGtkRadioButton; _label : Pgchar) : PGtkWidget;

Cette fois group ne correspond pas à la liste mais à un des boutons du groupe. À chaque appel d'une de ces fonctions Gtk+ va s'occuper de récupérer correctement la liste à laquelle appartient le bouton group et ajouter le nouveau bouton. Cela aura pour conséquence, dans le cas d'un groupe de trois boutons, de réduire le nombre de lignes de code de 5 à 3 (et oui, une ligne de code c'est une ligne de code).

Nous savons maintenant tout ce qu'il faut pour créer un groupe de GtkRadioButton.

Programme exemple modifier

Le programme exemple se présente sous la forme d'un mini sondage à trois choix :

  • Pour ;
  • Contre ;
  • Sans opinion.

La possibilité de choisir parmi une de ces valeurs est rendue possible par l'utilisation des GtkRadioButton. Un autre bouton (tout ce qu'il y a de plus normal) permet de valider le choix fait par l'utilisateur ainsi que d'afficher le résultat dans une boîte de dialogue.

Voilà le fichier gtk023.pas :

program gtk023;

uses glib2, gtk2;

procedure OnBtn(APWidget : PGtkwidget; AData : pgpointer); cdecl;
var
  pListe : PGSList;
  LabelBtnRad : PGChar;
  pFenetre : PGtkWidget;
  pInfo    : PGtkWidget;
begin
  // Récuperation de la liste des boutons 
  pListe := gtk_radio_button_get_group(GTK_RADIO_BUTTON(AData));

  // Parcours de la liste 
  while pListe <> NULL do begin
    // Le bouton est-il sélectionné
    if gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pListe^.data)) then begin
      // OUI -> on copie le label du bouton 
      LabelBtnRad := gtk_button_get_label(GTK_BUTTON(pListe^.data));
      // On met la liste a NULL pour sortir de la boucle
      pListe := NULL;
    end
    else begin
      // NON -> on passe au bouton suivant */
      pListe := g_slist_next(pListe);
    end;
  end;

  // On récupère la fenêtre principale
  //
  // À partir d'un contrôle, gtk_widget_get_toplevel
  // remonte jusqu'à la fenêtre mère qui nous est
  // utile pour l'affichage de la boîte de dialogue

  pFenetre := gtk_widget_get_toplevel(GTK_WIDGET(AData));

  pInfo := gtk_message_dialog_new(GTK_WINDOW(pFenetre),
    GTK_DIALOG_MODAL,
    GTK_MESSAGE_INFO,
    GTK_BUTTONS_OK,
    'Vous avez choisi : %s', [LabelBtnRad]);

  gtk_dialog_run(GTK_DIALOG(pInfo));
  gtk_widget_destroy(pInfo);
  g_free(LabelBtnRad);
end;

var
  pFenetre     : PGtkWidget;
  pVBox        : PGtkWidget;
  pLabel       : PGtkWidget;
  pRadio1      : PGtkWidget;
  pRadio2      : PGtkWidget;
  pRadio3      : PGtkWidget;
  pBtnValider  : PGtkWidget;
begin
  gtk_init(@argc, @argv);
  pFenetre := gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_position(GTK_WINDOW(pFenetre), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(pFenetre), 320, 200);
  gtk_container_set_border_width(GTK_CONTAINER(pFenetre), 4);
  gtk_window_set_title(GTK_WINDOW(pFenetre), 'Gtk023 : Boutons radio');
  gtk_signal_connect(pGTKOBJECT(pFenetre), 'destroy', GTK_SIGNAL_FUNC(@gtk_main_quit), NULL);

  pVBox := gtk_vbox_new(TRUE, 0);
  gtk_container_add(GTK_CONTAINER(pFenetre), pVBox);

  pLabel := gtk_label_new('Votre choix :');
  gtk_box_pack_start(GTK_BOX(pVBox), pLabel, FALSE, FALSE, 0);

  // Création du premier bouton radio 
  pRadio1 := gtk_radio_button_new_with_label(NULL, 'Pour');
  gtk_box_pack_start(GTK_BOX(pVBox), pRadio1, FALSE, FALSE, 0);
  // Ajout du deuxième 
  pRadio2 := gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(pRadio1), 'Contre');
  gtk_box_pack_start(GTK_BOX(pVBox), pRadio2, FALSE, FALSE, 0);
  // Ajout du troisième
  pRadio3 := gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(pRadio1), 'Sans opinion');
  gtk_box_pack_start(GTK_BOX(pVBox), pRadio3, FALSE, FALSE, 0);

  pBtnValider := gtk_button_new_from_stock(GTK_STOCK_OK);
  gtk_box_pack_start(GTK_BOX(pVBox), pBtnValider, FALSE, FALSE, 0);
  g_signal_connect(pGTKOBJECT(pBtnValider), 'clicked', GTK_SIGNAL_FUNC(@OnBtn), pRadio1);

  gtk_widget_show_all(pFenetre);
  gtk_main;
end.

Voilà ce que donne l'exécution du programme gtk023 :

 

Boutons : GtkButton ~ GtkToggleButton ~ GtkCheckButton ~ GtkRadioButton