Programmation GTK2 en Pascal/GtkToggleButton

Un livre de Wikilivres.
Programmation GTK2 en Pascal

Présentation[modifier | modifier le wikicode]

Le contrôle GtkToggleButton est un bouton poussoir qui ne peut prendre que deux états : enfoncé ou relâché.

Hiérarchie[modifier | modifier le wikicode]

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

Utilisation de base[modifier | modifier le wikicode]

Création[modifier | modifier le wikicode]

Comme d'habitude, il n'y a rien de bien compliqué vu que c'est toujours le même principe :

function gtk_toggle_button_new : PGtkWidget;
function gtk_toggle_button_new_with_label(_label : Pgchar) : PGtkWidget;
function gtk_toggle_button_new_with_mnemonic(_label : Pgchar) : PGtkWidget;

La première fonction crée un nouveau bouton vide, alors que la seconde ajoute du texte à l'intérieur et la troisième ajoute en plus un raccourci clavier.

État du bouton[modifier | modifier le wikicode]

Il peut être intéressant de connaître l'état du bouton pour agir en conséquence. Une fois encore, rien de plus simple on utilise la fonction :

function gtk_toggle_button_get_active(toggle_button : PGtkToggleButton) : gboolean;

Cette dernière nous renvoie TRUE si le bouton est enfoncé et FALSE sinon. Afin de pouvoir utiliser le paramètre toggle_button qui est le bouton dont on veut connaître l'état, il faut utiliser la fonction GTK_TOGGLE_BUTTON.

Pour modifier l'état du bouton, c'est aussi simple :

procedure gtk_toggle_button_set_active(toggle_button : PGtkToggleButton; is_active : gboolean);

Il suffit de mettre le paramètre is_active à TRUE si l'on veut enfoncer le bouton ou à FALSE pour le relâcher.

Apparence du bouton[modifier | modifier le wikicode]

Il existe cependant un troisième état qui n'est pas accessible en cliquant sur le bouton mais par une fonction spécifique. Ce troisième état, vous le connaissez sûrement. Le meilleur exemple est celui des éditeurs de texte : Vous avez une phrase dans laquelle il y a du texte normal et du texte en gras. Si vous sélectionnez le texte en gras, le bouton permettant justement de le mettre en gras s'enfonce (en général B). Par contre si vous sélectionnez le texte normal, ce même bouton repasse à son état relâché. Venons en au troisième état, qui apparaît lorsque vous sélectionnez la phrase entière. Le bouton ne change pas d'état mais seulement d'aspect, il donne l'impression d'être inactif.

Ce changement d'aspect doit se faire manuellement, et s'effectue avec cette fonction :

procedure gtk_toggle_button_set_inconsistent(toggle_button : PGtkToggleButton; setting : gboolean);

Il suffit de mettre le paramètre setting à TRUE pour donner au bouton l'aspect inactif.

Et pour connaître l'aspect du bouton, il y a tout naturellement la fonction :

function gtk_toggle_button_get_inconsistent(toggle_button : PGtkToggleButton) : gboolean;

Programme exemple[modifier | modifier le wikicode]

Nous allons construire une application contenant un GtkToggleButton qui changera d'état (bien sûr) lorsque nous cliquerons dessus, mais aussi lorsque nous cliquerons sur un deuxième bouton (le changement d'état entraînera la modification du label). De plus, il y aura un troisième bouton pour changer l'aspect du bouton (idem, on change aussi le label).

Voilà le fichier gtk021.pas :

program gtk021;

uses glib2, gtk2;

procedure OnBtnAEtatToggle(APWidget : PGtkwidget; AData : pgpointer); cdecl;
var
  Etat : GBoolean;
  Inconsistent : GBoolean;
  LabelBtn : PGChar;
  LabelEtat, LabelIncons : PGChar;
begin
  // Récuperation de l'état du bouton
  Etat := gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(APWidget));
  // Récuperation de l'aspect du bouton 
  Inconsistent := gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON(APWidget));

  // Construction du label du bouton 
  if Etat then
    LabelEtat := g_strdup('Enfoncé')
  else
    LabelEtat := g_strdup('Relâché');
  if Inconsistent then
    LabelIncons := g_strdup('Modifié')
  else
    LabelIncons := g_strdup('Normal');
  LabelBtn := g_strdup_printf('État : %s/Aspect : %s', [LabelEtat, LabelIncons]);

  // Modification du label du bouton 
  gtk_button_set_label(GTK_BUTTON(APWidget), LabelBtn);

  // Libération des chaînes
  g_free(LabelBtn);
  g_free(LabelEtat);
  g_free(LabelIncons);
end;

procedure OnBtnMajEtatClick(APWidget : PGtkwidget; AData : pgpointer); cdecl;
var
  Etat : GBoolean;
begin
  // Récuperation de l'état du bouton
  Etat := gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(AData));

  // Modification de l'état du bouton
  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(AData), Etat <> TRUE);
end;

procedure OnBtnMajAspectClick(APWidget : PGtkwidget; AData : pgpointer); cdecl;
var
  Inconsistent : GBoolean;
begin
  // Récuperation de l'aspect du bouton
  Inconsistent := gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON(AData));

  // Modification de l'aspect du bouton 
  gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(AData), Inconsistent <> TRUE);

  // On emet le signal « toggle » pour changer le texte du bouton 
  gtk_toggle_button_toggled(GTK_TOGGLE_BUTTON(AData));
end;

var
  pFenetre    : PGtkWidget;
  pVBox       : PGtkWidget;
  pBtnAEtat   : PGtkWidget;
  pBtnMajEtat : PGtkWidget;
  pBtnMajAspect : 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), 'Gtk021 : Bouton à état');
  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);

  // Création du bouton à état
  pBtnAEtat := gtk_toggle_button_new_with_label('État : Relâché/Aspect : Normal');
  gtk_box_pack_start(GTK_BOX(pVBox), pBtnAEtat, FALSE, FALSE, 5);
  g_signal_connect(pGTKOBJECT(pBtnAEtat), 'toggled', GTK_SIGNAL_FUNC(@OnBtnAEtatToggle), NULL);

  // Création du bouton de changement d'état
  pBtnMajEtat := gtk_button_new_with_label('Changer état');
  gtk_box_pack_start(GTK_BOX(pVBox), pBtnMajEtat, FALSE, FALSE, 5);
  g_signal_connect(pGTKOBJECT(pBtnMajEtat), 'clicked', GTK_SIGNAL_FUNC(@OnBtnMajEtatClick), pBtnAEtat);

  // Création du bouton de changement d'aspect
  pBtnMajAspect := gtk_button_new_with_label('Changer aspect');
  gtk_box_pack_start(GTK_BOX(pVBox), pBtnMajAspect, FALSE, FALSE, 5);
  g_signal_connect(pGTKOBJECT(pBtnMajAspect), 'clicked', GTK_SIGNAL_FUNC(@OnBtnMajAspectClick), pBtnAEtat);

  gtk_widget_show_all(pFenetre);
  gtk_main;
end.

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

Puis après avoir cliqué sur le bouton à état :

Puis après avoir cliqué sur le bouton de changement d'aspect :

Boutons : GtkButton ~ GtkToggleButton ~ GtkCheckButton ~ GtkRadioButton