Previous Next Contents

6. The Button Widget

6.1 Normal Buttons

We've almost seen all there is to see of the button widget. It's pretty simple. There is however two ways to create a button. You can use the gtk_button_new_with_label() to create a button with a label, or use gtk_button_new() to create a blank button. It's then up to you to pack a label or pixmap into this new button. To do this, create a new box, and then pack your objects into this box using the usual gtk_box_pack_start, and then use gtk_container_add to pack the box into the button.

Here's an example of using gtk_button_new to create a button with a picture and a label in it. I've broken the code to create a box up from the rest so you can use it in your programs.

#include <gtk/gtk.h>


/* create a new hbox with an image and a label packed into it
 * and return the box.. */

GtkWidget *xpm_label_box (GtkWidget *parent, gchar *xpm_filename, gchar *label_text)
{
    GtkWidget *box1;
    GtkWidget *label;
    GtkWidget *pixmapwid;
    GdkPixmap *pixmap;
    GdkBitmap *mask;
    GtkStyle *style;

    /* create box for xpm and label */
    box1 = gtk_hbox_new (FALSE, 0);
    gtk_container_border_width (GTK_CONTAINER (box1), 2);

    /* get style of button.. I assume it's to get the background color.
     * if someone knows the real reason, please enlighten me. */
    style = gtk_widget_get_style(parent);

    /* now on to the xpm stuff.. load xpm */
    pixmap = gdk_pixmap_create_from_xpm (parent->window, &mask,
                                         &style->bg[GTK_STATE_NORMAL],
                                         xpm_filename);
    pixmapwid = gtk_pixmap_new (pixmap, mask);

    /* create label for button */
    label = gtk_label_new (label_text);

    /* pack the pixmap and label into the box */
    gtk_box_pack_start (GTK_BOX (box1),
                        pixmapwid, FALSE, FALSE, 3);

    gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);

    gtk_widget_show(pixmapwid);
    gtk_widget_show(label);

    return (box1);
}

/* our usual callback function */
void callback (GtkWidget *widget, gpointer *data)
{
    g_print ("Hello again - %s was pressed\n", (char *) data);
}


int main (int argc, char *argv[])
{
    /* GtkWidget is the storage type for widgets */
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *box1;

    gtk_init (&argc, &argv);

    /* create a new window */
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");

    /* It's a good idea to do this for all windows. */
    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (gtk_exit), NULL);


    /* sets the border width of the window. */
    gtk_container_border_width (GTK_CONTAINER (window), 10);

    /* create a new button */
    button = gtk_button_new ();

    /* You should be getting used to seeing most of these functions by now */
    gtk_signal_connect (GTK_OBJECT (button), "clicked",
                        GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");

    /* this calls our box creating function */
    box1 = xpm_label_box(window, "info.xpm", "cool button");

    /* pack and show all our widgets */
    gtk_widget_show(box1);

    gtk_container_add (GTK_CONTAINER (button), box1);

    gtk_widget_show(button);

    gtk_container_add (GTK_CONTAINER (window), button);

    gtk_widget_show (window);

    /* rest in gtk_main and wait for the fun to begin! */
    gtk_main ();

    return 0;
}

The xpm_label_box function could be used to pack xpm's and labels into any widget that can be a container.

6.2 Toggle Buttons

Toggle buttons are very similar to normal buttons, except they will always be in one of two states, alternated by a click. They may be depressed, and when you click again, they will pop back up. Click again, and they will pop back down.

Toggle buttons are the basis for check buttons and radio buttons, as such, many of the calls used for toggle buttons are inherited by radio and check buttons. I will point these out when we come to them.

Creating a new toggle button:

GtkWidget* gtk_toggle_button_new (void);

GtkWidget* gtk_toggle_button_new_with_label (gchar *label);

As you can imagine, these work identically to the normal button widget calls. The first creates a blank toggle button, and the second, a button with a label widget already packed into it.

To retrieve the state of the toggle widget, including radio and check buttons, we use a macro as shown in our example below. This tests the state of the toggle in a callback. The signal of interest emitted to us by toggle buttons (the toggle button, check button, and radio button widgets), is the "toggled" signal. To check the state of these buttons, set up a signal handler to catch the toggled signal, and use the macro to determine it's state. The callback will look something like:

void toggle_button_callback (GtkWidget *widget, gpointer   data)
{
    if (GTK_TOGGLE_BUTTON (widget)->active) 
    {
        /* If control reaches here, the toggle button is depressed. */
    }
}

The above is in need of testing.. It's just a guess..

void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
                                  gint state);

The above call can be used to set the state of the toggle button, and it's children the radio and check buttons. Passing in your created button as the first argument, and a TRUE or FALSE for the second state argument to specify whether it should be up (released) or down (depressed). Default is up, or FALSE.

void       gtk_toggle_button_toggled        (GtkToggleButton *toggle_button);

This simply toggles the button, and emits the "toggled" signal.

6.3 Check Buttons

Check buttons inherent many properties and functions from the the toggle buttons above, but look a little different. Rather than being buttons with text inside them, they are small squares with the text to the right of them. These are often seen for toggling options on and off in applications.

The two creation functions are the same as for the normal button.

GtkWidget* gtk_check_button_new (void);

GtkWidget* gtk_check_button_new_with_label (gchar *label);

The new_with_label function creates a check button with a label beside it.

Checking the state of the check button is identical to that of the toggle button.

6.4 Radio Buttons

Radio buttons are similar to check buttons except they are grouped so that only one may be selected/depressed at a time. This is good for places in your application where you need to select from a short list of options.

Creating a new radio button is done with one of these calls:

GtkWidget* gtk_radio_button_new (GSList *group);

GtkWidget* gtk_radio_button_new_with_label (GSList *group,
                                            gchar *label);

You'll notice the extra argument to these calls. They require a group to perform they're duty properly. The first call should pass NULL as the first argument. You then create a group using:

GSList* gtk_radio_button_group (GtkRadioButton *radio_button);

You then pass this group as the first argument to each subsequent call to gtk_radio_button_new or new_with_label. It is also a good idea to explicitly set which button should be the default depressed button with:

void gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
                                  gint state);

This is described in the section on toggle buttons, and works in exactly the same way.

[Insert an example here of how to use these guys cause I think it could do a lot of good at this point.]


Previous Next Contents