Next Previous 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 are however two ways to create a button. You can use the GTK_BUTON::make_with_label() to create a button with a label, or use GTK_BUTON::make 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::make to create a button with a picture and a label in it. I've broken up the code to create a box from the rest so you can use it in your programs. There are further examples of using pixmaps later in the tutorial.

-- example-start buttons buttons.e
class BUTTONS
inherit
   -- All constants we need are defined in the class below.
   -- eg gtk_window_toplevel etc.
   GTK_CONSTANTS
   -- This class contains common features like vegtk_init and so
   VEGTK_MAIN
   -- If we need to handle callbacks we must inherit from the below
   -- class
   VEGTK_CALLBACK_HANDLER
creation
   make
feature -- support
   xpm_label_box( parent : GTK_WIDGET;
                  xpm_filename,label_text : STRING) : GTK_BOX is
   local
      box1 : GTK_HBOX;
      label: GTK_LABEL;
      pixmapwid : GTK_PIXMAP;
      pixmap : GDK_PIXMAP;
      style : GTK_STYLE;
   do
      -- Create box for xpm and label
      !!box1.make (False, 0);
      box1.set_border_width (2);

      -- Get the style of the button to get the
      -- background color. */
      style := parent.get_style;

      -- Now on to the xpm stuff
      !!pixmap.make_from_xpm (parent.window,style.bg(Gtk_state_normal),
                            xpm_filename);
      !!pixmapwid.make(pixmap, pixmap.mask);

      --Create a label for the button
      !!label.make (label_text);

      -- Pack the pixmap and label into the box
      box1.pack_start (pixmapwid, False, False, 3);

      box1.pack_start (label, False, False, 3);

      pixmapwid.show;
      label.show

      Result := box1;
   end
feature -- Callback handlers
   callback (data : ANY) is
   -- Our usual callback.
   do
      print("Hello again - ");
      print(data);
      print(" was pressed%N");
   end

   delete_event is
   -- This callback quits the program
   do
       gtk_main_quit;
   end

feature -- Creation
   make is
   local
      window : GTK_WINDOW;
      button : GTK_BUTTON;
      box1   : GTK_BOX;
   do
      -- This is called in all GTK applications. Arguments are parsed
      -- from the command line and are returned to the application.
      vegtk_init

      -- Create a new window
      !!window.make(Gtk_window_toplevel);

      -- Set the window title
      window.set_title ("Pixmap'd Buttons!");

      -- Set a handler for delete_event that immediately
      -- exits GTK. */
      signal_connect (window, "delete_event",$delete_event);

      -- Sets the border width of the window.
      window.set_border_width ( 10);

      window.realize;

      -- Create a new button
      !!button.make;

      -- Connect the "clicked" signal of the button to our callback */
      signal_connect_with_data (button, "clicked",$callback,"cool button");

      -- This calls our box creating function
      box1 := xpm_label_box(window, "info.xpm", "cool button");

      -- Pack and show all our widgets
      box1.show;

      button.add (box1);

      button.show;

      window.add (button);

      window.show;

      -- Rest in gtk_main and wait for the fun to begin!
      gtk_main;
   end -- make
end -- class BUTTONS
-- example-end

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

The Button widget has the following signals:

6.2 Toggle Buttons

Toggle buttons are derived from normal buttons and are very similar, 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.

Creation procedures of the class GTK_TOGGLE_BUTON:

make
make_with_label ( label : STRING )

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 function get_active : BOOLEAN 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 get_active function to determine its state. The callback will look something like:

toggle_button_callback (data : ANY; cb_data : VEGTK_CALLBACK_DATA) is
do
   if cb.data.get_active then
      -- If control reaches here, the toggle button is down

   else
      -- If control reaches here, the toggle button is up
   end -- if
end -- toggle_button_callback

set_active ( arg_state : BOOLEAN )

The above call can be used to set the state of the toggle button, and its children the radio and check buttons. Pass True or False for state argument to specify whether it should be down (depressed) or up (released). Default is up, or False

