3.5 Button Widgets


3.5 Button Widgets

Buttons are among the most elementary user -operated widgets. There are three basic types of buttons :

  • GtkButton ( GTK_TYPE_BUTTON ): A simple button; when you click the button, GTK+ emits a signal. The button goes back to its original state after the click and is therefore similar to a momentary electronic switch. If the button carries out a concrete action (as opposed to bringing up a list of preferences, for example), label it with the infinitive verb form of the action (without to ; for example, "Do This" or "Apply"). You have seen buttons in several programs so far, including the very first program in this chapter.

    This is also the parent class of the following two button classes.

  • GtkCheckButton ( GTK_TYPE_CHECK_BUTTON ) is an on/off button. When you click the button, it changes state; another click reverts the button to its original state. Check buttons (sometimes called check boxes) look different than regular buttons. See Section 3.13 for more information on a practically identical widget class, GtkToggleButton .

  • GtkRadioButton ( GTK_TYPE_RADIO_BUTTON ): These buttons typically come in sets; each set represents a single setting. You can select only one of the buttons at a time, and therefore, they resemble the buttons for preset stations on car radios.

The example program you're about to see demonstrates all three of these button types. It is supposed to be an interface for hot drinks. You select the temperature with a radio button, add some options with check buttons, and, finally, prepare your drink with one of three regular buttons.

Figure 3.8 shows the final application.


Figure 3.8: Button demonstration.

Like other examples, this program includes global variables for the radio and check button widgets along with the standard event handlers.

 /* -*-coding: utf-8;-*- */ /* buttons.c -- button demo */ #include <gtk/gtk.h> static GtkRadioButton *radio_temper[3]; static GtkCheckButton *check_option[3]; /* standard event handlers */ gint delete_event(GtkWidget *widget, GdkEvent event, gpointer data) {   return FALSE; } void end_program(GtkWidget *widget, gpointer data) {   gtk_main_quit(); } 

When you click one of the three regular buttons, GTK+ runs the following signal handler to tell you how it will prepare your drink. This is mostly busy, repetitive work; however, the important thing to notice is the active property for the radio and check button objects. GTK+ sets these gboolean values according to the states of the widgets. Also, note that only one of the radio_temper widgets is active at any given time, but any combination of the check buttons is possible.

 void prepare_drink(gpointer drink) {   gboolean scalding, hot, lukewarm = FALSE;   gboolean milk, sugar, rum = FALSE;   /* extract the temperature from radio buttons */   g_object_get(radio_temper[0], "active", &scalding, NULL);   g_object_get(radio_temper[1], "active", &hot, NULL);   g_object_get(radio_temper[2], "active", &lukewarm, NULL);   /* extract any options from check buttons */   g_object_get(check_option[0], "active", &milk, NULL);   g_object_get(check_option[1], "active", &sugar, NULL);   g_object_get(check_option[2], "active", &rum, NULL);   /* Piece together a little statement of drink to prepare. */   g_print("Preparing%s%s%s %s",           scalding ? " scalding" : "",           hot      ? " hot"      : "",           lukewarm ? " lukewarm" : "",           (gchar *) drink);   if (milk  sugar  rum)   {      g_print(" with:%s%s%s",              milk  ? " milk"  : "",              sugar ? " sugar" : "",              rum   ? " rum"   : "");   }   g_print(".\n"); } 

The application's layout consists of three columns (VBoxes) in a horizontal line (HBox).

 int main(int argc, char **argv) {   GtkWindow *window;   GtkHBox *hbox;   GtkVBox *vbox[3];   GtkButton *button_prepare[3];   gint i;   /* initialize GTK+, create a window */   gtk_init(&argc, &argv);   window = g_object_new(GTK_TYPE_WINDOW,                         "title", "Mawa's Drink-o-Matic",                         "border-width", 12,                         NULL);   /* add standard signal handlers */   g_signal_connect(window, "delete_event", G_CALLBACK(delete_event), NULL);   g_signal_connect(window, "destroy", G_CALLBACK(end_program), NULL);   /* create boxes and pack them */   hbox = g_object_new(GTK_TYPE_HBOX, "spacing", 6, NULL);   for (i=0; i<3; i++)   {     vbox[i] = g_object_new(GTK_TYPE_VBOX, "spacing", 6, NULL);     gtk_box_pack_start_defaults(GTK_BOX(hbox), GTK_WIDGET(vbox[i]));   }   gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox)); 

The regular buttons to prepare the drink are are in the following code. Look at the bindings to the prepare_drink() handler; you can now see the origin of its drink parameter.

