Les boutons (Partie 2)
1. Présentation
Nous allons étudier cette fois-ci trois nouveaux types de boutons qui dérivent du widget
GtkButton. L'étude de ces widgets sera rapide car ils ne comportent que très peu de fonctions.
1.1 Hiérarchie
GObject ->
GtkObject ->
GtkWidget ->
GtkContainer ->
GtkBin? ->
GtkButton ->
GtkToggleButton
GObject ->
GtkObject ->
GtkWidget ->
GtkContainer ->
GtkBin? ->
GtkButton ->
GtkToggleButton ->
GtkCheckButton
GObject ->
GtkObject ->
GtkWidget ->
GtkContainer ->
GtkBin? ->
GtkButton ->
GtkToggleButton ->
GtkCheckButton ->
GtkRadioButton
2. Le bouton poussoir
Le widget
GtkToggleButton est un bouton poussoir qui ne peut prendre que deux états : enfoncé ou relâché.
2.1 Création
Comme d'habitude, il n'y a rien de bien compliqué vu que c'est toujours le même principe :
toggle_button = gtk.ToggleButton?(label=None, use_underline=True)
Sans paramètre, vous obtenez un nouveau bouton vide, si vous donner un paramètre
label, vous ajoutez du texte à l'intérieur et si vous utilisez un texte avec un _, vous ajouter en plus un raccourci clavier.
2.2 Etat du bouton
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 :
actif = toggle_button.get_active()
Cette dernière nous renvoie True si le bouton est enfoncé et False sinon.
Pour modifier l'état du bouton, c'est aussi simple :
toggle_button.set_active(is_active)
Il suffit de mettre le paramètre
is_active à True si l'on veut enfoncer le bouton ou à False pour le relâcher.
2.3 Apparence du bouton
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 méthode :
toggle_button.set_inconsistent(setting)
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 :
etat = toggle_button.get_inconsistent()
2.4 Programme exemple
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).
# -*- Encoding: Latin-1 -*-
import gtk
def main():
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("GtkToggleButton")
window.set_default_size(320, 200)
vbox = gtk.VBox(True, 0)
window.add(vbox)
# Creation du label du bouton
label = u"Etat : Relâché - Aspect : Normal"
# Creation du bouton GtkToggleButton
toggle_btn = gtk.ToggleButton(label)
# Le label sLabel n'est plus utile
vbox.pack_start(toggle_btn, False, False, 0)
etat_btn = gtk.Button("CHANGER ETAT")
vbox.pack_start(etat_btn, False, False, 0)
aspect_btn = gtk.Button("CHANGER ASPECT")
vbox.pack_start(aspect_btn, False, False, 0)
window.show_all()
# Connexion des signaux
window.connect("destroy", gtk.main_quit, None)
toggle_btn.connect("toggled", OnToggle, None)
etat_btn.connect("clicked", OnEtatBtn, toggle_btn)
aspect_btn.connect("clicked", OnAspectBtn, toggle_btn)
gtk.main()
def OnEtatBtn(widget, toggle):
# Recuperation de l etat du bouton
etat = toggle.get_active()
# Modification de l etat du bouton
toggle.set_active(etat ^ True)
def OnAspectBtn(etat_btn, toggle):
# Recuperation de l aspect du bouton
inconsistent = toggle.get_inconsistent()
# Modification de l'aspect du bouton
toggle.set_inconsistent(inconsistent ^ True)
# On emet le signal "toggle" pour changer le texte du bouton
toggle.toggled()
def OnToggle(toggle, data):
# Recuperation de l etat du bouton
etat = toggle.get_active()
# Recuperation de l aspect du bouton
inconsistent = toggle.get_inconsistent()
# Construction du label du bouton
Etat = {True:u'Enfoncé', False:u'Relâché'}
Inconsistent = {True: u'Modifié', False: u'Normal'}
label = "Etat : %s - Aspect : %s" % (Etat[etat], Inconsistent[inconsistent])
# Modification du label du bouton
toggle.set_label(label)
3. Les cases à cocher
3.1 Création
Une fois encore, la syntaxe et l'utilisation des fonctions de création restent classiques :
widget = gtk.CheckButton?(label=None, use_underline=True)
Il n'existe pas d'autres fonctions pour ce widget, il faut donc utiliser les fonctions des widgets
GtkToggleButton et
GtkButton pour récupérer les propriétés du widget (état, aspect, label, ...).
3.2 Programme exemple
Nous n'allons pas ici créer de programme exemple pour ce widget car il suffit juste de remplacer gtk_toggle_button_new_with_label par gtk_check_button_new_with_label dans l'exemple précédent pour obtenir ceci :
Nous allons maintenant le widget
GtkRadioButton qui se différencie des autres boutons par la possibilité d'en grouper plusieurs. De ce fait, lorsque par exemple nous avons un groupe de trois boutons, il n'y en a qu'un seul qui pourra être actif. On pourrait très bien faire cela avec le widget
GtkCheckButton mais cela serait beaucoup plus long à programmer.
4.1 Création
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 :
widget = gtk.RadioButton?(group=None, label=None, use_underline=True)
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 None 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 :
liste = radio_button.get_group()
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 :
radio1 = gtk.RadioButton?(label="Radio 1")
Group = radio1.get_group()
radio2 = gtk.RadioButton?(Group, label="Radio 2")
Group = radio2.get_group()
radio3 = gtk.RadioButton?(Group, "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, on peut utiliser un widget
RadioButton? comme paramètre group.
Cette fois
group ne correspond pas à la liste mais à un des boutons du groupe. A 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.
4.2 Programme exemple
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.
# -*- Encoding: Latin-1 -*-
import gtk
def main():
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("GtkRadioButton")
window.set_default_size(320, 200)
vbox = gtk.VBox(True, 0)
window.add(vbox)
label = gtk.Label("Votre choix :")
vbox.pack_start(label, False, False, 0)
# Creation du premier bouton radio
radio1 = gtk.RadioButton(label="Pour")
vbox.pack_start(radio1, False, False, 0)
# Ajout du deuxieme
radio2 = gtk.RadioButton(radio1, "Contre")
vbox.pack_start(radio2, False, False, 0)
# Ajout du troisieme
radio3 = gtk.RadioButton(radio1, "Sans opinion")
vbox.pack_start(radio3, False, False, 0)
valider = gtk.Button(stock=gtk.STOCK_OK)
vbox.pack_start(valider, False, False, 0)
window.show_all()
# Connexion des signaux
window.connect("destroy", gtk.main_quit, None)
valider.connect("clicked", OnValider, radio1)
gtk.main()
def OnValider(btn, data):
# Recuperation de la liste des boutons
liste = data.get_group()
# Parcours de la liste
for bouton in liste:
# Le bouton est il selectionne
if bouton.get_active():
# OUI -> on copie le label du bouton
label = bouton.get_label()
# On sort de la boucle
break
# On recupere la fenetre principale
#
# A partir d'un widget, gtk_widget_get_toplevel
# remonte jusqu'a la fenetre mere qui nous est
# utile pour l'affichage de la boite de dialogue
window = bouton.get_toplevel()
info = gtk.MessageDialog(window,
gtk.DIALOG_MODAL,
gtk.MESSAGE_INFO,
gtk.BUTTONS_OK,
"Vous avez choisi : %s" % label)
info.run()
info.destroy()
if __name__ == '__main__':
main()Résultat :

