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:
(class: Gtk::Button
) Standard buttons, usually
marked with a label or picture; usually they cause something to happen
when you press them. See
Pushbuttons.
(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.
(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.
(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.
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.
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.
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
.
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;
}