(You could save a few lines of typing with a macro here, at the cost of a slightly more confusing program.)

 /* create and pack regular buttons for preparing drinks */   /* they go in the leftmost VBox */   for (i=0; i<3; i++)   {     button_prepare[i] = g_object_new(GTK_TYPE_BUTTON,                                      "use-underline", TRUE,                                      NULL);     gtk_box_pack_start_defaults(GTK_BOX(vbox[0]), GTK_WIDGET(button_prepare[i]));   }   g_object_set(button_prepare[0], "label", "Prepare _Coffee", NULL);   g_signal_connect_swapped(button_prepare[0],                            "clicked", G_CALLBACK(prepare_drink), "coffee");   g_object_set(button_prepare[1], "label", "Prepare _Tea", NULL);   g_signal_connect_swapped(button_prepare[1],                            "clicked", G_CALLBACK(prepare_drink), "tea");   g_object_set(button_prepare[2], "label", "Prepare C_ocoa", NULL);   g_signal_connect_swapped(button_prepare[2],                            "clicked", G_CALLBACK(prepare_drink), "cocoa"); 

Creating radio buttons and setting their labels isn't much different than creating regular buttons; all you need is the GTK_TYPE_RADIO_BUTTON class type identifier.

 /* create temperature radio buttons, pack into center VBox */   for (i=0; i<3; i++)   {     radio_temper[i] = g_object_new(GTK_TYPE_RADIO_BUTTON,                                    "use-underline", TRUE,                                    NULL);     gtk_box_pack_start_defaults(GTK_BOX(vbox[1]), GTK_WIDGET(radio_temper[i]));   }   g_object_set(radio_temper[0], "label", "_Scalding", NULL); 

After you create one radio button and are ready to initialize more, you need to group the radio buttons, so that only one in the group is allowed to be active at a time. To do this, set the group property in the remaining radio buttons to the first radio button.

 g_object_set(radio_temper[1],                "label", "_Hot",                "group", radio_temper[0],                NULL);   g_object_set(radio_temper[2],                "label", "_Lukewarm",                "group", radio_temper[0],                NULL); 

There aren't any special properties to worry about when you create the check buttons.

 /* create check buttons for additives, pack into third VBox */   for (i=0; i<3; i++)   {     check_option[i] = g_object_new(GTK_TYPE_CHECK_BUTTON,                                    "use-underline", TRUE,                                    NULL);     gtk_box_pack_start_defaults(GTK_BOX(vbox[2]), GTK_WIDGET(check_option[i]));   }   g_object_set(check_option[0], "label", "_Milk", NULL);   g_object_set(check_option[1], "label", "S_ugar", NULL);   g_object_set(check_option[2], "label", "_Rum", NULL);   /* show window, start main event loop */   gtk_widget_show_all(GTK_WIDGET(window));   gtk_main();   return 0; } 

All GtkButton objects have these two gboolean properties that you can set only when you create the widget:

  • use-underline : Enable a keyboard shortcut for this button. Set the key by placing an underscore ( _ ) before the appropriate character in the label property.

  • use-stock : This button should take on a stock item label with the label property.

Only GtkRadioButton objects have the group property; as you saw in the example, this is a radio button in the group. The easiest way to group radio buttons is to create the first button and then set the other buttons' group properties to the first button. GtkRadioButton and GtkCheckButton have these additional gboolean properties:

  • active is TRUE if the button is the currently selected radio button or is otherwise checked.

  • inconsistent is TRUE if the button is in some sort of transitional or disabled state; the widget will have a strikeout bar or be dimmed. For example, a check button could indicate an attribute in a text editor. If you mark out a large portion of the text with the mouse, the selection could contain text with and without the attribute, and therefore, the check button's active property doesn't make any sense, and therefore, the whole widget should be disabled. The program in Section 3.12 has a concrete example.

All GtkButton objects have signals with this handler prototype:

 void handler(GtkButton *button, gpointer *data); 

The signals and their emission circumstances are:

  • clicked : When you click the button.

  • enter : When you move the mouse pointer into the button.

  • leave : When you move the pointer away from the button.

  • pressed : When you click down on the button.

  • released : When you let go of the button.

  • activate : If you emit this signal with a button object, GTK+ clicks the button for you.

Normally, you should need to bother only with the clicked signal.




The Official GNOME 2 Developers Guide
The Official GNOME 2 Developers Guide
ISBN: 1593270305
EAN: 2147483647
Year: 2004
Pages: 108

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net