Progmar Marcin Załęczny

Kod programu witaj świecie z obsługą sygnału wyjścia

main.cpp

#include <gtk/gtk.h>

gboolean onDeleteEvent(GtkWidget* widget, GdkEvent* event, gpointer data) {
	gtk_main_quit();
	return FALSE;
}

int main(int argc, char** argv) {
	GtkBuilder *builder;
	GError *error;
	GtkWidget *window;
	
	gtk_init(&argc, &argv);
	
	builder = gtk_builder_new();
	error = NULL;
	gtk_builder_add_from_file(builder, "main_window.ui", &error);
	if (error) {
		g_print("Wystąpił błąd: %s\n", error->message);
		g_error_free(error);
		return -1;
	}
	window = GTK_WIDGET(gtk_builder_get_object(builder, "wndHelloWorld"));
	g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(onDeleteEvent), NULL);
	gtk_widget_show_all(window);
	
	gtk_main();
	return 0;
}

Wyjaśnienie kodu

Zmiany w stosunku do poprzedniej wersji programu zostały zapisane pogrubioną czcionką. Widać, że doszła funkcja onDeleteEvent oraz wywołanie funkcji g_signal_connect. Funkcja g_signal_connect służy do podpinania funkcji obsługi zdarzeń pod wystąpienie konkretnego zdarzenia:

g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(onDeleteEvent), NULL);

Pierwszy argument typu GObject jest obiektem, dla którego podpinamy funkcję obsługi zdarzenia.
Drugi argument typu gchar* to tekst oznaczający nazwę zdarzenia/sygnału, które chcemy obsłużyć przez naszą funkcję callback.
Trzeci argument - typu GCallback - jest funkcją, która zostanie wywołana po otrzymanu sygnału bądź zdarzenia.
Czwarty argument jest wskaźnikiem na dane, które mają zostać przekazane powyższej funkcji obsługi zdarzenia.

Widzimy, że jako GObject przekazujemy obiekt naszego okna. Możemy go bezpiecznie rzutować przy pomocy makra G_OBJECT, gdyż każdy widget (w tym okno) pochodzi od klasy GObject. Naszą funkcję obsługi zdarzenia - onDeleteEvent - przekazujemy rzutując ją na typ GCallback przy pomocy makra G_CALLBACK. Jako dodatkowe dane przekazujemu pusty wskaźnik NULL.

Sygnał delete-event wysyłany jest w momencie, gdy użytkownik kliknie przycisk zamykający okno. Funkcja obsługi sygnału delete-event musi mieć następującą sygnaturę:

gboolean user_function(GtkWidget *widget, GdkEvent *event, gpointer user_data)

W naszej funkcji obsługi tego zdarzenia wywołujemy funkcję gtk_main_quit(), która przerywa działanie pętli gtk_main(). Zwracając jako rezultat wartość FALSE pozwalamy, żeby nasze okno zostało zniszczone. Gdybyśmy nie wywołali funkcji gtk_main_quit() i zwrócili wartość TRUE, zablokowalibyśmy zniszczenie okna po kliknięciu w przycisk zamykający okno. Zachowanie to można wykorzystać do wyświetlenia komunikatu potwierdzającego chęć zamknięcia aplikacji. Stosowny przykład zostanie przedstawiony w dalszej części tutorialu.