Programowanie GTK

neuromancer

Programowanie GTK
by
NEURO

Luźne tłumaczenie artykułów Özcana
Güngöra</i>

Co to jest GTK?

Ogólnie rzecz biorąc GTK jest to biblioteka do tworzenia graficznego interfejsu użytkownika (GUI). Biblioteka jest rozpowszechniania na licencji GPL/LGPL. Używając tej biblioteki można tworzyć programy darmowe, komercyjne, open-source, czy jakie tam kto sobie wymyśli ;).

Nazwa biblioteki pochodzi GIMP toolkit, bo początkowo została stworzona dla GIMP'a (na marginesie: co nie najlepiej o niej świadczy). Jej utorami są: Peter Mattis Spencer Kimball Josh MacDonald. GTK ma obiektowo zorientowany interfejs.

Biblioteki można używać na Windows (np. wersje GIMP pod ten system), ale raczej jej niszą jest Linux (chociażby GNOME który jej używa) i pod niego też będziemy programować.

Kompilacja

Wymagany gcc. Po zapisaniu pliku źródłowego z rozszerzeniem .c należy uruchomić terminal (komenda xterm) i przejść do katalogu z plikiem (komenda cd <katalog>, np. cd /root/projekt). Następnie wpisać

gcc -o hello hello.c `gtk-config --cflags --libs`

