Spin Buttons ============ .. image:: ../../img/tutorials/component.png A spin button is a text field that accepts a range of values, with buttons that allow the value to be increased or decreased by a fixed amount. * `Interface guidelines `__ .. tabs:: .. code-tab:: c GtkAdjustment *spin_adjustment = gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 5.0, 0.0); GtkWidget *spin_button = gtk_spin_button_new (spin_adjustment, 1.0, 0); .. code-tab:: python spin_adjustment = Gtk.Adjustment(value=0, lower=0, upper=100, step_increment=1, page_increment=5, page_size=0) spin_button = Gtk.SpinButton(adjustment=spin_adjustment, climb_rate=1, digits=0) .. code-tab:: vala var spin_adjustment = new Gtk.Adjustment (0, 0, 100, 1, 5, 0); var spin_button = new Gtk.SpinButton (spin_adjustment, 1, 0); .. code-tab:: js const spin_adjustment = new Gtk.Adjustment({ value: 0, lower: 0, upper: 100, step_increment: 1, page_increment: 5, page_size: 0, }); const spin_button = new Gtk.SpinButton({ adjustment: spin_adjustment, climb_rate: 1, digits: 0, }); .. code-tab:: xml 0 0 100 1 5 0 Spin buttons use ``GtkAdjustment`` objects as `models `__ to determine the range of values they can display. The current value of the spin button will update the ``GtkAdjustment:value`` property, and vice versa. Changes in value ---------------- You can monitor changes in the spin button's value by using one of these signals: - ``GtkSpinButton::value-changed`` - ``GtkAdjustment::value-changed`` - ``GObject::notify`` on the ``GtkAdjustment:value`` property .. tabs:: .. code-tab:: c // "adj" is defined elsewhere GtkWidget *spin_button = gtk_spin_button_new (adj, 1.0, 0); // "on_value_changed" is defined elsewhere g_signal_connect (spin_button, "value-changed", G_CALLBACK (on_value_changed), NULL); .. code-tab:: python # "adj" is defined elsewhere spin_button = Gtk.SpinButton(adjustment=adj, climb_rate=1.0, digits=0) # "on_value_changed" is defined elsewhere spin_button.connect("value-changed", on_value_changed) .. code-tab:: vala // "adj" is defined elsewhere var spin_button = new Gtk.SpinButton (adj, 1, 0); // "on_value_changed" is defined elsewhere spin_button.value_changed.connect (on_value_changed); .. code-tab:: js // "adj" is defined elsewhere const spin_button = new Gtk.SpinButton(adj, 1, 0); // "on_value_changed" is defined elsewhere spin_button.connect("value_changed", on_value_changed); Non-numerical spin buttons -------------------------- Adjustments can only interpolate between numerical values, but spin buttons can show any type of alphanumerical value, as long as it can be mapped to the adjustment's range and current value. Spin buttons can use the ``GtkSpinButton::input`` signal to transform the current content of the spin button into a numerical value, and the ``GtkSpinButton::output`` signal to transform the numerical value of the adjustment into the data to be displayed. .. tabs:: .. code-tab:: c static const char *values[] = { "Live", "Laugh", "Love", }; static const guint n_values = G_N_ELEMENTS (values); static void transform_spin_input (GtkSpinButton *self, double *new_value, gpointer user_data G_GNUC_UNUSED) { const char *text = gtk_editable_get_text (GTK_EDITABLE (self)); // Search for the allowed values, and map them to their // numerical identifier for (guint i = 0; i < n_values; i++) { if (g_strcmp0 (text, values[i]) == 0) { gtk_widget_remove_css_class (GTK_WIDGET (self), "error"); *new_value = i; return; } } *new_value = 0; gtk_widget_add_css_class (GTK_WIDGET (self), "error"); } static void transform_spin_output (GtkSpinButton *self, gpointer user_data G_GNUC_UNUSED) { GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (self); int value = gtk_adjustment_get_value (adjustment); g_assert (value >= 0 && value < n_values); gtk_editable_set_text (GTK_EDITABLE (self), values[value]); } // ... GtkAdjustment *adj = gtk_adjustment_new (0, 0, 2, 1, 1, 0); GtkWidget *spin_button = gtk_spin_button_new (adj, 1.0, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin_button), FALSE); g_signal_connect (spin_button, "input", G_CALLBACK (transform_spin_input), NULL); g_signal_connect (spin_button, "output", G_CALLBACK (transform_spin_output), NULL); .. code-tab:: python def transform_spin_input(spin): text = spin.get_text() if text in ["Live", "Laugh", "Love"]: spin.remove_css_class("error") else: spin.add_css_class("error") if text == "Live": return 0 elif text == "Laugh": return 1 elif text == "Love": return 2 else: return 0 def transform_spin_output(spin): adj = spin.get_adjustment() value = adj.get_value() if value == 0: spin.set_text("Live") elif value == 1: spin.set_text("Laugh") else: spin.set_text("Love") adj = Gtk.Adjustment(value=0, lower=0, upper=2, step_increment=1, page_increment=1, page_size=0) spin_button = Gtk.SpinButton(adjustment=adj, climb_rate=1.0, digits=0, numeric=False) .. code-tab:: vala var adj = new Gtk.Adjustment (0, 0, 2, 1, 1, 0); var spin_button = new Gtk.SpinButton (adj, 1, 0); spin_button.numeric = false; spin_button.input.connect ((new_value) => { string text = spin_button.text; spin_button.remove_css_class ("error"); if (text == "Live") new_value = 0; else if (text == "Laugh") new_value = 1; else if (text == "Love") new_value = 2; else new_value = 0; spin_button.add_css_class ("error"); new_value = 0; }); spin_button.output.connect (() => { int value = adj.value; assert (value >= 0 && value <= 3); switch (value) { case 0: spin_button.text = "Live"; case 1: spin_button.text = "Laugh"; case 2: spin_button.text = "Love"; } }); Useful methods for the component -------------------------------- * The ``set_digits()`` method controls the precision of the value of a spin button; you can use the value of 0 if you only need integer values. API references -------------- In the examples we used the following classes: * `GtkSpinButton `__ * `GtkAdjustment `__