The follwing data types are passed into event handlers by Gtk--. For each data type listed, the signals that use this data type are listed.
Source location: examples/helloworld/helloworld.cc
#include <iostream>
#include <gtk--/button.h>
#include <gtk--/main.h>
#include <gtk--/window.h>
using std::cout;
using std::endl;
using SigC::slot;
class HelloWorld : public Gtk::Window
{
Gtk::Button m_button;
public:
HelloWorld();
// this is a callback function. the data arguments are ignored in this example..
// More on callbacks below.
void hello();
// When the window is given the "delete_event" signal (this is given
// by the window manager, usually by the 'close' option, or on the
// titlebar), this in turn calls the delete_event signal and the
// delete_event_impl virtual function. We will override the
// virtual function.
virtual int delete_event_impl(GdkEventAny *event);
};
// This is a callback that will hand a widget being destroyed.
void destroy_handler()
{
Gtk::Main::quit();
}
HelloWorld::HelloWorld()
: Gtk::Window(GTK_WINDOW_TOPLEVEL), // create a new window
m_button("Hello World") // creates a new button with the label "Hello World".
{
// Here we connect the "destroy" event to a signal handler.
// This event occurs when we call gtk_widget_destroy() on the window,
// or if we return 'false' in the "delete_event" callback.
destroy.connect(slot(&destroy_handler));
// Sets the border width of the window.
set_border_width(10);
// When the button receives the "clicked" signal, it will call the
// hello() method. The hello() method is defined below.
m_button.clicked.connect(slot(this, &HelloWorld::hello));
// This will cause the window to be destroyed by calling
// gtk_widget_destroy(window) when "clicked". Again, the destroy
// signal could come from here, or the window manager.
m_button.clicked.connect(destroy.slot());
// This packs the button into the window (a gtk container).
add(m_button);
// The final step is to display this newly created widget...
m_button.show();
// and the window
show();
// NOTE : These last two lines can be replaced by
//show_all();
}
void HelloWorld::hello()
{
cout << "Hello World" << endl;
}
int HelloWorld::delete_event_impl(GdkEventAny *event)
{
cout << "delete event occured" << endl;
// if you return false in the "delete_event" signal handler,
// GTK will emit the "destroy" signal. Returning true means
// you don't want the window to be destroyed.
// This is useful for popping up 'are you sure you want to quit ?'
// type dialogs.
// Change true to false and the main window will be destroyed with
// a "delete_event".
return true;
}
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 kit(argc, argv);
HelloWorld helloworld;
kit.run();
return 0;
}
Try to compile and run it before going on.
Pretty thrilling, eh? Let's examine the code. First, the
HelloWorld class:
class HelloWorld : public Gtk::Window
{
Gtk::Button m_button;
public:
HelloWorld();
void hello();
virtual int delete_event_impl(GdkEventAny *event);
};
This class implements the "Hello World" window. It's derived from
Gtk::Window, and has a single Gtk::Button as a member.
We'll be using two signals, and we also override the _impl method
for the widget's delete_event signal. We've chosen to use the
constructor to do all of the initialisation work for the window,
including setting up the signals. Here it is, with the comments
omitted:
HelloWorld::HelloWorld()
: Gtk::Window(GTK_WINDOW_TOPLEVEL),
m_button("Hello World")
{
set_border_width(10);
destroy.connect(slot(&destroy_handler));
m_button.clicked.connect(slot(this, &HelloWorld::hello));
m_button.clicked.connect(destroy.slot());
add(m_button);
m_button.show();
show();
}
We've placed two initialiser statements in the declaration. The first
one provides an argument to our parent's constructor; the argument
we've provided here simply tells GTK-- to make us a full-fledged
application window, instead of a transient dialog window or something
of that sort. The next initialiser initialises our m_button
object; we give it the label "Hello World".
Next we run the window's set_border_width() method. This sets
the amount of space between the sides of the window and the widget it
contains (windows can only contain a single widget, but this isn't
really a limitation, as you'll see later on).
Then we hook up some signals. We need to handle three signals:
delete_event and destroy for the window, and clicked
for the button. delete_event and destroy are defined in
Gtk::Widget, and are therefore common to all GTK-- widgets.
(delete_event is one of a special class of signals which
correspond to X events. We talk about those in Chapter 2.) A window
receives a delete_event when someone clicks its close box; when
it receives a destroy, it disappears (the way this mechanism
works is explained below).
First we hook up the destroy signal to a callback,
destroy_handler(), which looks like this:
void destroy_handler()
{
Gtk::Main::quit();
}
When destroy_handler() is called, it invokes
Gtk::Main::quit(), which, surprisingly enough, quits the
program. This is what we want; when our only window disappears, we
shouldn't keep running.
We next hook up two callbacks to m_button's clicked signal.
The first of these runs one of our member functions, hello(),
which prints our friendly greeting to stdout. The other one may
be a bit odd-looking at first, because we didn't use slot() here;
instead, we used a member function of destroy called
slot(). This function, which is part of every libsigc++
Signal object, returns a slot which, when called, will emit the
signal it came from. So, when the clicked signal occurs, and it
calls this slot, that slot will emit the destroy signal, which
will call the destroy_handler() function. (You can chain signals
up this way as much as you please.) Therefore, clicking the button
causes the program to quit.
Next, we use the window's add() method to put m_button in
the window. (add() comes from Gtk::Container, which is
described in the chapter on container widgets.) The add() method
places the widget you give it in the window, but it doesn't display
the widget.