9.10. Les boites
d'incrément
On utilise généralement les boites d'incrément (
gtk.SpinButton)
pour permettre à l'utilisateur de sélectionner une valeur numérique
dans un intervalle donné. Ce widget consiste en un champ de texte flanqué
de deux boutons fléchés haut et bas. En sélectionnant l'un ou l'autre
de ces boutons, on incrémente ou décrémente la valeur dans les limites
de l'intervalle. Le champ de texte peut également être édité
directement afin de saisir une valeur spécifique.
La valeur d'un gtk.SpinButton peut être affichée sous sa forme
entière ou décimale, et il est possible de définir son pas
d'incrémentation/décrémentation. On peut également décider
que plus l'on maintient enfoncé les boutons, plus cette
incrémentation/décrémentation s'accélère.
Les boites d'incrément utilisent des ajustements pour stocker les données
concernant l'intervalle de valeurs du gtk.SpinButton. Cela fait du
gtk.SpinButton un widget très puissant.
Pour bien montrer les informations stockées par l'ajustement, rappelons-nous sa fonction
de création :
ajustement = gtk.Adjustment(value=0, lower=0, upper=0, step_incr=0, page_incr=0, page_size=0)
La boite d'incrément utilise ces attributs de l'ajustement de la manière
suivante :
Un clic sur un des deux boutons avec le bouton 3 de la souris peut également
servir à aller directement à la valeur upper ou
lower. Voyons donc comment créer une boite à
incrément :
boite_increment = gtk.SpinButton(adjustment=None, climb_rate=0.0, digits=0)
L'argument climb_rate accepte une valeur comprise entre 0.0 et 1.0 et
indique le degré d'accélération de la boite d'incrément.
L'argument digits spécifie le nombre de décimales de la
valeur affichée.
On peut reconfigurer une boite à incrément après sa création
en appelant la méthode suivante :
boite_increment.configure(adjustment, climb_rate, digits)
L'argument boite_increment spécifie le gtk.SpinButton
à reconfigurer. Les autres arguments sont les mêmes que ceux décrits
plus haut.
L'ajustement (adjustment) peut être défini et
récupéré indépendamment à l'aide des deux méthodes
suivantes :
boite_increment.set_adjustment(adjustment)
ajustement = spin_button.get_adjustment()
On peut également modifier le nombre de décimales ainsi :
boite_increment.set_digits(digits)
La valeur affichée par une boite d'incrément peut être
changée avec cette méthode :
boite_increment.set_value(value)
La valeur courante d'une boite d'incrément peut être
récupérée sous sa forme décimale ou entière à
l'aide des deux méthodes suivantes :
valeur_dec = spin_button.get_value()
valeur_ent = spin_button.get_value_as_int()
Si l'on souhaite que la modification de la valeur soit effectuée par
rapport à la valeur courante, on peut utiliser la méthode suivante :
boite_increment.spin(direction, increment)
Le paramètre direction peut prendre l'une des valeurs
suivantes :
SPIN_STEP_FORWARD
SPIN_STEP_BACKWARD
SPIN_PAGE_FORWARD
SPIN_PAGE_BACKWARD
SPIN_HOME
SPIN_END
SPIN_USER_DEFINED
Cette méthode réunit plusieurs fonctionnalités que nous allons
tenter d'expliquer clairement. Un grand nombre de ces réglages utilise les valeurs
de l'ajustement
associé à la boite d'incrément.
SPIN_STEP_FORWARD (en avant d'un pas) et SPIN_STEP_BACKWARD (en arrière d'un pas)
modifient la valeur de la boite d'incrément en lui ajoutant/soustrayant celle
spécifiée par l'argument increment, ou, si ce dernier vaut 0,
celle du step_increment de l'ajustement.
SPIN_PAGE_FORWARD (en avant d'une page) et SPIN_PAGE_BACKWARD (en arrière d'une
page) modifient simplement la valeur de la boite d'incrément en lui
ajoutant/soustrayant celle de increment.
SPIN_HOME (début) fixe la valeur de la boite d'incrément à la borne
minimum de l'intervalle de l'
ajustement.
SPIN_END (fin) fixe la valeur de la boite d'incrément à la borne maximum de
l'intervalle de l'
ajustement.
SPIN_USER_DEFINED (défini par l'utilisateur) modifie simplement la valeur de la
boite d'incrément en lui ajoutant la valeur spécifiée.
Abandonnons à présent les méthodes de définition et
récupération des attributs d'intervalle, pour nous intéresser
à celles qui affectent l'apparence et le comportement du widget gtk.SpinButton
en lui-même.
La première de ces méthodes sert à faire en sorte que la boite de
texte du gtk.SpinButton ne puisse contenir que des valeurs numériques.
L'utilisateur ne pourra alors pas y saisir autre chose :
boite_increment.set_numeric(numeric)
Si numeric vaut TRUE (vrai), le champ de saisie n'acceptera que les
valeurs numériques. Si elles vaut FALSE (faux), aucune contrainte n'est
posée.
On peut indiquer si l'on veut que la boite d'incrément effectue une boucle
après avoir passé la valeur maximum de l'intervalle, et revienne donc à
la valeur minimum. On utilisera pour ce faire la méthode suivante :
boite_increment.set_wrap(wrap)
La boite d'incrément tournera en boucle si wrap vaut TRUE.
On peut faire en sorte que la boite d'incrément arrondisse la valeur au
step_increment le plus proche (le step_increment
est défini dans l'
ajustement utilisé par la boite d'incrément). On fera alors
appel à la méthode suivante, où snap_to_ticks
(s'accrocher aux marques) devra valoir TRUE :
boite_increment.set_snap_to_ticks(snap_to_ticks)
Le mode d'actualisation d'une boite d'incrément peut être modifié
avec la méthode suivante :
boite_increment.set_update_policy(policy)
Les valeurs possibles pour policy (mode) sont :
UPDATE_ALWAYS
UPDATE_IF_VALID
Ces modes d'actualisation affectent le comportement de la boite d'incrément
lorsqu'elle analyse le texte saisi et qu'elle synchronise sa valeur avec celles de
l'ajustement.
Avec UPDATE_IF_VALID (actualiser si valide), la valeur de la boite d'incrément
n'est modifiée que si le texte saisi est une valeur numérique comprise dans
l'intervalle de l'
ajustement. Dans le cas contraire, le champ de saisie reprend sa valeur
courante.
Avec UPDATE_ALWAYS (actualiser toujours), toute erreur sera ignorée lors de la
conversion du texte en valeur numérique.
Pour finir, on peut demander explicitement une actualisation de la boite
d'incrément :
boite_increment.update()
Le programme d'exemple
boitesincrement.py offre une démonstration d'utilisation des boites
d'incrément, incluant la modification de plusieurs caractéristiques.
La Figure 9.11 montre ce que l'on obtient en lançant
le programme :
Voici le code source de
boitesincrement.py :
1 #!/usr/bin/env python
2
3 # exemple boiteincrement.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8
9 class ExempleBoiteIncrement:
10 def modif_arrondi(self, widget, boiteincr):
11 boiteincr.set_snap_to_ticks(widget.get_active())
12
13 def modif_numerique(self, widget, boiteincr):
14 boiteincr.set_numeric(widget.get_active())
15
16 def modif_decimales(self, widget, boiteincr, boiteincr1):
17 boiteincr1.set_digits(boiteincr.get_value_as_int())
18
19 def recup_valeur(self, widget, donnees, boiteincr, boiteincr2, etiquette):
20 if donnees == 1:
21 tampon = "%d" % boiteincr.get_value_as_int()
22 else:
23 tampon = "%0.*f" % (boiteincr2.get_value_as_int(),
24 boiteincr.get_value())
25 etiquette.set_text(tampon)
26
27 def __init__(self):
28 fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
29 fenetre.connect("destroy", gtk.main_quit)
30 fenetre.set_title("Boites d'increment")
31
32 boite_v0 = gtk.VBox(False, 5)
33 boite_v0.set_border_width(10)
34 fenetre.add(boite_v0)
35
36 cadre = gtk.Frame("Sans acceleration")
37 boite_v0.pack_start(cadre, True, True, 0)
38
39 boite_v1 = gtk.VBox(False, 0)
40 boite_v1.set_border_width(5)
41 cadre.add(boite_v1)
42
43 # Boites d'increment pour le jour, le mois et l'annee
44 boite_h = gtk.HBox(False, 0)
45 boite_v1.pack_start(boite_h, True, True, 5)
46
47 boite_v2 = gtk.VBox(False, 0)
48 boite_h.pack_start(boite_v2, True, True, 5)
49
50 etiquette = gtk.Label("Jour :")
51 etiquette.set_alignment(0, 0.5)
52 boite_v2.pack_start(etiquette, False, True, 0)
53
54 ajustement = gtk.Adjustment(1.0, 1.0, 31.0, 1.0, 5.0, 0.0)
55 boiteincr = gtk.SpinButton(ajustement, 0, 0)
56 boiteincr.set_wrap(True)
57 boite_v2.pack_start(boiteincr, False, True, 0)
58
59 boite_v2 = gtk.VBox(False, 0)
60 boite_h.pack_start(boite_v2, True, True, 5)
61
62 etiquette = gtk.Label("Mois :")
63 etiquette.set_alignment(0, 0.5)
64 boite_v2.pack_start(etiquette, False, True, 0)
65
66 ajustement = gtk.Adjustment(1.0, 1.0, 12.0, 1.0, 5.0, 0.0)
67 boiteincr = gtk.SpinButton(ajustement, 0, 0)
68 boiteincr.set_wrap(True)
69 boite_v2.pack_start(boiteincr, False, True, 0)
70
71 boite_v2 = gtk.VBox(False, 0)
72 boite_h.pack_start(boite_v2, True, True, 5)
73
74 etiquette = gtk.Label("Annee :")
75 etiquette.set_alignment(0, 0.5)
76 boite_v2.pack_start(etiquette, False, True, 0)
77
78 ajustement = gtk.Adjustment(1998.0, 0.0, 2100.0, 1.0, 100.0, 0.0)
79 boiteincr = gtk.SpinButton(ajustement, 0, 0)
80 boiteincr.set_wrap(False)
81 boiteincr.set_size_request(55, -1)
82 boite_v2.pack_start(boiteincr, False, True, 0)
83
84 cadre = gtk.Frame("Avec acceleration")
85 boite_v0.pack_start(cadre, True, True, 0)
86
87 boite_v1 = gtk.VBox(False, 0)
88 boite_v1.set_border_width(5)
89 cadre.add(boite_v1)
90
91 boite_h = gtk.HBox(False, 0)
92 boite_v1.pack_start(boite_h, False, True, 5)
93
94 boite_v2 = gtk.VBox(False, 0)
95 boite_h.pack_start(boite_v2, True, True, 5)
96
97 etiquette = gtk.Label("Valeur :")
98 etiquette.set_alignment(0, 0.5)
99 boite_v2.pack_start(etiquette, False, True, 0)
100
101 ajustement = gtk.Adjustment(0.0, -10000.0, 10000.0, 0.5, 100.0, 0.0)
102 boiteincr1 = gtk.SpinButton(ajustement, 1.0, 2)
103 boiteincr1.set_wrap(True)
104 boiteincr1.set_size_request(100, -1)
105 boite_v2.pack_start(boiteincr1, False, True, 0)
106
107 boite_v2 = gtk.VBox(False, 0)
108 boite_h.pack_start(boite_v2, True, True, 5)
109
110 etiquette = gtk.Label("Decimales :")
111 etiquette.set_alignment(0, 0.5)
112 boite_v2.pack_start(etiquette, False, True, 0)
113
114 ajustement = gtk.Adjustment(2, 1, 5, 1, 1, 0)
115 boiteincr2 = gtk.SpinButton(ajustement, 0.0, 0)
116 boiteincr2.set_wrap(True)
117 ajustement.connect("value_changed", self.modif_decimales, boiteincr2, boiteincr1)
118 boite_v2.pack_start(boiteincr2, False, True, 0)
119
120 boite_h = gtk.HBox(False, 0)
121 boite_v1.pack_start(boite_h, False, True, 5)
122
123 bouton = gtk.CheckButton("Deplacement tous les 0,5")
124 bouton.connect("clicked", self.modif_arrondi, boiteincr1)
125 boite_v1.pack_start(bouton, True, True, 0)
126 bouton.set_active(True)
127
128 bouton = gtk.CheckButton("Saisie numerique seulement")
129 bouton.connect("clicked", self.modif_numerique, boiteincr1)
130 boite_v1.pack_start(bouton, True, True, 0)
131 bouton.set_active(True)
132
133 etiquette_valeur = gtk.Label("")
134
135 boite_h = gtk.HBox(False, 0)
136 boite_v1.pack_start(boite_h, False, True, 5)
137 bouton = gtk.Button("Valeur entiere")
138 bouton.connect("clicked", self.recup_valeur, 1, boiteincr1, boiteincr2,
139 etiquette_valeur)
140 boite_h.pack_start(bouton, True, True, 5)
141
142 bouton = gtk.Button("Valeur decimale")
143 bouton.connect("clicked", self.recup_valeur, 2, boiteincr1, boiteincr2,
144 etiquette_valeur)
145 boite_h.pack_start(bouton, True, True, 5)
146
147 boite_v1.pack_start(etiquette_valeur, True, True, 0)
148 etiquette_valeur.set_text("0")
149
150 boite_h = gtk.HBox(False, 0)
151 boite_v0.pack_start(boite_h, False, True, 0)
152
153 bouton = gtk.Button("Fermer")
154 bouton.connect("clicked", gtk.main_quit)
155 boite_h.pack_start(bouton, True, True, 5)
156 fenetre.show_all()
157
158 def main():
159 gtk.main()
160 return 0
161
162 if __name__ == "__main__":
163 ExempleBoiteIncrement()
164 main()