Tutorial

Inti Logo

« Widget Overview
Adjustments »

The Button Widget

  1. Normal Buttons
  2. Toggle Buttons
  3. Check Buttons
  4. Radio Buttons

Normal Buttons

We've almost seen all there is to see of the button widget. It's pretty simple. There are however several ways to create a button. You can use one following constructors:

Button();

explicit Button(Gtk::Image& image);

explicit Button(const String& label, bool use_underline = false);


to create an blank button, a button with an image, a button with a label or a button with a mnemonic label if use_underline is true. If you create a blank button it is then up to you to pack a label or image into the new button by calling Gtk::Container::add(). You can also create a button that displays a stock GTK image and text by calling to following constructor:
 
explicit StockButton(const char *stock_id);

Here's an example of using Button() to create a button with a image and a label in it. I've broken up the code to create an image button class so you can use it in your programs. There are further examples of using images later in the tutorial.

CoolButton

The header file for Pixmap'd Buttons! is buttons.h:

#include<inti/main.h>
#include <inti/core.h>
#include <inti/gtk/button.h>

using namespace Inti;

class ImageButton : public Gtk::Button
{
protected:
    virtual void on_clicked();

public:
    ImageButton(const String& xpm_filename, const String& label_text);
    virtual ~ImageButton();
};

class ButtonWindow : public Gtk::Window
{
public:
    ButtonWindow();
    virtual ~ButtonWindow();
};

and the source file is buttons.cc:

#include"buttons.h"
#include <inti/gtk/image.h>
#include <inti/gtk/label.h>
#include <iostream>

// ImageButton

ImageButton::ImageButton(const String& xpm_filename, const String& label_text)
{
    // Create box for image and label
    Gtk::HBox *box = new Gtk::HBox;
    box->set_border_width(2);

    // Now on to the image stuff
    Gtk::Image *image = new Gtk::Image(xpm_filename);

    // Create a label for the button
    Gtk::Label *label = new Gtk::Label(label_text);

    // Pack the image and label into the box
    box->pack_start(*image, false, false, 3);
    box->pack_start(*label, false,false, 3);

    box->show_all();
    add(*box);
}

ImageButton::~ImageButton()
{
}

void
ImageButton::on_clicked()
{
    using namespace std;

    cout << "Hello again - cool button was pressed" << endl;
}

// ButtonWindow

ButtonWindow::ButtonWindow()
{
    set_title("Pixmap'd Buttons!");
    set_border_width(10);

    // Create a new button
    ImageButton *button = new ImageButton("info.xpm", "cool button");
    add(*button);
    button->show();
}

ButtonWindow::~ButtonWindow()
{
}

int main(int argc, char *argv[])
{
    using namespace Main;

    init(&argc, &argv);

    ButtonWindow window;
    window.sig_destroy().connect(slot(&Inti::Main::quit));
    window.show();

    run();
    return 0;
}


The Button widget has the following protected static signals:
Each protected signal has a corresponding public accessor method that is used to connect to the protected signal. The public methods are for convenience and pass the object pointer to the protected signal for you. The Button widget has the following public signal accessor methods:


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.

To create a toggle button you can use one of the following constructors:

ToggleButton();

explicit ToggleButton(const String& label, bool use_underline = false);

The first creates a blank toggle button, and the second a button with a label widget already packed into it. If use_underline is true the label is parsed for '_'-prefixed mnemonic characters.

To retrieve the state of the toggle widget, including radio and check buttons, we use a construct as shown in our example below. This tests the state of the toggle button, by accessing the active field of the toggle widget's structure. The signal of interest to us emitted by toggle buttons (the toggle button, check button, and radio button widgets) is the "toggled" signal. There are two ways to check the state of these buttons.
  1. Derive your own class from the existing button class and override it's protected virtual on_toggled signal handler.
  2. Create an instance of the existing button class and connect a slot to it's toggled signal.
Using the second method to check the state of a toggle button, create a new button instance and connect a signal handler to it's toggled signal. This is done using a slot.

Gtk::ToggleButton *button = new Gtk::ToggleButton("Button");

button->sig_toggled().connect(bind(slot(this, &MyClass::on_button_toggled), button));


Since the on_button_toggled slot is a method in MyClass you will have to bind the button pointer to the slot so that it gets passed as the last argument to the slot method when a toggled signal is emitted. In the case of on_button_toggled() it is the only argument because the toggled signal has no parameters. Remember bound slots, I introduced them to you in the Theory of Signals and Slots. To check the state of the toggle button use the following construct:

void
MyClass::on_button_toggled(Gtk::ToggleButton *button)
{
    if (button->get_active())
    {
        // If control reaches here, the toggle button is down
    }
    else
    {
        // If control reaches here, the toggle button is up
    }
}

