Next Previous Contents

5. The Button Widget

We've already seen quite a bit of the button widget. We've been using it rather heavily in our examples so far, but the chances are that you'll use it rather heavily throughout your GTK-- career, so it's a useful thing to introduce early on. This chapter provides a more thorough discussion of this important widget.

GTK-- provides four basic types of buttons:

Pushbuttons

(class: Gtk::Button) Standard buttons, usually marked with a label or picture; usually they cause something to happen when you press them. See Pushbuttons.

Toggle buttons

(class: Gtk::ToggleButton) These look like pushbuttons, but act differently: when you press a Pushbutton, it "springs" back up; a toggle button stays down until you press it again. Useful when you need an on/off switch. See Toggle Buttons.

Checkboxes

(class: Gtk::CheckButton) These are buttons which act like toggle buttons, but are much smaller. They are usually marked with a label off to the side. They're useful in all sorts of situations where you need an on/off setting. Whether you use this or a toggle button is a matter of the situation, the amount of space you have, personal preference, etc. See Checkboxes.

Radio buttons

(class: Gtk::RadioButton) Named after the station-selectors on old car radios, these buttons travel in groups; pressing one causes all the others in its group to turn off. They are similar in form to Checkboxes (i.e., small control with a label to the side), but usually look different. Radio buttons are a good way to control options which are mutually exclusive. See Radio Buttons.

Note that, because of GTK's theming system, the appearance of these widgets will vary. In the case of checkboxes and radio buttons, they may vary considerably.

5.1 Pushbuttons

There are two ways to create a pushbutton: you can pass a string to the Gtk::Button constructor to create a button with a label, or pass no argument to it to create a blank button. If you make a blank button, you can pack a label or pixmap (icon or picture) into it. You can also put another container widget into it, and place more widgets inside that. (This makes it possible to construct rather unusual layouts - imagine packing a button inside another button!)

Here's an example of creating a button with a picture and a label in it. We've broken up the code to make it easy for you to use in your own programs.

Source location: examples/buttons/buttons.cc

#include <iostream>
#include <gtk--/main.h>
#include <gtk--/window.h>
#include <gtk--/button.h>

using std::cout;

using SigC::slot;
using SigC::bind;

class Buttons : public Gtk::Window
{
public:
  Gtk::Button *m_button;

  Buttons();
  ~Buttons();

  void callback(char *data) 
    {
      cout << "Hello again - " << data << " was pressed" << endl;
    }

  gint delete_event_impl(GdkEventAny*) { 
    Gtk::Main::quit(); return 0; 
  }
  
};

Buttons::Buttons() 
{
  m_button = manage(new Gtk::Button());
  m_button -> add_pixlabel("info.xpm", "cool button");
   
  set_title("Pixmap'd buttons!");
  set_border_width(10);
  
  m_button->clicked.connect(bind<char*>(slot(this, &Buttons::callback),
                                        "cool button"));
  
  add(*m_button);
  show_all();
}

Buttons::~Buttons() {};

int main (int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  Buttons buttons;

  kit.run();
  return 0;
}

Note that the XPMLabelBox class can be used to place XPMs and labels into any widget that can be a container.

The Gtk::Button widget has the following signals:

pressed

Emitted when the button is pressed.

released

Emitted when the button is released.

clicked

Emitted when the button is pressed and released.

enter

Emitted when the mouse pointer moves over the button's window.

leave

Emitted when the mouse pointer leaves the button's window.

5.2 Toggle Buttons

The Gtk::ToggleButton constructors are:

Gtk::ToggleButton();
Gtk::ToggleButton(const string &label);

These work exactly the same as the Gtk::Button constructors.

To retrieve the state of the toggle button, you can use the method Gtk::ToggleButton::get_active(); this returns true if the button is "down". You can also set the toggle button's state; the member function to use for this is:

void Gtk::ToggleButton::set_active(bool state);

Pass true to this method to force the button "down". Note that if you do this, and the state is actually changed, it causes the "clicked" signal to be emitted. This is usually what you want.

You can use the following function to toggle the button, rather than forcing it to be up or down:

void Gtk::ToggleButton::toggled ();

This switches the button's state, and causes the toggled signal to be emitted.

5.3 Checkboxes

Gtk::CheckButton inherits from Gtk::ToggleButton. The only real difference between the two is Gtk::CheckButton's appearance; you can check, set, and toggle a checkbox using the same member functions as you would for Gtk::ToggleButton.

The two Gtk::CheckButton constructors are

Gtk::CheckButton();
Gtk::CheckButton(const string &label);

and they work exactly as the ones for Gtk::Button.

5.4 Radio Buttons

Like checkboxes, radio buttons also inherit from Gtk::ToggleButton, but there are more substantial differences than mere appearance, due to their travelling in groups (you could have a radio button by itself, but they're very social beings, and get lonely rather easily. Also, it doesn't make much sense).

