2.1. Gtk::Button & Signals

Since buttons, signals and callbacks always go hand-in-hand so I am just going to put them into one chapter.

1. Signals & Callbacks:
Like many other GUI toolkits, such as wxWidget, gtkmm is event-driven, meaning that it relies on signals and callbacks to interact with the users. A signal is emitted when the users perform some actions with your widgets, such as pressing a mouse button. And in order to make the application react to those signals, we set up “signal handlers”, or callback functions, to do something after the signals are emitted. (For example, we can have a function (or “signal handler”) creating a notification dialog and showing it on the screen after the users click the button (or emit the “clicked” signals).

In order to preserve the object-oriented approach, gtkmm uses the libsigc++, a type-safe callback system for standard C++, to connect signals with callback functions (See the libsigc++ homepage). The following line is an example of connecting a Gtk::Button “clicked” signal with a callback function (“signal handler”) called “on_button_clicked” (You don’t have to remember or examine this code line. Just simply take a look at it. I will explain this statement for you later in this chapter):

button.signal_clicked().connect(sigc::mem_fun(*this, &HelloWorld::on_button_clicked));

2. An improved HelloWorld with Gtk::Button:
Like last time, we will start with the code of the program first and then examine it later. At present, as you already have some basic knowledge about Gtkmm, try to first read the following codes without looking at the explanation below it.

helloworld_2.1.cc

#include <iostream>
#include <gtkmm.h>

/* Create the HelloWorld class 
 * by inheritance from Gtk::Window 
 */
class HelloWorld : public Gtk::Window {
public:
  //Constructors & Destructors
  HelloWorld();
  virtual ~HelloWorld();
  
protected:
  //Signal Handler
  virtual void on_button_clicked();
  
  //Child widget
  Gtk::Button button;
};

/* The HelloWorld::HelloWorld() constructor */
HelloWorld::HelloWorld() : 
  //set the button's label
  button("Click me!")
{
  //set the window's title
  set_title("Hello World!");
  
  //connect the button's clicked signal to member 
  //function HelloWorld::on_button_clicked()
  button.signal_clicked().connect(sigc::mem_fun(*this, 
                   &HelloWorld::on_button_clicked));
  
  //add the button to the main window
  add(button);
  
  show_all_children();
}

/* The HelloWorld::~HelloWorld() destructor */
HelloWorld::~HelloWorld() {
}

/* Signal-Handler for Gtk::Button button */
void HelloWorld::on_button_clicked() {
  std::cout << "The button was clicked!!" << std::endl;
}

/* The main program */
int main(int argc, char *argv[]) {
  //Initialize Gtkmm
  Gtk::Main kit(argc, argv);
  
  //Create the helloworld object
  HelloWorld helloworld;
  
  //Display the helloworld window
  Gtk::Main::run(helloworld);

  return 0;
}

So did you see some new things in this code comparing to the one in chapter 1? Let’s examine it!

3. Create the Gtk::Button:
In the above example, I first create an empty button inside HelloWorld class by using:

Gtk::Button button;

and then set its label in the constructor’s initializer list.

HelloWorld::HelloWorld() : 
  button("Click me!")
{
  //the rest of the code...
}

As I have mentioned above, you can use the Gtk::Button::set_label() member function to set the label of button. This function accepts a Glib::ustring as its only argument.

void Gtk::Button::set_label(const Glib::ustring& label);

/* label: the button's label
 */

According to the Gtkmm reference, Gtk::Window is inherited from Gtk::Container. Therefore, we can use the Gtk::Container::add() method of the Gtk::Container class to add button to the helloworld window:

void Gtk::Container::add(Gtk::Widget& widget);

/* widget: the widget need to be packed inside the container
 */

Please notes that all the functions from the base class can be called directly inside the derived class. You don’t have to create a base object and then call out its method. For example, you just need to use .add() inside the HelloWorld class to directly add widget into the helloworld window, instead of creating a Gtk::Container and invoke its method like this:

/* ERROR: HelloWorld, derived from Gtk::Window, is already a 
 * container. Just need to invoke .add() inside HelloWorld 
 */
Gtk::Container container;
container.add(button);

4. Connect the signal to the callback:
Now here comes the fun part of this chapter.

Advertisements

Tags: , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: