PROGRAMOWANIE OBIEKTOWE W C++
LABORATORIUM 7
BIBLIOTEKA GTK+/GTKMM
GTK+ jest darmową (GNU LGPL), międzyplatformową biblioteką służącą do tworzenia GUI (Graphical User Interface). Pierwotnie została napisana w języku C, lecz obecnie istnieją wersje przeznaczone dla innych języków (np. Python, Perl). Zastosowano ją w wielu aplikacjach, np.: GIMP, gnome (domyślne środowisko graficzne wielu dystrybucji linuxa), Inkscape, Chromium.
Międzyplatformowość biblioteki oznacza, że przygotowana aplikacja będzie działała niezależnie od systemu operacyjnego, pod którym program jest kompilowany. Jest to istotna zaleta względem na przykład WinAPI, działającego wyłącznie pod Windowsem. Istnieją również inne biblioteki pełniące te same funkcje co GTK+, np. Qt, czy wxWidgets i trudno jednoznacznie wskazać najlepszą spośród wymienionych.
W trakcie zajęć wykorzystano bibliotekę gtkmm, która stanowi „opakowanie” GTK+ do postaci obiektowej w języku C++. Interfejs użytkownika (GUI) będzie tworzony w trakcie zajęć przez wpisywanie komendy „z palca”, jednak wygodniejszą formą jest korzystanie z kreatora – Glade.
Poniższa instrukcja oparta jest w znacznej części na podręczniku Cumming M.i in. Programming with gtkmm 2. dostępnego na stronie http://developer.gnome.org/gtkmm-tutorial/2.24.
1. Stwórz pierwszy program tworzący puste okienko. Kod znajduje się poniżej:
#include <gtkmm.h>
//dołączenie plików nagłówkowych gtkmmm
int main(int argc, char* argv[])
{
Gtk::Main kit(argc, argv); //inicjalizacja biblioteki
Gtk::Window window;
//stworzenie obiektu window klasy Gtk::Window
Gtk::Main::run(window);
//wyświetlenie obiektu window
return 0;
}
Powyższy przykład powinien wygenerować puste okno o wymiarach 200x200px. W pierwszej linii zawarto instrukcje służące inicjalizacji biblioteki. Dalej, tworzony jest obiekt klasy Gtk::Window, która jest podstawową jednostką odpowiedzialną za okno. Instrukcja Gtk::Main::run(window) wyświetla obiekt window i uruchamia właściwe działanie „okienek”. Proces ten kończy działanie w momencie zamknięcia okna window.
2. Utwórz pustą klasę Okno, która dziedziczy po klasie Gtk::Window. Tworzona klasa będzie przechowywać główne okno programu.
W celu nadania nazwy (napis na górnym pasku) oknu programu należy wywołać metodę set_title(„napis”) na danym obiekcie.
3. Dodaj do istniejącego okna przycisk. Przycisk ma być składową klasy Okno i powinien zawierać napis
„Hello world!”. Sprawdź jak wyglądają poszczególne typy przycisków w bibliotece GTK+.
Biblioteka GTK+ zawiera różne rodzaje przycisków:
Gtk::Button
Gtk::ToggleButton
Gtk::CheckButton
Gtk::RadioButton
Podstawowy klawisz z
Przełącznik
Gtk::ToggleButton o
Klawisz występujący w
tekstem lub ikoną
dwupozycyjny (on/off)
innym wyglądzie
grupach; stosowany gdy
(naciśnij-puść)
możliwe jest wybranie
tylko jednej opcji z kilku
podanych
Ustawienie tekstu wyświetlanego przez klawiszu można wykonać wołając konstruktor parametryczny Gtk::Button(„napis”) lub metodę set_label(„napis”);
Stworzony obiekt należy dodać do okna ( Gtk::Window::add( Gtk::Button mbtn) ) i następnie wyświetlić w tym oknie Gtk::Button::show(). Zamiast ręcznie ustawiać wyświetlanie każdego obiektu wygodniej jest wyświetlić wszystkie za pomocą metody Gtk::Window::show_all_children().
4. Dodaj w klasie Okno metodę (slot), która w przypadku naciśnięcia na klawisz wypisze w konsoli komunikat „Nacisnieto klawisz”.
Biblioteka GTK+ oparta jest na zdarzeniach (event driven). Oznacza to, że program oczekuje na jakieś wydarzenie, np. naciśnięcie klawisza, zmianę stanu, i wówczas podejmuje określone działanie. Mówi się, że sygnał jest wysyłany (emitowany) do odbiornika (slotu). Klasa Gtk::Button posiada zaimplementowanych kilka sygnałów dostępnych przez akcesory (m.in.: signal_clicked()reagujący na kliknięcie w dany klawisz).
Slotem jest zwyczajna funkcja lub metoda, która jest wykonywana, jeżeli określony sygnał zostanie wyemitowany. Przed rozpoczęciem pracy z GUI należy połączyć ze sobą sygnał i slot, służy do tego metoda connect() klasy reprezentującej sygnał. Argumentem metody connect() jest adres funkcji lub metody, która ma zostać wywołana, jednak „po drodze” konieczne jest wywołanie funkcji sigc::mem_fun (dla slotu –
metody) lub sigc::fun_ptr (dla slotu – funkcji). Przykład:
void mojafunkcja(); //funkcja
class Klasa
{
...
void metoda(); // metoda klasy
...
}
int main()
{
Gtk::Button btn(“Napis”);
btn.signal_clicked().connect( sigc::fun_ptr( &myfunction ) ); Klasa obj;
btn.signal_clicked().connect( sigc::mem_fun(obj, &Klasa::metoda );
}
W przypadku, gdy slotem ma być metoda klasy, pierwszym argumentem jest obiekt, na którym ma zostać wykonana dana metoda (tutaj obj), natomiast drugim – adres tej metody (&Klasa::metoda).
5. W głównym oknie programu stwórz i wyświetl drugi przycisk.
Biblioteka GTK+ przechowuje elementy w kontenerach: jedno- lub wieloelementowych. Przykładem kontenera zawierającego tylko jeden widget (element) jest Gtk::Button, Gtk::Window,Gtk::Frame. Istnieje również wiele kontenerów przechowujących więcej niż jeden widget, kilka najważniejszych to: Gtk::HBox, Gtk::VBox
Układ liniowy elementów, odpowiednio poziomo i pionowo
Gtk::Table
Tworzy macierz elementów
Gtk::Notebook
Kontener tworzący zakładki/karty
Aby dodać elementy do kontenera Gtk::HBox i Gtk::Vbox należy wywołać metodę pack_start(button) lub pack_end(button). Sprawdź czym się różnią te metody.
Należy pamiętać o dodaniu przynależności widżetu Gtk::Hbox/Gtk::Vbox do okna, w którym ma być wyświetlony – metoda Gtk::Window::add( .. ).
6. Wyświetl w oknie trzeci klawisz w sposób jak na rysunku obok wykorzystując kontener Gtk::Table.
W celu dodania elementu do kontenera Gtk::Table wykorzystuje się metodę składową Gtk::Table::attach(). Szczegóły dotyczące składni znajdują się w dokumentacji biblioteki oraz podręczniku użytkownika Programming with gtkmm 2 (rozdział 7.2.6. Table)
7. Stwórz klasę Przycisk dziedziczącą po klasie Gtk::Button, która ma dodatkowy atrybut mid, przechowujący cyfrę, którą reprezentuje dany klawisz.
8. Stwórz i wyświetl macierz 4x3 z układem przycisków jak na klawiaturze alfanumerycznej z wykorzystaniem klasy Przycisk. Dodaj obsługę sygnałów tak, aby po naciśnięciu klawisza w konsoli wyświetlała się cyfra, którą przedstawia dany klawisz.
Biblioteka sigc++ wykorzystana wewnątrz GTK+ ma możliwość tworzenia sygnałów wysyłających różne zmienne/obiekty. Przygotowane wcześniej połączenie sygnału nie przewidywało przekazywania argumentów do slotu. Aby umożliwić wysyłanie sygnału z argumentami, konieczne jest wykorzystanie funkcji sigc::bind.
W przypadku wysyłania zmiennej całkowitej val po naciśnięciu klawisza mbtn postać jest następująca: int main()
{
...
Klasa::metoda(int i);
Gtk::Button mbtn;
mbtn.signal_clicked().connect(sigc::bind<int>(sigc::mem_fun(obj,&Klasa::metoda),val)
...
}
9. W istniejącym oknie utwórz obiekt Gtk::Entry, który po naciśnięciu klawisza wyświetli jego cyfrę.
Widget Gtk::Entry służy do wprowadzania tekstu, jednak może być wykorzystany również jako obiekt tylko do odczytu, na którym wyświetlany będzie napis. Podstawową rolę odgrywają tutaj dwie metody Gtk::Entry::set_text() oraz Gtk::Entry::get_text(), służące odpowiednio do wyświetlenia podanego komunikatu oraz pobrania wyświetlanego napisu. W celu ustawienia widgetu tylko do odczytu służy metoda Gtk::Entry::set_editable(true/false).
10. Stwórz własny kalkulator
Specyfikacja:
- Kalkulator działa w sposób przyrostowy, tzn. wartość w lewej komórce jest dodawana, odejmowana, mnożona lub dzielona przez liczbę po prawej stronie. Wynik działania jest wyświetlany w lewej komórce, natomiast pozostałe są czyszczone.
- Wyodrębnić klasę odpowiadającą za obliczenia i wykorzystać mechanizm sygnałów w celu sterowania tą klasą.