The constructors for Gtk::RadioButton are:

  Gtk::RadioButton();
  Gtk::RadioButton(const string &label, gfloat xalign=0.5, gfloat yalign=0.5);
  Gtk::RadioButton(Group &groupx);
  Gtk::RadioButton(Group &groupx,
                   const string &label, gfloat xalign=0.5, gfloat yalign=0.5);

The first constructor makes a new radio button without a label; the second lets you specify a label, and also allows you to tweak the positioning of the label text, if you want. The third and fourth constructors are like the first two, except you also specify a group to put the new buttons in. (Of course, the group must exist first; read on to see how this works.)

There are two ways to set up a group of radio buttons. The first way is to create the buttons, and set up their groups afterwards. Only the first two constructors are used. In the following example, we make a new window class called RadioButtons, and then put three radio buttons in it:

  class RadioButtons : public Gtk::Window
  {
      Gtk::RadioButton m_rb1, m_rb2, m_rb3;
      RadioButtons();
  };     

  RadioButtons::RadioButtons()
    : Window(),  
      m_rb1("button1"),
      m_rb2("button2"),
      m_rb3("button3")
  {
      m_rb2.set_group(m_rb1.group());
      m_rb3.set_group(m_rb2.group());
  }

When a radio button is created without a group, a new group is made for it; this group can be retrieved through the radio button's group() method. A radio button's group can be changed using the set_group() method. In the example, we created three radio buttons without specifying groups for them. We then used set_group() on radio button m_rb2 to set its group to the same as m_rb1, and did likewise with m_rb3. The result is that all three buttons belong to the same group.

The second way to set up radio buttons is to make a group first, and then add radio buttons to it. Here's an example:

  class RadioButtons : public Gtk::Window
  {
      RadioButtons();
  };     

  RadioButtons::RadioButtons()
    : Window()
  {
      Gtk::RadioButton::Group gr;
      Gtk::RadioButton *m_rb1=manage( new Gtk::RadioButton(gr,"button1"));
      Gtk::RadioButton *m_rb2=manage( new Gtk::RadioButton(gr,"button2"));
      Gtk::RadioButton *m_rb3=manage( new Gtk::RadioButton(gr,"button3"));
  }

We made a new group by simply declaring a variable, gr, of type Gtk::RadioButton::Group. Then we made three radio buttons, using the third constructor to make each of them part of gr.

Radio buttons are "off" when created; this means that when you first make a group of them, they'll all be off. Often this is not what you want (or what the user expects), so don't forget to turn one of them on using set_active():

void Gtk::ToggleButton::set_active(bool state);

This function is inherited from Gtk::ToggleButton, and works the same.

The following is an example of using radio buttons:

Source location: examples/radiobuttons/radiobuttons.cc

#include <gtk--/main.h>
#include <gtk--/window.h>
#include <gtk--/box.h>
#include <gtk--/separator.h>
#include <gtk--/button.h>
#include <gtk--/radiobutton.h>
// Gtk-- version of the radiobuttons example from the gtk+ tutorial

class RadioButtons : public Gtk::Window
{
public:

  Gtk::VBox m_box1, m_box2, m_box3;
  Gtk::RadioButton m_rb1, m_rb2, m_rb3;
  Gtk::HSeparator m_seperator;
  Gtk::Button m_closeButton;
  
  RadioButtons();
  
  gint delete_event_impl(GdkEventAny*) { 
    Gtk::Main::quit(); return 0; 
  }

  void close_application() 
    {
      delete_event_impl(0);
    }

};

RadioButtons::RadioButtons() :
  m_box1(false, 0),
  m_box2(false, 10),
  m_box3(false, 10),
  m_rb1("button1"),
  m_rb2("button2"),
  m_rb3("button3"),
  m_closeButton("close")
{
  set_title("radio buttons");
  set_border_width(0);

  m_rb2.set_group(m_rb1.group());
  m_rb3.set_group(m_rb1.group());
  
  add(m_box1);
  
  m_box2.set_border_width(10);
  m_box1.pack_start(m_box2);
  
  m_box2.pack_start(m_rb1);
  m_box2.pack_start(m_rb2);
  m_rb2.set_active(true);
  
  m_box2.pack_start(m_rb3);
  
  m_box1.pack_start(m_seperator, false, true, 0);
  
  m_box3.set_border_width(10);
  m_box1.pack_start(m_box3, false, true, 0);
  
  m_closeButton.clicked.connect(slot(this,&RadioButtons::close_application));
  
  m_box3.pack_start(m_closeButton);
  m_closeButton.set_flags(GTK_CAN_DEFAULT);
  m_closeButton.grab_default();
  
  show_all();
}

int main (int argc, char *argv[])
{
          
  // all GTK applications must have a gtk_main(). Control ends here
  // and waits for an event to occur (like a key press or mouse event).
  Gtk::Main myapp(&argc, &argv);

  RadioButtons radiobuttons;

  myapp.run();
  return 0;
}


Next Previous Contents