Programowanie Graficznego Interfejsu Użytkownika GUI za pomocą GTK

ArticleCategory:

SoftwareDevelopment

AuthorImage:

Ozcan Gungor

TranslationInfo:

original in tr Özcan Güngör

tr to en Özcan Güngör

en to pl Daniel Maciejewski

AboutTheAuthor

Używam Linux'a od 1997. Swoboda, elastyczność oraz otwarty kod. To są właściwości które lubię.

Abstract

W tej serii artykułów nauczymy się jak pisać aplikacje z graficznym interfejsem użytkownika (GUI) używając GTK. Nie mam pojęcia jak długa będzie ta seria. Żeby zrozumieć te artykuły, musisz znać kilka podstaw języka programowania C, mianowicie:


ArticleIllustration:

GTK

ArticleBody:

Czym jest GTK?

GTK (GIMP Toolkit) jest biblioteką pozwalającą tworzyć interfejsy graficzne. Ta biblioteka jest dostępna na licencji GPL. Używając więc tej biblioteki możesz tworzyć darmowe lub komercyjne programy typu open-source.

Biblioteka ta ma nazwę GIMP toolkit (GTK) ponieważ była oryginalnie zaprojektowana dla rozwoju programu GIMP (General Image Manipulation Program). Autorami GTK są:

GTK jest zorientowaną obiektowo aplikacją interfejsu użytkownika. Chociaż napisana jest w C, używa idei klas oraz funkcji połączenia zwrotnego (callback functions).

Kompilacja

Żeby skompilować programy korzystające z GTK, musisz powiedzieć kompilatorowi gcc jakie biblioteki są potrzebne i gdzie się znajdują. Te informacje możemy uzyskać stosując komendę gtk-config.

# gtk-config --cflags --libs

Wyniki zwrócone przez wykonanie tej komendy mogą być (zależnie od systemu) podobne do poniższych:

-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

Oto wyjaśnienia powyższych parametrów:

-l biblioteka: Szuka biblioteki w postaci libbiblioteka.a w zdefiniowanych ścieżkach.
-L ścieżka : Dodaje ścieżkę poszukiwań dla bibliotek.
-I ścieżka : Dodaje ścieżkę poszukiwań dla plików nagłówkowych, używanych w programie.

Aby skompilować program GTK o nazwie hello.c, musi być użyta następująca komenda:

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

Parametr użyty po opcji -o decyduje o nazwie, jaką będzie miał skompilowany program.

Pierwszy program

Zakładam, że masz zainstalowane GTK w swoim systemie. Najświeższą wersję GTK możesz znaleźć na serwerze ftp.gtk.org.

Napiszmy nasz pierwszy program. Tworzy on puste okno o rozmiarze 200x200 pikseli.

#include <gtk/gtk.h>

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

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_widget_show  (window);

    gtk_main ();

    return(0);
}

GtkWidget jest typem zmiennej, służącym do definiowania różnych komponentów takich jak okno (window), przycisk (button), etykieta (label) ... W tym przykładzie, okno jest zdefiniowane w następujący sposób:

GtkWidget *window;

void gtk_init(int *argc,char ***argv) służy do inicjalizacji oraz pobiera parametry wpisane w linii komend. Funkcja ta musi być użyta po zdefiniowaniu komponentów.

GtkWidget *gtk_window_new(GtkWindowType windowtype) tworzy nowe okno. Typem okna może być:

void gtk_widget_show(GtkWidget *widget) używa się aby komponent stał się widoczny w oknie.Po zdefiniowaniu komponentu oraz ustawieniu atrybutów ta funkcja musi zostać użyta.

void gtk_main(void) przygotowuje okna oraz wszystkie komponenty do pojawienia się na ekranie. Tej funkcji należy używać na końcu programów GTK.

Użyjemy teraz pewnych właściwości okna takich jak tytuł, rozmiar, pozycja ...

void gtk_window_set_title(GtkWindow *window,const gchar *title) jest używana do ustawienia bądź zmiany tytułu okna. Pierwszy parametrem tej funkcji jest typu GtkWindow. Ale zmienna window jest typu GtkWidget. Podczas kompilacji dostaniemy ostrzeżenie informujące nas o tym fakcie. Chociaż skompilowany program zadziała, to jednak lepiej jest to poprawić. Używa się do tego GTK_WINDOW(GtkWidget *widget). Drugi parametr title (tytuł) jest typu gchar. gchar został zdefiniowany w bibliotece glib tak samo jak typ char.

