GTK+/Szkielet programu GTK+ w języku C++
Z Wikibooks, biblioteki wolnych podręczników.
Dzięki cudownym właściwościom języka C++ (wsteczna kompatybilność z językiem C) możemy beż problemy używać bibliotek GTK+ pisząc aplikacje w C++. Utworzymy trzy pliki z kodem, a naszą klasę nazwiemy MyGUI. Pierwszy to deklaracja klasy MyGUI.hpp, następnie MyGUI.cpp gdzie znajduje się definicja metod klasy (część z nich jest funkcjami zwrotnymi dla kontrolek GTK+). Główny plik będzie zawierał tylko obsługę naszej klasy MyGUI.
Plik MyGUI.hpp
#include <gtk/gtk.h> #include <iostream> #include <string> using namespace std; class MyGUI { private: GtkWidget *window; GtkWidget *button; string programtitle; static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data); static void destroy(GtkWidget *widget, gpointer data); static void buttonclicked(GtkWidget *widget, gpointer data); public: MyGUI(); ~MyGUI(); void init(int, char**); void build(); void run(); };
Klasa przechowuje wskaźniki do tworzonych kontrolek oraz funkcje zwrotne (zwróć uwagę na to, iż muszą być zadeklarowane jako statyczne - ponieważ GTK+ musi mieć do nich dostęp) w sekcji private. Znajduje się tu też zmienna klasy string. Natomiast w sekcji public posiadamy standardowo konstruktor oraz destruktor oraz trzy funkcje. Funkcje te realizują odpowiednio następujące zadania; zainicjowanie maszyny GTK+, tworzenie okna i kontrolek wraz z podpinaniem do nich funkcji zwrotnych, tworzenie widocznym stworzonych kontrolek oraz uruchamianie samej maszyny GTK+. Podział tych zadań wynika wyłącznie z koncepcji, nic nie stoi na przeszkodzie aby cały ten kod umieścić w jednej funkcji.
Plik MyGUI.cpp
#include "MyGUI.hpp" MyGUI::MyGUI() { cout << "Konstruktor" << endl; } MyGUI::~MyGUI() { cout << "Destruktor" << endl; } void MyGUI::init(int argc, char** argv) { gtk_init(&argc, &argv); } void MyGUI::build() { window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),this); g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),this); gtk_window_set_title(GTK_WINDOW(window),"MyGUI"); gtk_widget_set_size_request(window,170,50); gtk_container_set_border_width(GTK_CONTAINER(window),10); button = gtk_button_new_with_label("PressMy"); g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(buttonclicked),this); gtk_container_add(GTK_CONTAINER(window),button); } void MyGUI::run() { gtk_widget_show_all(window); gtk_main(); } gboolean MyGUI::delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { return FALSE; } void MyGUI::destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); } void MyGUI::buttonclicked(GtkWidget *widget, gpointer data) { MyGUI *mygui = static_cast<MyGUI*>(data); cout << gtk_button_get_label(GTK_BUTTON(mygui->button)) << endl; mygui->programtitle = gtk_window_get_title(GTK_WINDOW(mygui->window)); cout << "Nazwa twojego programu to: " << mygui->programtitle << endl; }
W tym pliku najbardziej interesującą rzeczą jest sposób przekazywania danych z klasy do funkcji zwrotnych. Zwróć uwagę na łączenie sygnałów. Do dodatkowych danych funkcji zwrotnej - gpointer user_data - jest przekazywany wskaźnik this. Natomiast w funkcji zwrotnej buttonclicked() widać jak go rzutujemy na oryginalny typ MyGUI aby mieć dostęp do danych zawartych w naszej klasie, przycisku oraz zmiennej klasy string.
Plik main.cpp
#include "MyGUI.cpp" int main(int argc, char *argv[]) { MyGUI *gui = new MyGUI; gui->init(argc,argv); gui->build(); gui->run(); delete gui; return 0; }
Ostatecznie tworzymy nowy obiekt naszej klasy i wywołujemy w odpowiedniej kolejności funkcje tworzące interfejs.
Na koniec przyda nam się plik Makefile:
CC = g++ CFLAGS = -Wall \ -DG_DISABLE_DEPRECATED \ -DGDK_DISABLE_DEPRECATED \ -DGDK_PIXBUF_DISABLE_DEPRECATED \ -DGTK_DISABLE_DEPRECATED kalkulator: main.cpp $(CC) main.cpp -o mygui $(CFLAGS) `pkg-config gtk+-2.0 --cflags --libs` clean: rm -f *.o mygui
Teraz aby skompilować nasz program wystarczy wpisać:
$ make
ponowna kompilacja to:
$ make clean
$ make
Oczywiście jeżeli używa się systemu Linux.