Kod programu witaj świecie z demonstracją potwierdzenia wyjścia
main.cpp
#include <gtk/gtk.h>
void onDestroy(GtkWidget* widget, gpointer data) {
gtk_main_quit();
}
gboolean onDeleteEvent(GtkWidget* widget, GdkEvent* event, gpointer data) {
GtkWidget *dialog;
dialog = gtk_message_dialog_new(GTK_WINDOW(widget), GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
"Czy na pewno chcesz opuścić program?");
gtk_window_set_title(GTK_WINDOW(dialog), "Pytanie");
GtkResponseType result = (GtkResponseType)gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
if (result == GTK_RESPONSE_YES) {
return FALSE;
}
return TRUE;
}
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);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(onDestroy), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Wyjaśnienie kodu
Program ten demonstruje jak opuścić działającą aplikację po kliknięciu w przycisk TAK w okienku dialogowym wymagającym potwierdzenia operacji zamknięcia programu. Aby to osiągnąć podpięliśmy funkcje obsługi zdarzenia "delete-event" - onDeleteEvent oraz sygnału "destroy" - onDestroy. Funkcje te różnią się nieco nagłówkami. Pierwsza z nich ma nagłówek:
gboolean user_function(GtkWidget *widget, GdkEvent *event, gpointer user_data)
natomiast druga:
void user_function(GtkWidget *object, gpointer user_data)
O tym jak wygląda nagłówek funkcji obsługi zdarzenia możemy się przekonać w programie devhelp, wpisując w nim frazy wyszukiwania delete-event oraz destroy signal.
Dlaczego użyliśmy tych zdarzeń? Ponieważ w funkcji onDeleteEvent możemy się wycofać z chęci zamknięcia aplikacji zwracając wartość TRUE. Jeśli natomiast zwrócimy w niej wartość FALSE, to okno główne zostanie zniszczone a przed jego zniszczeniem wyemitowany zostanie sygnał destroy. Funkcja onDestroy odpowiada za opuszczenie funkcji gtk_main() po to, aby program zakończył działanie po zniszczeniu okna głównego aplikacji. Natomiast funkcja onDeleteEvent wyświetla okno dialogowe z zapytaniem "Czy na pewno chcesz opuścić program?". Jeśli użytkownik kliknie przycisk TAK - aplikacja zostanie zamknięta. W przeciwnym razie będzie kontynuowała działanie.
Okienko dialogowe tworzymy przy pomocy funkcji gtk_message_dialog_new i przypisujemy do zmiennej dialog. Funkcja ta przyjmuje następujące parametry:
- Wskaźnik na okno rodzica (typu GtkWindow). Tutaj obiekt widget został zrzutowany na obiekt okna przy pomocy makra GTK_WINDOW.
- Flagi dla tworzonego okna dialogowego. Tutaj przekazaliśmy flagę: GTK_DIALOG_DESTROY_WITH_PARENT oznaczającą, że utworzony dialog zostanie zniszczony wraz ze zniszczeniem okna rodzica. Nie oznacza to jednak, że nie możemy zniszczyć dialogu wywołując w prost funkcję gtk_widget_destroy.
- Typ okna dialogowego - tutaj GTK_MESSAGE_QUESTION. Oznacza to, że okno dialogowe będzie mieć ikonkę pytajnika. Inne możliwe typy to: GTK_MESSAGE_INFO, GTK_MESSAGE_WARNING, GTK_MESSAGE_ERROR, GTK_MESSAGE_OTHER. W przypadku ostatniego z tych typów żadna ikonka nie zostanie wyświetlona.
- Typy przycisków, które pojawią się w okienku - tutaj GTK_BUTTONS_YES_NO wyświetlające przyciski TAK i NIE. Inne możliwe typy to: GTK_BUTTONS_OK, GTK_BUTTONS_CLOSE, GTK_BUTTONS_CANCEL, GTK_BUTTONS_OK_CANCEL, GTK_BUTTONS_NONE. W przypadku ostatniego z tych typów żadne przyciski nie pojawią się w okienku dialogowym.
- Jako ostatni parametr przekazywany jest tekst komunikatu. Może to być tekst zawierający formanty takie jak w funkcji printf. Wtedy wszystkie dodatkowe zmienne przekazujemy po tekście komunikatu.
Następnie utworzonemu widgetowi okna dialogowego nadajemy tytuł przy pomocy funkcji gtk_window_set_title. Teraz jesteśmy gotowi na wyświetlenie okna dialogowego. Robimy to wywołując funkcję gtk_dialog_run i przekazując jej nasz widget. Funkcja ta przetwarza w pętli komunikaty okna dialogowego aż do naciśnięcia któregokolwiek z przycisków. Wtedy kończy działanie i zwraca w postaci liczby całkowitej gint typ przycisku, który został kliknięty. Rezultat rzutujemy do typu GtkResponseType i zapamiętujemy w zmiennej result. Teraz możemy już zniszczyć okno dialogowe przy pomocy funkcji gtk_widget_destroy. Następnie testujemy zawartość zmiennej result i jeśli jest równa GTK_RESPONSE_YES, to zwracamy wartość FALSE pozwalając zamknąć okno główne. W przeciwnym razie przerywamy operację zamknięcia zwracając TRUE.