gdzie zamiast hello podajemy nazwę pliku wyjściowego (wykonywalnego), a zamiast hello.c nazwę naszego pliku źródłowego. UWAGA: symbol ` uzyskujemy naciskając klawisz na lewo od jedynki (tylda - ~) a nie cudzysłów.

Biblioteki GTK można znaleźć pod ftp://ftp.gtk.org/
Do kompilacji wymagane są oczywiście zainstalowane biblioteki GTK i znajomość ich położenia. Aby się dowiedzieć tego można wpisać:

gtk-config --cflags --libs

Powinno dać coś takiego (w zależnosci od systemu):

-I/opt/gnome/include/gtk-1.2 -I/opt/gnome/include/glib-1.2 -I/opt/gnome/lib/glib
/include -I/usr/X11R6/include -L/opt/gnome/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic
-lgmodule -lglib -ldl -l Xext -lX11 -lm

gdzie:

-l library: Searches for a library in the form like liblibrary.a in defined paths.
-L path: Adds a path to search libraries.
-I path: Adds a path to search header file used in program.

Początek

Dobra zaczynamy. Pierwszy okienkowy program. Tworzy puste okno o rozmiarach 200x200.

//--------------CUT HERE-----------------
#include &lt;gtk/gtk.h&gt;  //Dołączamy nagłówki

int main(int argc, char *argv[])
{
  GtkWidget *window;   //Klasa okienka

  gtk_init(&amp;argc, &amp;argv);  //Obsługa parametrów programu

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);  //Tworzymy nowe okno
  gtk_widget_show(window);                        //Pokazujemy okno

  gtk_main ();                                    //Główna pętla programu

  return 0 ;
}
//--------------CUT HERE-----------------

GtkWidget to klasa do tworzenia okienek, przycisków, pól edycyjnych, napisów itd.

void gtk_init(int *argc,char ***argv)

Inicjuje bibliotekę i pobiera parametry wpisane w wierszu poleceń. Funkcja musi być użyta po deklaracji komponentów.

GtkWidget *gtk_window_new(GtkWindowType windowtype)

Tworzy nowe okno. Parametrem (zmienia styl okna) może być:

  • GTK_WINDOW_TOPLEVEL
  • GTK_WINDOW_DIALOG
  • GTK_WINDOW_POPUP
void gtk_widget_show(GtkWidget *widget)

Funkcja pokazuje okno.

void gtk_main(void)

Obsługuje główną pętle programu. Musi być użyta na końcu programów pod GTK.

Ustawienia okna

Tytuł okna

void gtk_window_set_title(GtkWindow *window,const gchar *title)

Funkcja zmienia tytuł okna. Pierwszy parametr to okno GTK. UWAGA: zmienna window jest typu GtkWidget i aby ją przekonwertować na ten typ należy użyć makra GTK_WINDOW(GtkWidget *widget) który zwraca typ GtkWindow, przy parametrze typu GtkWidget.

Dobra dalej. Drugi parametr jest typu gchar, który jest zdefiniowany w bibliotece glib i jest takiego samego typu jak char. Jest to wskaźnik czyli można ustawić parametr typu char *, lub tablicę char[].

Rozmiar okna

void gtk_window_set_default_size(GtkWindow *window, gint width, gint height)

Zmienia rozmiar okna. Pierwszy parametr to GtkWindow (czytaj wyżej). Kolejne dwa to wartości szerości i wysokości okna, które są typu gint, równoznacznego zwykłemu int.

Położenie okna

void gtk_window_set_position(GtkWindow *window, GtkWindowPosition position)

Zmienia położenia okna. Pierwszy parametr to klasa okna (czytaj wyżej), którego położenie ustalamy, kolejny to window.position który może być:

  • GTK_WIN_POS_NONE - nic konkretnego
  • GTK_WIN_POS_CENTER - centrum ekranu
  • GTK_WIN_POS_MOUSE - pozycja myszki
  • GTK_WIN_POS_CENTER_ALWAYS - zawsze na środku

Uzupełnienie

gtk_widget_set_uposition(window, sx, sy);

Położenie okna można modyfikować także tą funkcją. Pierwszy parametr to klasa okna, kolejne dwa to położenie okna w pikselach, od lewego górnego rogu ekranu.

Przykładowy kod:

//--------------CUT HERE-----------------

#include &lt;gtk/gtk.h&gt;  //Nagłówki GTK

int main(int argc,char *argv[])
{
  GtkWidget *window;    //Komponent: okno

  gtk_init(&amp;argc, &amp;argv);                                  //Obsługa parametrów
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);                    //Stworzenie okna
  gtk_window_set_title(GTK_WINDOW(window), &quot;Program&quot;);   //Zmiana tytułu okna
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); //Położenie
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 300);       //Rozmiar
  gtk_widget_show(window);                                         //Pokazanie okna

  gtk_main();                                                      //Główna procedura programu

  return 0;
}
//--------------CUT HERE-----------------

Sygnały i zdarzenia

Graficzny interfejs użytkownika (GUI) służy do komunikacji z użytkownikiem programu, więc musi odpowiednio reagować na to co
on robi (zdarzenia). Może to zrobić dzięki sygnałom na które adekwatnie reaguje.

W GTK służy do tego funkcja:

guint gtk_signal_connect_object(GtkObject *object, const gchar *name,
  GtkSignalFunc func, GtkObject *slot_object);

Pierwszy parametr to komponent który emituje sygnał. Na przykład jeśli zostanie wciśnięty przycisk, to object będzie wskazywał na ten przycisk. Parametr name oznacza zdarzenie (jako wskaźnik do ciągu znaków). Zdarzeniami mogą być:

  • event - wydarzenie
  • button_press_event - wciśnięcie przycisku
  • button_release_event - zwolnienie przycisku
  • motion_notify_event - zawiadomienie o ruchu
  • delete_event - usunięcie
  • destroy_event - zniszczenie
  • expose_event - wystawienie (wyświetlenie)
  • key_press_event - wciśnięcie klawisza
  • key_release_event - puszczenie klawisza
  • enter_notify_event - wejście kursora myszki na obszar elementu
  • leave_notify_event - opuszczenie obszaru elementu przez kursor myszki
  • configure_event - zdarzenie konfiguracji
  • focus_in_event - aktywowanie okno
  • focus_out_event - deaktywowanie okna
  • map_event - planowanie
  • unmap_event
  • property_notify_event
  • selection_clear_event - wyczyszczenie zaznaczenia
  • selection_request_event - pytanie o zaznaczenie
  • selection_notify_event
  • proximity_in_event - w pobliżu
  • proximity_out_event
  • drag_begin_event - początek przeciągania
  • drag_request_event
  • drag_end_event
  • drop_enter_event - przeciągnięcie czegoś na kontrolkę
  • drop_leave_event
  • drop_data_available_event
  • other_event - inne zdarzenie

Trzeci parametr - func jest nazwą funkcji, która zostanie wywołana po zdarzeniu. Przykładowy kod:

//--------------CUT HERE-----------------

#include &lt;gtk/gtk.h&gt; //Nagłówki

void close(GtkWidget *widget, gpointer *data) //Funkcja
{
  gtk_main_quit(); //Zamknij program GTK
}

int main(int argc,char *argv[])
{
  GtkWidget *window; //Klasa okna

  gtk_init(&amp;argc, &amp;argv); //Parametry

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //Utworzenie okna
  gtk_signal_connect(GTK_OBJECT(window), &quot;destroy&quot;,
    GTK_SIGNAL_FUNC(close), NULL); //Skojarzenie sygnału
  gtk_widget_show(window); //Pokazanie

  gtk_main(); //Główna funckja programu GTK

  return 0;
}
//--------------CUT HERE-----------------

Funkcja:

gtk_signal_connect(GTK_OBJECT(window), &quot;destroy&quot;,
  GTK_SIGNAL_FUNC(close), NULL)

Nasłuchuje na sygnał "destroy" (zniszczenia - usunięcia okna). Kiedy okno jest zamykane to zostaje wywołana funkcja close, która wywołuje gtk_main_quit() i program kończy działanie.

Przycisk

Zwykłe przyciski służą do wykonania jakichś operacji po ich wciśnięciu. W GTK są dwie drogi stworzenia przycisków:

GtkWidget* gtk_button_new (void);
GtkWidget* gtk_button_new_with_label (const gchar *label);

Pierwsza funkcja tworzy przycisk bez napisu (label), drugi z napisem gdzie za parametr podajemy właśnie napis (wskaźnik do ciągu znaków).

Kolejną ważną funkcją jest:

void gtk_container_add(GtkContainer *container, GtkWidget *widget)

Używając tej funkcji, można stworzyć (ogólnie każdy komponent) w oknie (ogólnie w kontenerze (ang. container)). W przykładzie
, kontenerem jest okno, a komponentem dodawanym jest przycisk.Najważniejszą rzeczą jeśli idzie o przycisk jest to czy jest on wciśnięty, czy nie. Znowu użyjemy funkcji gtk_signal_connect do tego celu.

//--------------CUT HERE-----------------

#include &lt;gtk/gtk.h&gt; //Nagłówki GTK

void close(GtkWidget *widget, gpointer *data) //Zamknięcie okna
{
  gtk_main_quit(); //Zamknij okno
}

void clicked(GtkWidget *widget,gpointer *data) //Funkcja wywołana po kliknięciu okna
{
  g_print(&quot;Button Clicked\\n&quot;);  //Wyświetlenie napisu
}

int main(int argc,char *argv[])  //Główna funkcja programu
{
  GtkWidget *window, *button;   //Deklaracje komponentów

  gtk_init(&amp;argc, &amp;argv); //Obsługa parametrów

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //Utowrzenie okna
  gtk_signal_connect(GTK_OBJECT(window), &quot;destroy&quot;,
    GTK_SIGNAL_FUNC(close), NULL); //Skojarzenie sygnału zniszenia okna z funkcją close

  button=gtk_button_new_with_label(&quot;Button&quot;); //Stworzenie przycisku z napisem
  gtk_container_add(GTK_CONTAINER(window),button);      //Dodanie przycisku do okna
  gtk_signal_connect(GTK_OBJECT(button),&quot;clicked&quot;,
    GTK_SIGNAL_FUNC(clicked),NULL); //Skojarzenie zdarzenia kliknięcia przycisku z funkcją clicked
  gtk_widget_show(button); //Pokazanie przycisku

  gtk_widget_show(window); //Pokazanie okna

  gtk_main();  //Główna pętla programu GTK

  return 0;
}
//--------------CUT HERE-----------------

Pakowanie komponentów używając pudełek (box)

Pakowanie oznacza ustawianie komponentów w kolejności w oknie. Jedną z możliwości w GTK są pudełka (boxy). Główna idea z pudełkami to pakowanie komponentów kolejno poziomo lub pionowo. Są więc dwa typy pudełek: poziome i pionowe.

Poziome pudełka

W tym typie pudełka, komponenty są pakowane (układane) poziomo. Aby utworzyć pudełko należy wpisać:

gtk_widget *box; //Deklaracja komponentu
box=gtk_hbox_new(gboolean homogenous, gint spacing); //Utworzenie pudełka

Pierwszy parametr przyjmuje wartości prawda (TRUE) i fałsz (FALSE). Jeżeli wartość parametru podamy TRUE, to komponent wypełni całą przestrzeń pudełka. Drugi parametr typu int(wartość liczbowa) to odległość między komponentami.

Pionowe pudełka

W tym typie komponenty są układane pionowo Do utworzenia używamy:

gtk_widget *box;
box=gtk_vbox_new(gboolean homogenous, gint spacing);

Parametry są analogiczne jak powyżej.

Obsługa pudełek

Aby dodać komponent do pudełka, można użyć jednej z dwóch możliwości. Pierwszą jest:

gtk_box_pack_start(GtkBox *box, GtkWidget *child, gboolean expand,
  gboolean fill, guint padding);

Dzięki tej funkcji możemy dodać kolejne (w poziomych od lewej strony, w pionowych od góry) komponenty do pudełka. Pierwszy parametr to pudełko do którego chcemy dodać. Drugi to komponent, który dodajemy. Kolejne dwa służą do opisania zachowania się komponentu w pudełku, ostatni opisuje odległość od innych komponentów.

Parzystą funkcją do powyższej jest

gtk_box_pack_end(GtkBox *box,GtkWidget *child, gboolean expand,
  gboolean fill, guint padding);

Służy do dodania komponentu na końcu pudełka (prawa lub dolna strona). Parametry są analogiczne jak w powyższej.

Do dodania pudełka do okna służy funkcja:

gtk_container_add (GtkContainer *container,GtkWidget *component);

gdzie pierwszym parametrem jest okno do którego będziemy dodawać (kontener), a drugą pudełko. Przykład:

gtk_container_add(GTK_CONTAINER(window), box);

Kolejna funkcja:

gtk_box_set_homogeneous (GtkBox *box, gboolean homogenous);

zmienia jednorodność ułożenia w pudełku.

Funkcja:

gtk_box_set_spacing(GtkBox *box, gint spacing);

zmienia odległości między komponentami w pudełku.
Pierwszy parametr to wskaźnik do pudełka, drugi to liczba, opisująca odległości.

Do zmiany ustawień już zapakowanych komponentów służy funkcja:

gtk_box_set_child_packing(GkBox *box,GtkWidget *shild, gboolean expand,
  gboolean fill, guint padding, GtkPackType packingtype);

Parametry mają identyczne znaczenie jak w funkcji gtk_box_pack_start. Ostatni parametr ustala styl pakowania. Przyjmuje
wartość GTK_PACK_START lub GTK_PACK_END, co pakuje komponenty na początku, lub na końcu pudełka.

Przykładowy kod:

//--------------CUT HERE-----------------
#include &lt;gtk/gtk.h&gt;     //Nagłówki GTK
#include&lt;string.h&gt;       //Obsługa łańcuchów znakowych
#include&lt;stdlib.h&gt;       //Obsługa stardowych funkcji systemu

void destroy(GtkWidget *widget, gpointer data) { //Usunięcie programu
  gtk_main_quit();
}

GtkWidget *window, *text[10], *box, *button[10],
  *box1, *box2, *box3, *box4, *sep; //Deklaracje komponentów

int t, padding=0, space=0;  //Zmienne z opisami odległości
char name[15], no, isim[10][15] = {
   &quot;Expand FALSE&quot;,&quot;FillFALSE&quot;,
   &quot;Padding 10&quot;,&quot;Homojen FALSE&quot;,&quot;Spacing 0&quot;,&quot;Expand TRUE&quot;,
   &quot;Fill TRUE&quot;,&quot;Padding 0&quot;,&quot;Homojen TRUE&quot;,&quot;Spacing 10&quot;
 },
labelisim[6][15]={
  &quot;expand = &quot;,&quot;fill = &quot;,&quot;padding = &quot;,&quot;homojen = &quot;,
  &quot;spacing = &quot;
};

gboolean expand=0, fill=0, homogen=0; //Ustawienia stylu pakowania komponentów

void click(GtkWidget *widget, GdkEventButton *data, gpointer *po){
  //Definicja funkcji wywołanej po kliknięciu przycisku
  //Która po kolejnym kliknięciu przycisku modyfikuje parametry pakowania

  if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button5&quot;))
    expand = 1;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button0&quot;))
    expand=0;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button6&quot;))
    fill=1;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button1&quot;))
    fill=0;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button7&quot;))
    padding=0;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button2&quot;))
    padding=10;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button8&quot;))
    homogen=1;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button3&quot;))
    homogen=0;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button9&quot;))
    space=10;
  else if(!strcmp(gtk_widget_get_name(GTK_WIDGET(po)),&quot;button4&quot;))
    space=0;
  else g_print(&quot;ALOO&quot;);

  gtk_box_set_homogeneous(GTK_BOX(box3), homogen);
  gtk_box_set_spacing(GTK_BOX(box3),space);
  gtk_box_set_homogeneous(GTK_BOX(box4),homogen);
  gtk_box_set_spacing(GTK_BOX(box4),space);

  for(t=4;t&lt;5;t++) {
    gtk_box_set_child_packing (GTK_BOX(box3),text[t],expand,fill,padding,GTK_PACK_START);
    gtk_box_set_child_packing (GTK_BOX(box4),button[t],expand,fill,padding,GTK_PACK_START);
  }

  strcpy(name, labelisim[4]);

  if(space==0)
    strcat(name,&quot;0&quot;);
  else
    strcat(name,&quot;10&quot;);

  gtk_label_set_text(GTK_LABEL(text[4]),name);

  strcpy(name,labelisim[0]);
  t=strlen(name);
  name[t]=expand+48;
  name[t+1]=0;
  gtk_label_set_text(GTK_LABEL(text[0]),name);

  strcpy(name,labelisim[1]);
  t=strlen(name);
  name[t]=fill+48;
  name[t+1]=0;
  gtk_label_set_text(GTK_LABEL(text[1]),name);

  strcpy(name,labelisim[2]);

  if(padding==0)
    strcat(name,&quot;0&quot;);
  else
    strcat(name,&quot;10&quot;);

  gtk_label_set_text(GTK_LABEL(text[2]),name);

  strcpy(name,labelisim[3]);
  t=strlen(name);
  name[t]=homogen+48;
  name[t+1]=0;
  gtk_label_set_text(GTK_LABEL(text[3]),name);
}

int main(int argc, char *argv[])
{
  gtk_init (&amp;argc, &amp;argv); //Inicjalizacja
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //Utworzenie okna
  gtk_window_set_title((GtkWindow *)window,&quot;Program&quot;); //Zmiana tytułu okna
  gtk_widget_set_usize(window,700,200); //Zmiana rozmiaru
  gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); //Zmiana położenia
  gtk_signal_connect_object(GTK_OBJECT(window),&quot;destroy&quot;,
    GTK_SIGNAL_FUNC(destroy),NULL); //Skojarzenie sygnału zamknięcia okna z funkcją destroy
  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
    //Zmiana obramowania kontenera (tutaj okna)

  //Utworzenie kolejnych pudełek
  box1=gtk_hbox_new(TRUE,0);
  box=gtk_hbox_new(TRUE,0);
  box2=gtk_vbox_new(FALSE,0);
  box3=gtk_hbox_new(homogen,space);
  box4=gtk_hbox_new(homogen,space);

  //Stworzenie separatora
  sep=gtk_hseparator_new();

  for(t=0;t&lt;5;t++) {
    strcpy(name,&quot;label&quot;);
    name[6]=t+48;
    name[7]='\\0';
    text[t]=gtk_label_new(labelisim[t]); //Utworzenie kolejnych napisów (etykiet)
    gtk_label_set_justify(GTK_LABEL(text[t]),GTK_JUSTIFY_FILL);
       //Zmiana wyrównania etykiet
    gtk_box_pack_start(GTK_BOX(box3),text[t],expand,fill,space);
       //Pakowanie etykiet do pudełka
    gtk_widget_show(text[t]); //Pokazanie napisu
  }

  gtk_box_pack_start(GTK_BOX(box2),box3,FALSE,FALSE,0); //Dopakowanie pudełka pudełkiem
  gtk_widget_show(box3); //Pokazanie pudełka

  for(t=0;t&lt;10;t++) {
    strcpy(name,&quot;button&quot;);
    name[6]=t+48;
    name[7]='\\0';
    button[t]=gtk_button_new_with_label(isim[t]);
    gtk_widget_set_name(GTK_WIDGET(button[t]),name);
    gtk_widget_set_usize(button[t],100,20);
    gtk_signal_connect_object(GTK_OBJECT(button[t]),&quot;button_release_event&quot;,
      GTK_SIGNAL_FUNC(click),(gpointer)box3);

    if(t&gt;4)
      gtk_box_pack_start(GTK_BOX(box1),button[t],FALSE,FALSE,0);
    else
      gtk_box_pack_start(GTK_BOX(box),button[t],FALSE,FALSE,0);

    gtk_widget_show(button[t]);
  }

  for (t=0;t&lt;5;t++) { //Utworzenie, zapakowanie I pokazanie kolejnych napisów
    button[t]=gtk_button_new_with_label(&quot;button&quot;);
    gtk_box_pack_start(GTK_BOX(box4),button[t],expand,fill,space);
    gtk_widget_show(button[t]);
  }

  //Wpakowanie i pokazanie kolejnych pudełek
  gtk_box_pack_start (GTK_BOX (box2), box4,FALSE,FALSE,0);
  gtk_widget_show(box4);
  gtk_box_pack_start(GTK_BOX(box2), sep,FALSE,FALSE,10);
  gtk_widget_show(sep);
  gtk_box_pack_start (GTK_BOX (box2), box1,FALSE,FALSE,0);
  gtk_widget_show(box1);
  gtk_box_pack_start (GTK_BOX (box2), box,FALSE,FALSE,0);
  gtk_widget_show(box);
  gtk_container_add (GTK_CONTAINER (window), box2);
  gtk_widget_show(box2);
  gtk_widget_show (window); //Pokazanie okna
  gtk_main (); //Główna funkcja GTK

  return 0;
}
//--------------CUT HERE-----------------

Tabele

Tabele tak jak w HTML służy do pakowania komponentów do komórek. Dzięki temu, wystarczy utworzyć tabelę z wierszami i kolumnami. Potem możemy układać komponenty w komórki, albo grupy komórek. Do utworzenia tabeli używamy:

GtkWidget *table; //Deklaracja komponentu
GtkWidget *gtk_table_new(guint row, guint column, gboolean homogenous); //Utworzenie tabeli

Pierwszy parametr to liczba wierszy tabeli, drugi to liczba kolumn. Trzeci to styl pakowania.

Aby dodać komponent do tabeli należy użyć funkcji:

void gtk_table_attach (GtkTable *table, GtkWidget *child, guint left_attach,
  guint right_attach, guint top_attach, guint bottom_attach, GtkAttachOptions xoptions,
  GtkAttachOptions yoptions, guint xpadding, guint ypadding);

Pierwszy parametr to tabela do której będziemy dodawać. Drugi to komponent, który dodajemy. Trzeci to kolumna (od lewej) od której liczone będzie położenie komponentu. Czwarty to kolumna do której liczona będzie szerokość komponentu. Kolejne dwa służą do opisania ułożenia pionowego położenia komponentu. Komponent może zajmować więcej niż jedną komórkę. Parametry: xoptions i yoptions mogą przyjmować następujące wartości:

  • GTK_FILL - komponent zajmuje całą komórkę
  • GTK_EXPAND - eśli komponent jest większy od komórki, to komórki są zwiększane
  • GTK_SHRINK - jeśli komponent jest większy od komórki, to jest zmniejszany

Ostatnie dwa parametry opisują odległości poziomo i pionowo od krawędzi komórek.

Przykładowy kod:

//--------------CUT HERE-----------------

#include &lt;gtk/gtk.h&gt; //Nagłówki GTK

//Zamknięcie programu GTK
void delete_event(GtkWidget *widget,GdkEvent *event, gpointer data)
{
  gtk_main_quit();
}

int main(int argc,char *argv[])
{
  GtkWidget *window; //Deklaracjekomponentów
  GtkWidget *button;
  GtkWidget *table;

  gtk_init(&amp;argc, &amp;argv); //Inicjalizacja

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //Utworzenie okna
  gtk_signal_connect(GTK_OBJECT(window), &quot;delete_event&quot;, GTK_SIGNAL_FUNC(delete_event), NULL);
    //Skojarzenie sygnału niszczenia okna z funkcją zamykającą program

  table = gtk_table_new (2, 2, TRUE); //Utworzenie tabeli
  gtk_container_add(GTK_CONTAINER(window), table); //Dodanie tabeli do kontenera (tutaj okno)

  button = gtk_button_new_with_label (&quot;button 1&quot;); //Utworzenie przycisku
  gtk_table_attach(GTK_TABLE(table), button, 0, 1, 0, 2,GTK_SHRINK, GTK_SHRINK,0,0);
    //Umieszczenie przycisku w tabeli
  gtk_widget_show(button); //Pokazanie przycisku

  button = gtk_button_new_with_label(&quot;button 2&quot;); //Utworzenie przycisku
  gtk_table_attach(GTK_TABLE(table), button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
    // Umieszczenie przycisku w tabeli
  gtk_widget_show(button); //Pokazanie przycisku

  button = gtk_button_new_with_label(&quot;button 3&quot;);
  gtk_table_attach (GTK_TABLE(table), button, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
  gtk_widget_show(button);

  gtk_widget_show(table); //Pokazanietabeli
  gtk_widget_show(window); //Pokazanie okna

  gtk_main();

  return 0;
}
//--------------CUT HERE-----------------

Funkcja gtk_table_attach ma bardzo dużo parametrów, więc aby skrócić pisanie stworzono funkcję:

void gtk_table_attach_defaults (GtkTable *table, GtkWidget *child,
  guint left_attach, guint right_attach, guint top_attach, guint bottom_attach);

której działanie jest identyczne, ale przyjmuje mniej parametrów. Przyjęto za xoptions i yoptions parametr GTK_FILL | GTK_EXPAND, a parametrom xpadding i ypadding nadano wartości 0.

Do zmiany liczby kolumn i wierszy istniejącej tabeli służy funkcja:

void gtk_table_resize(GtkTable *table, guint rows, guint columns);

Do zmiany odległości w wierszach i kolumnach służą funkcje:

void gtk_table_set_row_spacing (GtkTable *table, guint row, guint spacing);
void gtk_table_set_col_spacing (GtkTable *table, guint column, guint spacing);

Do zmiany wszystkich odległości używamy funkcji:

void gtk_table_set_row_spacings (GtkTable *table, guint spacing);
void gtk_table_set_col_spacings (GtkTable *table, guint spacing);

Aby zmienić homogeniczność (jednorodność) należy użyć funkcji:

void gtk_table_set_homogeneous (GtkTable *table, gboolean homogenous);

Przełączany Przycisk (Toggle Button)

Ten przycisk wygląda jak normalny przycisk, ale przyjmuje dwa stany: wciśnięty i niewciśnięty. Do stworzenia przycisku należy
użyć jednej z dwóch funkcji:

GtkWidget *toggle=gtk_toggle_button_new(void);
GtkWidget *toggle=gtk_toggle_button_new_with_label(const gchar *label);

Pierwsza tworzy przycisk bez napisu (label) lub z nim.

Do zmiany stanu przycisku służy funkcja:

gtk_toggle_button_set_active(GtkToggleButton *toggle_button, gboolean is_active);

w której pierwszy parametr to przycisk którego zmieniamy stan, a drugi to to stan który przyjmuje wartość 0(niewciśnięty) lub 1(wciśnięty).

Do pobrania stanu (statusu) przycisku służy funkcja:

gboolean gtk_toggle_button_get_active(GtkToggleButton *button);

która zwraca 0, gdy przycisk nie jest wciśnięty i 1 jeśli jest.
Z przełączanym przyciskiem można połączyć zdarzenie toggled.

Przykładowy kod:

//--------------CUT HERE-----------------


#include &lt;gtk/gtk.h&gt; //Nagłówki GTK

void togg(GtkWidget *widget, gpointer *data) {
  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data)))
     //Sprawdza stan (aktywność) przycisku, przy użyciu makra wyciągającego z parametru data
    g_print(&quot;State is 1\\n&quot;);
  else
    g_print(&quot;State is 0\\n&quot;);
}

int main(int argc,char *argv[])  {
  GtkWidget *window; //Deklaracja okna
  GtkWidget *button; //Deklaracja przycisku

  gtk_init(&amp;argc, &amp;argv);   //Inicjalizacja
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //Utworzenie nowego okna
  gtk_window_set_title(GTK_WINDOW (window), &quot;Toggle Button&quot;); //Zmiana tytułu okna
  gtk_signal_connect(GTK_OBJECT(window), &quot;destroy&quot;, GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
    //Połączenie zdarzenia z funkcją

  button=gtk_toggle_button_new_with_label(&quot;I'm a toggle button&quot;);
    //Utworzenie przycisku toggle z napisem
  gtk_container_add(GTK_CONTAINER(window),button); //Dodanie przycisku do kontenera (tutaj okna)
  gtk_signal_connect(GTK_OBJECT (button), &quot;toggled&quot;,
    GTK_SIGNAL_FUNC(togg), (gpointer *)button); //Połączenie zdarzenia toggled z funkcją togg

  gtk_widget_show(button);  //Pokazanie przycisku
  gtk_widget_show(window);  //Pokazanie okna

  gtk_main(); //Główna pętla programu
  return 0;
}

//--------------CUT HERE-----------------

Przycisk testowy (check button)

Check button (znany także jako check box) jest podklasą (subclass) przycisku toggle. Może być używany do wyboru pewnych opcji.

Do stworzenia przycisku można użyć funkcji:

GtkWidget* gtk_check_button_new (void);
GtkWidget* gtk_check_button_new_with_label(const gchar *label);

Których działanie jest analogiczne jak w przycisku toggle.

Przykładowy kod:

//--------------CUT HERE-----------------
#include &lt;gtk/gtk.h&gt;

void togg(GtkWidget *widget, gpointer *data) {
  //Sprawdza zaznaczenie (aktywność) przycisku
  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data)))
    g_print(&quot;State is 1\\n&quot;);
  else
    g_print(&quot;State is 0\\n&quot;);
}

int main(int argc,char *argv[])
{
  GtkWidget *window; //Deklaracja okna
  GtkWidget *button; //Deklaracja przycisku

  gtk_init(&amp;argc, &amp;argv); //Inicjalizacja

  //Stworzenie nowego okna
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  //Zmiana tytułu
  gtk_window_set_title(GTK_WINDOW (window), &quot;Check Button&quot;);

  gtk_signal_connect(GTK_OBJECT (window), &quot;destroy&quot;,
    GTK_SIGNAL_FUNC(gtk_main_quit), NULL);

  //Stworzenie check button'a
  button = gtk_check_button_new_with_label(&quot;I'm a check button&quot;);
  gtk_container_add(GTK_CONTAINER(window),button);
  gtk_signal_connect(GTK_OBJECT(button), &quot;toggled&quot;,
    GTK_SIGNAL_FUNC(togg), (gpointer *)button);
  gtk_widget_show(button);
  gtk_widget_show

  gtk_main();

  return 0 ;
}
//--------------CUT HERE-----------------

Napis (Label)

Etykiety pozwalają na wstawienie dowolnego tekstu w dowolne miejsce w oknie.

Do stworzenia etykiety używamy funkcji:

GtkWidget* gtk_label_new(const gchar *text);

Zawartość etykiety możemy zmienić w dowolnym czasie funkcją:

gtk_label_set_text(GtkLabel *label, gchar *text);

Do zmiany wyrównania napisu używamy funkcji:

gtk_label_set_justify(GtkLabel *label, GtkJustification jtype);

Parametr jtype może przyjmować wartości:

  • GTK_JUSTIFY_LEFT - wyrównanie do lewej
  • GTK_JUSTIFY_RIGHT - wyrównanie do prawej
  • GTK_JUSTIFY_CENTER - wyśrodkowanie
  • GTK_JUSTIFY_FILL - do pokrycia całej etykiety napisem</li>

Do zmiany zawijania wierszy w etykiecie używamy funkcji:

gtk_label_set_line_wrap (GtkLabel *label, gboolean wrap);

Kiedy parametr wrap ustawimy na 1 to napisy będą zawijane, jeśli 0 to nie.

Aby pobrać tekst z etykiety używamy funkcji:

gtk_label_get(GtkLabel *label, gchar **str)

w której, pierwszy parametr to etykieta, a drugi to wskaźnik do napisu (char*) pod który zostanie zapisany tekst z napisu.

Okienka informacyjne - podpowiedzi (tooltips)

Tooltips jest to napis jaki pojawi się gdy zatrzymamy przez chwilę myszkę na komponencie. Do utworzenia tego najpierw trzeba utworzyć komponent GtkToolTips:

GtkToolTips* gtk_tooltips_new();

Następnie należy przymocować go do komponentu(widgetu) :

gtk_tooltips_set_tip(GtkTooltips *tooltips, GtkWidget *widget,
  const gchar *tip_text, const gchar *tip_private);

Przykład:

//--------------CUT HERE-----------------
#include &lt;gtk/gtk.h&gt; //Nagłówki

int main(int argc,char *argv[])
{
  //Deklaracje:
  GtkWidget *window;
  GtkWidget *button;
  GtkTooltips *tip;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW (window), &quot;Tooltips&quot;);

  gtk_signal_connect(GTK_OBJECT (window), &quot;destroy&quot;,
    GTK_SIGNAL_FUNC (gtk_main_quit), NULL);

  button=gtk_button_new_with_label(&quot;I'm a Button&quot;);
  gtk_container_add(GTK_CONTAINER(window),button);

  tip = gtk_tooltips_new(); //Utworzenie podpowiedzi
  //Przymocowanie podpowiedzi tip do przycisku button i nadaniu jej napisu Click me!
  gtk_tooltips_set_tip(tip, button, &quot;Click me!&quot;, NULL);

  gtk_widget_show(button); //Pokazanie przycisku
  gtk_widget_show(window);

  gtk_main();

  return 0;
}
//--------------CUT HERE-----------------

Dodatkowe funkcje:

gtk_tooltips_enable (GtkTooltips *tooltips);   //Włącza podpowiedź
gtk_tooltips_disable (GtkTooltips *tooltips); //Wyłącza podpowiedź
gtk_tooltips_set_delay (GtkTooltips *tip, guint delay) //Zmienia czas (parametr delay)
  // pokazywania się podpowiedzi (parametr tip)

Do pobrania zawartości podpowiedzi z dowolnego komponentu używamy funkcji:

GtkTooltipsData* gtk_tooltips_get_data(GtkWidget *widget);

Która zwraca strukturę GtkTooltipsData o następującej budowie:

struct _GtkTooltipsData
{
  GtkTooltips *tooltips;
  GtkWidget   *widget;
  gchar       *tip_text;
  gchar       *tip_private;
  GdkFont     *font;
  gint         width;
  GList       *row;
};

Pudełko kombinacyjne (combo box)

Combo box jest możliwym do edycji polem tekstowym z wysuwanym do dołu menu. Można w nim samodzielnie wpisywać wartość lub
wybierać z menu.

Combo box tworzy się używając funkcji:

GtkWidget *gtk_combo_new();

Oprócz niego potrzebna będzie lista opcji do wyboru.
Jej deklaracja:

GList *glist = NULL;

Do dodania opcji do listy służy funkcja:

GList *g_list_append(GList *list, gchar *option);

Gdzie pierwszy parametr to lista do której dodajemy, a drugi to opcja (napis typu char*)
Następnie należy dodać listę do combo box'a funkcją:

gtk_combo_set_popdown_strings(GtkCombo *combo, GList *List);

gdzie pierwszy parametr to combo box, a drugi lista.

Combo box jest gotowy. Do odczytania wybranej opcji służy funkcja:

gchar *gtk_entry_get_text(GtkEntry *entry);

która zwraca tekst (char* lub char[]) z combo box'a, a parametr entry to GTK_ENTRY(GTK_COMBO(combo)->entry)), gdzie combo to nasz combo box.

Do zezwalania lub zablokowania zmiany opcji combo box'a przy pomocy strzałek klawiatury służy funkcja:

gtk_combo_set_use_arrows(GtkCombo *combo,gint val);

w której val przypisujemy 0 lub 1.

Działanie funkcji:

gtk_combo_set_use_arrows_always(GtkCombo* combo,gint val);

jest identyczne jak powyższej z tym, że kiedy tekst w combo box'ie jest różny od wartości z listy, strzałki funkcjonują.

Do zmiany wartości w combo box'ie służy funkcja:

gtk_combo_set_value_in_list(GtkCombo *combo, gboolean val, gboolean ok_if_empty);

kiedy val to 1, może wpisywać opcje na listę. Kiedy ok_if_empty to 1, wartość może być pusta.

Przykład:

//--------------CUT HERE-----------------
#include &lt;gtk/gtk.h&gt;

void act(GtkWidget *widget, gpointer *data) {
  g_print((gchar *)data);
}

int main(int argc,char *argv[]) {
  GtkWidget *window;
  GtkWidget *combo;
  GtkWidget *button;
  GtkWidget *box;
  GList *list = NULL;

  list = g_list_append(list,&quot;Slackware&quot;);
  list = g_list_append(list,&quot;RedHat&quot;);
  list = g_list_append(list,&quot;SuSE&quot;);

  gtk_init (&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW (window), &quot;Combo Box&quot;);
  gtk_signal_connect(GTK_OBJECT (window), &quot;destroy&quot;,
    GTK_SIGNAL_FUNC(gtk_main_quit), NULL);

  box=gtk_hbox_new(1, 0);
  gtk_container_add(GTK_CONTAINER(window), box);

  combo=gtk_combo_new();
  gtk_combo_set_popdown_strings(GTK_COMBO(combo), list);
  gtk_combo_set_use_arrows_always(GTK_COMBO(combo), 1);
  gtk_box_pack_start(GTK_BOX(box), combo,1,1,1);

  button = gtk_button_new_with_label(&quot;Write it&quot;);
  gtk_signal_connect(GTK_OBJECT(button),&quot;clicked&quot;,GTK_SIGNAL_FUNC(act),

  gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)-&gt;entry)));
  gtk_box_pack_start(GTK_BOX(box), button,1,1,1);

  gtk_widget_show(box);
  gtk_widget_show(combo);
  gtk_widget_show(button);
  gtk_widget_show(window);

  gtk_main();
  return 0;
}
//--------------CUT HERE-----------------

I to by było na tyle. Ogólnie same podstawy, ale wystarczające aby zrozumieć na czym to wszystko polega. Kolejnym krokiem powinno być czytanie nagłówków GTK i próba opanowania Glade'a.

2 komentarzy

Nastepny dobry art dotyczasy linuxa! TAK TRZYMAC!!!

Czy mi się wydaje, ze te 2 arty są takie same ??