El control SpinButton (Botón Aumentar/
Disminuir) se usa generalmente para permitir al usuario seleccionar un valor
dentro de un rango de valores numéricos. Consiste en una caja de entrada de
texto con botones de flecha arriba y abajo a un lado. Seleccionando uno de los
botones causa que el valor aumente o disminuya en el rango de valores posibles.
La caja de entrada también puede editarse directamente para introducir un valor
específico.
El SpinButton permite que el valor tenga
cero o más cifras decimales y puede incrementarse/decrementarse en pasos
configurables. La acción de mantener pulsado uno de los botones opcionalmente
provoca una aceleración en el cambio del valor correspondiente al tiempo que
se mantenga presionado.
El SpinButton usa un objeto
Adjustment (Ajuste) para
almacenar la información del rango de valores que el botón aumentar/disminuir
puede tomar. Esto le hace un control muy útil.
Recordemos que un control Adjustment (Ajuste) se
crea con la siguiente función, que muestra la información que almacena:
adjustment = gtk.Adjustment(value=0,lower=0,upper=0,step_incr=0,page_incr=0,page_size=0)
Estos atributos de un Adjustment (Ajuste) se
usan en el SpinButton de la siguiente manera:
value | valor inicial para el Botón Aumentar/Disminuir |
lower | el valor más bajo del rango |
upper | el valor más alto del rango |
step_increment | valor que se incrementa/decrementa cuando se pulsa el del ratón en un botón |
page_increment | valor que se incrementa/decrementa cuando se pulsa el del ratón en un botón |
page_size | no se usa |
Adicionalmente, el botón del ratón
se puede usar para saltar directamente
a los valores upper (superior) y lower
(inferior) cuando se usa para seleccionar uno de los botones. Veamos como crear
un SpinButton (Botón Aumentar/Disminuir):
spin_button = gtk.SpinButton(adjustment=None,climb_rate=0.0,digits=0)
El argumento climb_rate (razón de escalada)
puede tomar un valor entre 0.0 y 1.0 e indica la cantidad de aceleración que
el SpinButton tiene. El argumento
digits especifica el número de cifras decimales que se
mostrarán.
Un SpinButton se puede reconfigurar después
de su creación usando el siguiente método:
spin_button.configure(adjustment,climb_rate,digits)
La variable spin_button especifica
el botón aumentar/disminuir que se va a reconfigurar. Los otros argumentos son
los mismos que antes.
El adjustment (ajuste) se puede fijar y recupar
independientemente usando los siguientes dos métodos:
spin_button.set_adjustment(adjustment)
adjustment = spin_button.get_adjustment()
El número de cifras decimales también se puede cambiar usando:
spin_button.set_digits(digits)
El valor que un SpinButton está mostrando
actualmente se puede cambiar usando el siguiente método:
spin_button.set_value(value)
El valor actual de un SpinButton se puede
recuperar como un valor real o como un valor entero usando los siguientes
métodos:
float_value = spin_button.get_value() int_value = spin_button.get_value_as_int()
Si quieres alterar el valor de un SpinButton
relativo a su valor actual, entonces usa el siguiente
método:
spin_button.spin(direction,increment)
El parámetro direction (dirección) puede tomar
uno de los siguientes valores:
SPIN_STEP_FORWARD # paso hacia adelante SPIN_STEP_BACKWARD # paso hacia atrás SPIN_PAGE_FORWARD # página hacia adelante SPIN_PAGE_BACKWARD # página hacia atrás SPIN_HOME # inicio SPIN_END # fin SPIN_USER_DEFINED # definido por el usuario
Este método comprime bastante funcionalidad, que explicaremos
ahora. Muchos de estos parámetros usan valores del objeto Adjustment (Ajuste) que
está asociado con un SpinButton
(Botón Aumentar/Disminuir).
SPIN_STEP_FORWARD (paso adelante) y
SPIN_STEP_BACKWARD (paso atrás)
cambian el valor del SpinButton con una cantidad
especificada por el increment (incremento), a menos que
increment (incremento) sea igual a 0, en cuyo caso el valor
se modifica con el step_increment (incremento de paso) del
Adjustment.
SPIN_PAGE_FORWARD (página adelante) y
SPIN_PAGE_BACKWARD (página
atrás) simplemente alteran el valor del SpinButton por
increment (incremento).
SPIN_HOME (inicio) pone el valor del
SpinButton a la parte de abajo del rango del
Adjustment .
SPIN_END (fin) fija el valor del
SpinButton a la parte de arriba del rango del Adjustment .
SPIN_USER_DEFINED (definido por el usuario) simplemente
modifica el valor del SpinButton con la cantidad especificada.
Ahora nos alejamos de los métodos para fijar y recuperar los
atributos del rango de un SpinButton, y nos centramos
en los métodos que modifican la apariencia y comportamiento del propio control
SpinButton.
El primero de estos métodos se usa para limitar la caja de texto del
SpinButton para que solo contenga un valor numérico.
Esto evita que el usuario escriba cualquier otra cosa que no sea un valor
numérico dentro de la caja de texto de un SpinButton:
spin_button.set_numeric(numeric)
El argumento numeric es TRUE para
limitar la caja de texto a valores numéricos o FALSE para quitar esta
limitación.
Puedes fijar si quieres que el valor del
SpinButton se quede en los valores inferior y superior
del rango con el siguiente método:
spin_button.set_wrap(wrap)
El SpinButton limitará los valores dentro
del rango si wrap es TRUE.
Puedes hacer que el SpinButton redondee el
valor al step_increment (incremento) más cercano, lo cual
se fija dentro del objeto Adjustment usado en el
SpinButton. Esto se consigue con el siguiente método
cuando el argumento snap_to_ticks es TRUE
:
spin_button.set_snap_to_ticks(snap_to_ticks)
La política de actualización de un
SpinButton se cambia con el siguiente método:
spin_button.set_update_policy(policy)
Los valores posibles de esta política son:
UPDATE_ALWAYS # actualizar siempre UPDATE_IF_VALID # actualizar si es válido
Estas políticas afectan el comportamiento de un
SpinButton cuando analiza el texto insertado y
sincroniza su valor con los valores del Adjustment.
En el caso de UPDATE_IF_VALID (actualizar si es válido) el valor
del SpinButton sólo cambia si el texto es un valor
numérico que está dentro del rango especificado por el Adjustment. En cualquier
otro caso el texto se resetea al valor actual.
En el caso de UPDATE_ALWAYS (actualizar siempre) se ignoran
los errores de conversión al pasar el texto a un valor numérico.
Finalmente, se puede solicitar una actualización del
SpinButton :
spin_button.update()
El programa de ejemplo spinbutton.py muestra el uso de botones de aumentar/disminuir incluyendo el uso de varias características. La figura Figura 9.11, “Ejemplo de Botón Aumentar/Disminuir” muestra el resultado de ejecutar el programa de ejemplo:
El código fuente spinbutton.py es:
1 #!/usr/bin/env python
2
3 # ejemplo spinbutton.py
4
5 import pygtk
6 pygtk.require('2.0')
7 import gtk
8
9 class SpinButtonExample:
10 def toggle_snap(self, widget, spin):
11 spin.set_snap_to_ticks(widget.get_active())
12
13 def toggle_numeric(self, widget, spin):
14 spin.set_numeric(widget.get_active())
15
16 def change_digits(self, widget, spin, spin1):
17 spin1.set_digits(spin.get_value_as_int())
18
19 def get_value(self, widget, data, spin, spin2, label):
20 if data == 1:
21 buf = "%d" % spin.get_value_as_int()
22 else:
23 buf = "%0.*f" % (spin2.get_value_as_int(),
24 spin.get_value())
25 label.set_text(buf)
26
27 def __init__(self):
28 window = gtk.Window(gtk.WINDOW_TOPLEVEL)
29 window.connect("destroy", lambda w: gtk.main_quit())
30 window.set_title("Spin Button")
31
32 main_vbox = gtk.VBox(gtk.FALSE, 5)
33 main_vbox.set_border_width(10)
34 window.add(main_vbox)
35
36 frame = gtk.Frame("Not accelerated")
37 main_vbox.pack_start(frame, gtk.TRUE, gtk.TRUE, 0)
38
39 vbox = gtk.VBox(gtk.FALSE, 0)
40 vbox.set_border_width(5)
41 frame.add(vbox)
42
43 # Botones de aumentar/disminuir día, mes y año
44 hbox = gtk.HBox(gtk.FALSE, 0)
45 vbox.pack_start(hbox, gtk.TRUE, gtk.TRUE, 5)
46
47 vbox2 = gtk.VBox(gtk.FALSE, 0)
48 hbox.pack_start(vbox2, gtk.TRUE, gtk.TRUE, 5)
49
50 label = gtk.Label("Day :")
51 label.set_alignment(0, 0.5)
52 vbox2.pack_start(label, gtk.FALSE, gtk.TRUE, 0)
53
54 adj = gtk.Adjustment(1.0, 1.0, 31.0, 1.0, 5.0, 0.0)
55 spinner = gtk.SpinButton(adj, 0, 0)
56 spinner.set_wrap(gtk.TRUE)
57 vbox2.pack_start(spinner, gtk.FALSE, gtk.TRUE, 0)
58
59 vbox2 = gtk.VBox(gtk.FALSE, 0)
60 hbox.pack_start(vbox2, gtk.TRUE, gtk.TRUE, 5)
61
62 label = gtk.Label("Month :")
63 label.set_alignment(0, 0.5)
64 vbox2.pack_start(label, gtk.FALSE, gtk.TRUE, 0)
65
66 adj = gtk.Adjustment(1.0, 1.0, 12.0, 1.0, 5.0, 0.0)
67 spinner = gtk.SpinButton(adj, 0, 0)
68 spinner.set_wrap(gtk.TRUE)
69 vbox2.pack_start(spinner, gtk.FALSE, gtk.TRUE, 0)
70
71 vbox2 = gtk.VBox(gtk.FALSE, 0)
72 hbox.pack_start(vbox2, gtk.TRUE, gtk.TRUE, 5)
73
74 label = gtk.Label("Year :")
75 label.set_alignment(0, 0.5)
76 vbox2.pack_start(label, gtk.FALSE, gtk.TRUE, 0)
77
78 adj = gtk.Adjustment(1998.0, 0.0, 2100.0, 1.0, 100.0, 0.0)
79 spinner = gtk.SpinButton(adj, 0, 0)
80 spinner.set_wrap(gtk.FALSE)
81 spinner.set_size_request(55, -1)
82 vbox2.pack_start(spinner, gtk.FALSE, gtk.TRUE, 0)
83
84 frame = gtk.Frame("Accelerated")
85 main_vbox.pack_start(frame, gtk.TRUE, gtk.TRUE, 0)
86
87 vbox = gtk.VBox(gtk.FALSE, 0)
88 vbox.set_border_width(5)
89 frame.add(vbox)
90
91 hbox = gtk.HBox(gtk.FALSE, 0)
92 vbox.pack_start(hbox, gtk.FALSE, gtk.TRUE, 5)
93
94 vbox2 = gtk.VBox(gtk.FALSE, 0)
95 hbox.pack_start(vbox2, gtk.TRUE, gtk.TRUE, 5)
96
97 label = gtk.Label("Value :")
98 label.set_alignment(0, 0.5)
99 vbox2.pack_start(label, gtk.FALSE, gtk.TRUE, 0)
100
101 adj = gtk.Adjustment(0.0, -10000.0, 10000.0, 0.5, 100.0, 0.0)
102 spinner1 = gtk.SpinButton(adj, 1.0, 2)
103 spinner1.set_wrap(gtk.TRUE)
104 spinner1.set_size_request(100, -1)
105 vbox2.pack_start(spinner1, gtk.FALSE, gtk.TRUE, 0)
106
107 vbox2 = gtk.VBox(gtk.FALSE, 0)
108 hbox.pack_start(vbox2, gtk.TRUE, gtk.TRUE, 5)
109
110 label = gtk.Label("Digits :")
111 label.set_alignment(0, 0.5)
112 vbox2.pack_start(label, gtk.FALSE, gtk.TRUE, 0)
113
114 adj = gtk.Adjustment(2, 1, 5, 1, 1, 0)
115 spinner2 = gtk.SpinButton(adj, 0.0, 0)
116 spinner2.set_wrap(gtk.TRUE)
117 adj.connect("value_changed", self.change_digits, spinner2, spinner1)
118 vbox2.pack_start(spinner2, gtk.FALSE, gtk.TRUE, 0)
119
120 hbox = gtk.HBox(gtk.FALSE, 0)
121 vbox.pack_start(hbox, gtk.FALSE, gtk.TRUE, 5)
122
123 button = gtk.CheckButton("Snap to 0.5-ticks")
124 button.connect("clicked", self.toggle_snap, spinner1)
125 vbox.pack_start(button, gtk.TRUE, gtk.TRUE, 0)
126 button.set_active(gtk.TRUE)
127
128 button = gtk.CheckButton("Numeric only input mode")
129 button.connect("clicked", self.toggle_numeric, spinner1)
130 vbox.pack_start(button, gtk.TRUE, gtk.TRUE, 0)
131 button.set_active(gtk.TRUE)
132
133 val_label = gtk.Label("")
134
135 hbox = gtk.HBox(gtk.FALSE, 0)
136 vbox.pack_start(hbox, gtk.FALSE, gtk.TRUE, 5)
137 button = gtk.Button("Value as Int")
138 button.connect("clicked", self.get_value, 1, spinner1, spinner2,
139 val_label)
140 hbox.pack_start(button, gtk.TRUE, gtk.TRUE, 5)
141
142 button = gtk.Button("Value as Float")
143 button.connect("clicked", self.get_value, 2, spinner1, spinner2,
144 val_label)
145 hbox.pack_start(button, gtk.TRUE, gtk.TRUE, 5)
146
147 vbox.pack_start(val_label, gtk.TRUE, gtk.TRUE, 0)
148 val_label.set_text("0")
149
150 hbox = gtk.HBox(gtk.FALSE, 0)
151 main_vbox.pack_start(hbox, gtk.FALSE, gtk.TRUE, 0)
152
153 button = gtk.Button("Close")
154 button.connect("clicked", lambda w: gtk.main_quit())
155 hbox.pack_start(button, gtk.TRUE, gtk.TRUE, 5)
156 window.show_all()
157
158 def main():
159 gtk.main()
160 return 0
161
162 if __name__ == "__main__":
163 SpinButtonExample()
164 main()