Note that when you use the set_active procedure, and the state is actually changed, it causes the "clicked" signal to be emitted from the button.

   toggled is

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 used for toggling options on and off in applications.

The two creation procedures of the class GTK_CHECK_BUTTON are similar to those of the normal button.

   make
   make_with_label ( label : STRING )

The make_with_label procedure 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.

Creation procedures of the class RADIO_BUTTON are:

   make ( arg_group : G_SLIST )
   make_with_label ( arg_group : G_SLIST; label : STRING )
   make_with_label_from_widget ( arg_group : GTK_RADIO_BUTTON; label : STRING )
   make_alone_with_label ( label : STRING )

You'll notice the extra argument to these calls. They require a group to perform their duty properly. The first call to make or new_with_label should pass Void as the first argument. Then create a group using feature :

   group : G_SLIST

The important thing to remember is that GTK_RADIO_BUTTON::group must be called for each new button added to the group, with the previous button passed in as an argument. The result is then passed into the call to GTK_RADIO_BUTTON::_make or GTK_RADIO_BUTTON::make_with_label. This allows a chain of buttons to be established. The example below should make this clear.

You can shorten this slightly by using the following syntax, which removes the need for a variable to hold the list of buttons. This form is used in the example to create the third button:

     button2.make_with_label(button1.group,"button2");

It is also a good idea to explicitly set which button should be the default depressed button with:

set_active ( arg_state : BOOLEAN )

Which is of course defined in the GTK_RADIO_BUTTON's ancestor GTK_TOGGLE_BUTTON. This is described in the section on toggle buttons, and works in exactly the same way.

The following example creates a radio button group with three buttons.

-- example-start radiobuttons radiobuttons.e
class RADIOBUTTONS
inherit
   -- All constants we need are defined in the class below.
   -- eg gtk_window_toplevel etc.
   GTK_CONSTANTS
   -- This class contains common features like vegtk_init and so
   VEGTK_MAIN
   -- If we need to handle callbacks we must inherit from the below
   -- class
   VEGTK_CALLBACK_HANDLER
creation
   make
feature -- Callback handlers
   close_application is
   -- This callback quits the program
   do
       gtk_main_quit;
   end

feature -- Creation
   make is
   local
      window : GTK_WINDOW;
      rbutton : GTK_RADIO_BUTTON;
      button : GTK_BUTTON;
      box1,box2   : GTK_VBOX;
      separator : GTK_HSEPARATOR;
   do
      -- This is called in all GTK applications. Arguments are parsed
      -- from the command line and are returned to the application.
      vegtk_init;

      -- Create a new window
      !!window.make(Gtk_window_toplevel);

      -- Set the window title
      window.set_title ("radio buttons");

      -- Set a handler for delete_event that immediately
      -- exits GTK. */
      signal_connect (window, "delete_event",$close_application);

      -- Sets the border width of the window.
      window.set_border_width (0);

      !!box1.make (False, 0);
      window.add (box1);
      box1.show;

      !!box2.make (False, 10);
      box2.set_border_width (10);
      box1.pack_start (box2, True, True, 0);
      box2.show;

      !!rbutton.make_with_label (Void, "button1");
      box2.pack_start (rbutton, True, True, 0);
      rbutton.show;

      !!rbutton.make_with_label(rbutton.group, "button2");
      rbutton.set_active (True);
      box2.pack_start (rbutton, True, True, 0);
      rbutton.show;

      !!rbutton.make_with_label(rbutton.group,"button3");
      box2.pack_start (rbutton, True, True, 0);
      rbutton.show;

      !!separator.make;
      box1.pack_start (separator, False, True, 0);
      separator.show;

      !!box2.make(False, 10);
      box2.set_border_width (10);
      box1.pack_start (box2, False, True, 0);
      box2.show;

      !!button.make_with_label ("close");
      signal_connect (button, "clicked",$close_application);
      box2.pack_start (button, True, True, 0);
      button.set_flags(Gtk_can_default);
      button.grab_default;
      button.show;
      window.show;

      gtk_main;
   end -- make
end
-- example-end
end


Next Previous Contents