"delete_event"
завершает цикл событий
"gtk_main()" путем вызова "gtk_main_quit()";
это заставляет "gtk_main()" вернуть управление, что
завершает программу. Обработчик "clicked"
заменяет текст
метки тем же, но перевернутым текстом. Заметьте, что метка была передана в
обработчик как параметр "user_data" в
"gtk_signal_connect()".
Обычно, ошибочно думают что все сигналы используют один и тот же тип
обработчика. Каждый сигнал требует обработчик с определенным
типом и набором аргументов и определенным поведением. Сигнал
"clicked"
имеет очень распространенный тип обработчика; его
обработчик принимает указатель на виджет, который испустил сигнал и любой
"user_data"-параметр, который предоставляет программист.
Обработчик должен вернуть void, иначе может
произойти порча памяти.
С другой стороны, "delete_event"
является особым случаем. Он
принимает три аргумента; первый и последний аналогичны "clicked"
,
тогда как второй является указателем на событие, которое породило сигнал
(события -- это сообщения от X приложению, оповещающие о
передвижениях мыши, нажатиях на клавиши и т.п.). Обработчик
"delete_event"
возвращает волшебное значение:
если вернули FALSE, значит Gtk+ удалит окно;
а если TRUE -- то ничего не сделает. Возвращайте
TRUE, если вам надо сделать что-то отличное от удаления
окна; например, если вы захотите предупредить пользователя о несохраненном
документе.
Заголовочные файлы виджетов -- наилучшее быстрое справочное руководство по
типу обработчиков. Структура класса для виджета будет иметь место
для обработчика сигнала по умолчанию; ваш обработчик должен быть смоделирован
на основе обработчика по умолчанию. Например, в "gtk/gtkbutton.h"
структура класса GtkButton выглядит примерно так:
struct _GtkButtonClass
{
GtkBinClass parent_class;
void (* pressed) (GtkButton *button);
void (* released) (GtkButton *button);
void (* clicked) (GtkButton *button);
void (* enter) (GtkButton *button);
void (* leave) (GtkButton *button);
};
Глава 9 объясняет, для чего нужна структура класса; а сейчас, просто обратите
внимание на указатели на функции, и отметьте, что они соответствуют сигналам.
Для перехода от этого:
void (* clicked) (GtkButton *button);
к этому:
static void button_click_cb(GtkWidget *w, gpointer data);
просто добавьте gpointer data к описанию функции в
структуре класса. В Hello, World я также сменил тип
с GtkButton* на GtkWidget*; это
делается часто, так как может быть более удобно иметь
GtkWidget*. Аргумент всегда будет кнопкой
(GtkButton), испускающей сигнал.
Другой пример может быть полезен; вот "delete_event"
из
"gtk/gtkwidget.h":
gint (* delete_event) (GtkWidget *widget, GdkEventAny *event);
а вот обработчик из Hello, World:
static gint delete_event_cb(GtkWidget *w, GdkEventAny *e,
gpointer data);
Ну вот и все с этим. Вы можете писать простые приложения Gtk+, используя только информацию, представленную в этом разделе. Gtk+ и Gnome -- мощные средства разработки приложений, потому что вы можете думать о реальной функциональности, вместо борьбы за появление окна на экране.