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 :
value | valeur initiale de la boite d'incrément |
lower | limite basse de l'intervalle |
upper | limite haute de l'intervalle |
step_increment | pas de l'incrémentation/décrémentation lorsque on clique sur l'un des deux boutons avec le bouton 1 de la souris |
page_increment | pas de l'incrémentation/décrémentation lorsque on clique sur l'un des deux boutons avec le bouton 2 de la souris |
page_size | inutilisé |
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()