To force the state of a toggle button, and its children, the radio and check buttons, use this method:

void set_active(bool is_active);

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

Note that when you use the Gtk::ToggleButton::set_active() method, and the state is actually changed, it causes the "clicked" and "toggled" signals to be emitted from the button.

bool get_active() const;

This returns the current state of the toggle button as a bool true/false value.


Check Buttons

Check buttons inherit many properties and functions from 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 constructors are similar to those of the normal button.

CheckButton();

explicit CheckButton(const String& label, bool use_underline = false);


The second constructor  creates a check button with a label beside it. Checking the state of the check button is identical to that of the toggle button.


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 the following constructors:

RadioButton();

explicit RadioButton(Group *group);

explicit RadioButton(const Gtk::RadioButton *group);

RadioButton(const String& label, bool use_underline = false);

RadioButton(Group *group, const String& label, bool use_underline = false);

RadioButton(const Gtk::RadioButton *group, const String& label, bool use_underline = false);

You'll notice the extra argument to these constructors. They require a group to perform their duty properly. The group specified can either be a pointer to a Group, which is just a typedef for a GSList or a pointer to a radio button already in the group. The first radio button can be created by either calling the first  or fourth constructors, or by calling the fifth or sixth constructors and passing null for the group argument. Subsequent radio buttons must be constructed by either calling the fifth or sixth constructors and specifying the group. For the fifth constructor, the group can be retrieved by calling:

Group* get_group() const;

The important thing to remember is that Gtk::RadioButton::get_group() must be called on the previous button and the result passed in as the group argument to the new button. Then the result of calling Gtk::RadioButton::get_group() on the new button is passed into the constructor call for the next button. This allows a chain of buttons to be established. The example below should make this clear.

Gtk::RadioButton::Group *group = 0;
Gtk::RadioButton *button = new Gtk::RadioButton(group, "button1");
pack_start(*button);
button->show();
group = button->get_group();
button = new Gtk::RadioButton(group, "button2");
pack_start(*button);
button->show();


You can shorten this slightly by using either of the following syntax, which removes the need for a variable to hold the Group (list) of buttons:

Gtk::RadioButton *button2 = new Gtk::RadioButton(button1->get_group(), "button2");

or


Gtk::RadioButton *button2 = new Gtk::RadioButton(button1, "button2");

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

void set_active(bool is_active);

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

RadioButtons

The header file for radio buttons is radiobuttons.h:

#include<inti/main.h>
#include <inti/core.h>


using namespace Inti;

class RadioButtonWindow : public Gtk::Window
{
public:
    RadioButtonWindow();
    ~RadioButtonWindow();
};


and the source file is radiobuttons.cc:

#include"radiobuttons.h"
#include <inti/gtk/radiobutton.h>
#include <inti/gtk/separator.h>


RadioButtonWindow::RadioButtonWindow()
{
    set_title("radio buttons");
    set_border_width(0);

    Gtk::VBox *box1 = new Gtk::VBox;
    add(*box1);
    box1->show();

    Gtk::VBox *box2 = new Gtk::VBox(false, 10);
    box2->set_border_width(10);
    box1->pack_start(*box2);
    box2->show();

    // When adding the first radio button to a group pass null for the group parameter.
    Gtk::RadioButton::Group *group = 0;
    Gtk::RadioButton *radio_button = new Gtk::RadioButton(group, "button1");
    box2->pack_start(*radio_button);
    radio_button->show();

    // Then, pass the group returned by calling get_group() to the constructors of the other buttons.
    group = radio_button->get_group();
    radio_button = new Gtk::RadioButton(group, "button2");
    radio_button->set_active(true);
    box2->pack_start(*radio_button);
    radio_button->show();

    // Or even easier, pass a pointer to a radio button already in the group.
    radio_button = new Gtk::RadioButton(radio_button, "button3");
    box2->pack_start(*radio_button);
    radio_button->show();

    Gtk::HSeparator *separator = new Gtk::HSeparator;
    box1->pack_start(*separator, false);
    separator->show();

    box2 = new Gtk::VBox(false, 10);
    box2->set_border_width(10);
    box1->pack_start(*box2, false);
    box2->show();

    Gtk::Button *button = new Gtk::Button("close");
    button->sig_clicked().connect(slot(this, &RadioButtonWindow::dispose));
    box2->pack_start(*button);
    button->set_flags(Gtk::CAN_DEFAULT);
    button->grab_default();
    button->show();
}

RadioButtonWindow::~RadioButtonWindow()
{
}

int main (int argc, char *argv[])
{
    using namespace Main;

    init(&argc, &argv);

    RadioButtonWindow window;
    window.sig_destroy().connect(slot(&Inti::Main::quit));
    window.show();

    run();
    return 0;
}




« Widget Overview Index
Top
Adjustments »