The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Каталог документации / Раздел "Программирование, языки" / Оглавление документа

Еще о сигналах и обработчиках

Если испущен какой-либо из сигналов, к которому подключилась программа, вызывается соответствующий обработчик. Наш обработчик "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 -- мощные средства разработки приложений, потому что вы можете думать о реальной функциональности, вместо борьбы за появление окна на экране.


Linux Land
2000-09-15



Спонсоры:
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2021 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру