Spin Buttons

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.

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);

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

// "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);

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.

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);

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: