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
tekstem lub ikoną
(naciśnij-puść)
Przełącznik
dwupozycyjny (on/off)
Gtk::ToggleButton
o
innym wyglądzie
Klawisz występujący w
grupach; stosowany gdy
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ą.