void gtk_window_set_default_size(GtkWindow *window, gint width, gint height) ustawia rozmiar okna window (width oznacza szerokość, height - wysokość). Podobnie jak gchar, również gint jest zdefiniowane w bibliotece glib tak samo jak int.

Funkcja

void gtk_window_set_position(GtkWindow *window, GtkWindowPosition position)

ustawia pozycję okna window. Wartością position może być:

Poniżej przedstawiony jest przykład programu:

#include <gtk/gtk.h>

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

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window),"Ýlk Program");
    gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window),300,300);
    gtk_widget_show  (window);

    gtk_main ();

    return(0);
}

Sygnały i zdarzenia.

Używając intefejsu graficznego GUI, potrzebujesz używać myszki i klawiatury np. aby kliknąć przycisk. Dlatego używa się następujacej funkcji GTK:

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

object jest komponentem, od którego pochodzi sygnał. Np. jeśli chcesz wiedzieć czy został kliknięty button (czyli przycisk) , nasz object to właśnie będzie ten button. name jest nazwą zdarzenia i może to być:

func jest nazwą funkcji, która zostanie wywołana gdy wystąpi określone zdarzenie. Oto przykład:

#include <gtk/gtk.h>

void close( GtkWidget *widget,gpointer *data)
{
    gtk_main_quit();
}

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

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (close), NULL);
    gtk_widget_show  (window);

    gtk_main ();

    return(0);
}

Funkcja

gtk_signal_connect (GTK_OBJECT (window), "destroy",GTK_SIGNAL_FUNC (close), NULL)

nasłuchuje czy dla okna wystąpiło zdarzenie destroy (zniszcz). Gdy nastąpi więc próba zamknięcia okna zostanie wywołana funkcja close. Funkcja close wywołuje funkcję gtk_main_quit() i program kończy działanie.

Szczegóły na temat sygnałów i zdarzeń zostaną wyjaśnione później...

Zwykły przycisk

Normalne przyciski są zwykle używane do robienia pewnych rzeczy, gdy zostaną kliknięte. W bibliotece GTK są dwa sposoby tworzenia przycisków:

  1. GtkWidget* gtk_button_new (void);
  2. GtkWidget* gtk_button_new_with_label (const gchar *label);

Pierwsza funkcja tworzy przycisk bez etykiety (tzn.nic nie jest napisane na przycisku). Druga natomiast tworzy przycisk z etykietą (label), która jest napisana na przycisku.

Teraz użyjemy nowej funkcji:

void gtk_container_add(GtkContainer *container,GtkWidget *widget)

Użycie tej funkcji umożliwia stworzenie przycisku (ogólnie rzecz biorąc każdego komponentu) który pojawi się w oknie (generalnie w kontenerze). W kolejnym przykładzie kontenerem jest okno (window), a komponentem, który zostanie dodany jest przycisk (button). O innych kontenerach dowiesz się później.

Najważniejszą rzeczą jaką trzeba wiedzieć o przycisku jest to czy został on kliknięty czy nie. Znowu do tego celu używa się funkcji gtk_signal_connect. Dzięki tej funkcji inna funkcja zostanie wywołana i w ten sposób "za przyciskiem" zostanie ukryta pewna funkcjonalność. Oto przykład:

#include <gtk/gtk.h>

void close( GtkWidget *widget,gpointer *data)
{
    gtk_main_quit();
}

void clicked(GtkWidget *widget,gpointer *data)
{
        g_print("Button Clicked\n");
}
int main( int   argc,char *argv[] )
{
    GtkWidget *window,*button;

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_signal_connect (GTK_OBJECT (window), "destroy",
                        GTK_SIGNAL_FUNC (close), NULL);

    button=gtk_button_new_with_label("Button");
    gtk_container_add(GTK_CONTAINER(window),button);
    gtk_signal_connect(GTK_OBJECT(button),"clicked",
                       GTK_SIGNAL_FUNC(clicked),NULL);
    gtk_widget_show(button);

    gtk_widget_show(window);

    gtk_main ();

    return(0);
}