2006.04_Piszemy widget zegara w GTK+_[Programowanie].pdf

(723 KB) Pobierz
439113691 UNPDF
dla programistów
Piszemy
widget zegara
w GTK+
Marek Sawerwain
w ANSI C i ma przystępne API,
co sprawia, że względnie szyb-
ko można nauczyć się pisania
skomplikowanych programów za jej po-
mocą. Tworzenie własnych widgetów (kon-
trolek graicznych) w GTK+ nie jest już jed-
nak zadaniem zbyt łatwym i wymaga bar-
dzo dobrej znajomości biblioteki, która za-
zwyczaj nie jest potrzebna podczas two-
rzenia typowego oprogramowania. W tym
artykule przedstawię, jak utworzyć własny
widget. Będzie to zegar, którego później
będzie można użyć do „upiększenia” wła-
snej aplikacji.
Nie będzie to zegar liczbowy, bo taki
widget byłby mimo wszystko zbyt łatwy
do opracowania. Dokonamy implemen-
tacji tradycyjnego zegara ze wskazów-
kami. Dodatkowo, użyjemy najnowsze-
go elementu GTK+, czyli biblioteki Cairo ,
która jest odpowiedzialna za generowanie
wysokiej jakości graiki 2D. Oznacza to,
iż należy dysponować najnowszą wersją
GTK+, np. 2.8.x. Z tego powodu opisany
w tym artykule widget nie będzie współpra-
cować z jakąkolwiek starszą wersją GTK+.
będzie przygotowanie dwóch struktur:
klasy oraz obiektu kontrolki (pojęcia klasa
czy obiekt GTK+, a dokładniej obiekt typu
GObject , warto traktować jako odpowiedni-
ki klasy i obiektu z języka C++).
Z procedurą osadzania związana jest
także inicjalizacja obiektu, o ile klasa jest
Instalacja biblioteki GTK+
Zastosowana przez nas wersja GTK+
2.8.x nie jest jeszcze szeroko stosowa-
na. W wielu nieco starszych dystrybucjach
systemu Linux jest dostępna poprzednia
wersja stabilna 2.6.x. Z tego powodu jest
całkiem prawdopodobne, iż nowa wersja
nadal nie jest dostępna. Nie trzeba się tym
jednak martwić, gdyż można bez więk-
szych problemów podmienić wersję GTK+
2.6.x na nowszą 2.8.x. Wymaga to samo-
dzielnej kompilacji GTK+ ze źródeł. W tym
celu należy skompilować kilka pakietów:
GLIB, ATK, PANGO, CAIRO oraz ostatecz-
nie GTK+. Wszystkie biblioteki instalujemy
w katalogu /usr . Ponieważ każda z biblio-
tek posiada skrypt conigure , to za każdym
razem wystarczą trzy linie kodu:
DVD
Po uruchomieniu Linux+ Live
DVD możesz zapoznać się
z prostą aplikacją z opisywanym
w artykule widgetem zegara.
Plan kontrolki
Dla widgetu nie można utworzyć typowe-
go schematu blokowego, ponieważ kon-
trolka to tylko pewien niewielki fragment
większego programu bądź systemu. Po-
mimo tego, schemat z Rysunku 1 porusza
wszystkie obszary istotne dla poprawnego
funkcjonowania kontrolki.
Pierwszym elementem, którym musi-
my się zająć, jest osadzenie kontrolki. Cho-
ciaż za ten proces jest odpowiedzialny sam
system GTK+, to jednak naszym zadaniem
./conigure –preix=/usr
make
make install
aby daną bibliotekę skonigurować, poddać
kompilacji oraz instalacji. Ponieważ autorzy
GTK+ utrzymują zgodność binarną swojej
biblioteki wstecz, to nie powinno być pro-
blemów, aby GNOME i inne aplikacje
GTK+ współpracowały z nowszą wersją
biblioteki, którą instalujemy „na dziko” w ist-
niejącym systemie.
Na płycie CD/DVD
Na płycie CD/DVD znajdują się
wykorzystywane biblioteki oraz
kod źródłowy programu.
72 kwiecień 2006
B iblioteka GTK+ jest napisana
439113691.047.png 439113691.052.png 439113691.053.png
 
439113691.001.png 439113691.002.png 439113691.003.png 439113691.004.png 439113691.005.png 439113691.006.png 439113691.007.png 439113691.008.png 439113691.009.png
 
GTK+/Cairo
dla programistów
#deine GTK_IS_CLOCK(obj)
(G_TYPE_CHECK_INSTANCE_TYPE
((obj), GTK_TYPE_CLOCK))
Rysunek 1. Schemat zdarzeń, które pojawiają się w kontrolce zegara
Wykorzystujemy tu inne makro, G_TYPE_
CHECK_INSTANCE_TYPE , które sprawdza,
czy obiekt to instancja odpowiedniego dla
nas typu, określonego przez zdeiniowane
przez nas makro GTK_TYPE_CLOCK . Jednak,
gdy spojrzymy ponownie na Listing 1, to
okaże się, iż makro GTK_TYPE_CLOCK ogra-
nicza się do wywołania funkcji o nazwie
gtk_clock_get_type . Jej zadaniem jest
utworzenie struktury reprezentującej typ
widgetu. Jak się za chwilę okaże, funk-
cja gtk_clock_get_type jest generowana
samoczynnie, więc nie musimy się mar-
twić jej postacią.
Kolejnym elementem są dwie struktu-
ry. _GtkClock jest odpowiedzialna za prze-
chowywanie wartości związanych z kon-
kretnym obiektem, czyli instancją klasy
GtkClock , która to jest reprezentowana
przez strukturę o nazwie _GtkClockClass .
Do obydwu struktur za pomocą type-
def tworzone są nowe redeinicje, co jest
ważne z powodu pewnych konwen-
cji, które zostały przyjęte przez autorów
GTK+ oraz GLib.
Struktura _GtkClock posiada zaledwie
pięć pól. Pola o nazwach h , m i s będą
zawierać aktualny czas, a pole clock_
update_handle zawiera uchwyt do obie-
ktu timer , który w równych jednosekun-
dowych odstępach czasu będzie uaktu-
alniał nasz zegar. Ostatnim polem jest
parent , które będzie wskazywać na
widget rodzicielski naszej kontrolki
– inaczej mówiąc, widget, który zawiera
(można powiedzieć, przechowuje) nasza
kontrolkę.
Struktura klasy jest już znacznie bar-
dziej uboższa, ponieważ zawiera tylko
jedno pole, w którym przechowujemy
wskazanie na klasę rodzica naszego wid-
getu. Po deinicji klasy pozostaje nam tylko
wymienić funkcje publiczne. W naszym
przypadku będzie to tylko funkcja kon-
struktora gtk_clock_new . Oczywiście, jeśli
dodamy do naszej kontrolki więcej moż-
liwości, to w pliku nagłówkowym należy
wymienić nowe funkcje.
tworzona częściowo przez system obiek-
towy GTK+ -- chociaż i tak piszemy funk-
cję przeznaczoną do inicjalizacji klasy, to
ważnym zadaniem jest napisanie kon-
struktora obiektu, tzn. funkcji o nazwie np.
gtk_clock_new .
Oprócz klasy oraz konstruktora, nale-
ży podłączyć obsługę dwóch zdarzeń . Pier-
wsze to zdarzenie expose , które jest wywo-
ływane, gdy system prosi o narysowa-
nie kontrolki na ekranie. Drugie to zda-
rzenie timer , które będzie generowane
cyklicznie co sekundę. Jest ono potrzebne,
aby nasz zegar co sekundę odświeżał swój
wygląd.
Aby wprowadzić więcej czytelności do
kodu, za narysowanie widgetu (w naszym
przypadku to tarcza typowego zegara)
będzie odpowiedzialna inna funkcja o naz-
wie draw_clock , będąca funkcją prywatną
klasy GtkClock .
Chociaż można dodać jeszcze wiele
innych przydatnych funkcji, np. dbają-
cych o wygląd naszego zegara, to jednak,
aby uprościć nasz widget, poprzestaniemy
tylko na implementacji podstawowej funk-
cjonalności kontrolki.
biblioteki GTK+, każdy plik z implemen-
tacją innych widgetów będzie posiadał
podobną strukturę.
Kod pliku nagłówkowego po zdeinio-
waniu stałej __GTK_CLOCK_H__ oraz po włą-
czeniu pliku gtk.h rozpoczynamy od wy-
wołania makra G_BEGIN_DECLS i, co ważne,
kończymy G_END_DECLS . Obecnie zada-
niem tych makr jest dodanie wyrażenia
extern ”C” , aby nasz projekt kompilował
się poprawnie w środowisku C++. Nie
jest wykluczone, iż w przyszłości makra te
będą wprowadzać inne istotne deinicje.
Następnie podajemy kilkanaście dei-
nicji makr, które ułatwiają używanie kon-
trolki w środowisku GTK+. Przydatnym
makrem jest np. GTK_CLOCK , które wyko-
nuje konwersję widgetu ogólnego typu
( GtkWidget ) na widget typu GtkClock .
Ważnym makrem jest również GTK_IS_
CLOCK , gdyż pozwala ono sprawdzić, czy
dany obiekt jest istotnie instancją klasy
GtkClock . W każdym dynamicznym sys-
temie obiektowym tego typu funkcje są
konieczne, aby cały system funkcjonował
poprawnie.
Jak widać, nie musimy deiniować
tych makr wprost – wystarczy skorzy-
stać z gotowych funkcji, które znajdują się
w API systemu GObject , będącego częścią
biblioteki GLib .
Wymienione makro sprawdzające, czy
dany obiekt jest typu GtkClock , posiada
następującą deinicję:
Plik nagłówkowy
Tworzenie widgetu zaczniemy od przy-
gotowania pliku nagłówkowego, którego
pełny kod źródłowy znajduje się na Listin-
gu 1. Chociaż nasz widget ma charakter
edukacyjny, to przeglądając kod źródłowy
Implementacja widgetu
Po przygotowaniu pliku nagłówkowego
można przystąpić do implementacji nasze-
go widgetu. Plik źródłowy, umieszczony
na płycie CD/DVD, który ją zawiera, nosi
nazwę gtk_clock.c . Jest on zbyt duży, aby
www.lpmagazine.org
73
439113691.010.png 439113691.011.png 439113691.012.png 439113691.013.png 439113691.014.png 439113691.015.png 439113691.016.png 439113691.017.png 439113691.018.png 439113691.019.png 439113691.020.png
dla programistów
Listing 1. Plik nagłówkowy widgetu GtkClock
słowa class jako nazwy argumentu stosu-
je się słowo klass . W ten sposób kod może
być kompilowany za pomocą kompilatora
języka C++.
Druga funkcja jest jeszcze krótsza:
#ifndef __GTK_CLOCK_H__
#deine __GTK_CLOCK_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#deine GTK_TYPE_CLOCK (gtk_clock_get_type ())
#deine GTK_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GTK_TYPE_CLOCK, GtkClock))
#deine GTK_CLOCK_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj),
GTK_CLOCK, GtkClockClass))
#deine GTK_IS_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GTK_TYPE_CLOCK))
#deine GTK_IS_CLOCK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj),
GTK_TYPE_CLOCK))
#deine GTK_CLOCK_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj),
GTK_TYPE_CLOCK, GtkClockClass))
typedef struct _GtkClock GtkClock ;
typedef struct _GtkClockClass GtkClockClass ;
struct _GtkClock {
GtkDrawingArea parent ;
/* < private > */
guint clock_update_handle ;
int h , m , s ;
} ;
struct _GtkClockClass {
GtkDrawingAreaClass parent_class ;
} ;
GtkWidget * gtk_clock_new ( void );
G_END_DECLS
# endif /* __GTK_CLOCK_H__ */
static void gtk_clock_init
(GtkClock *clock) {
clock->clock_update_handle=g_
timeout_add( 1000, clock_
update, clock);
}
Wykonujemy tylko jedną czynność, a mia-
nowicie tworzymy nowy obiekt timer , a uch-
wyt do tego obiektu zapamiętujemy w po-
lu clock_update_handle . Zakładamy, iż fun-
kcja, która będzie zajmować się uaktual-
nieniem zegara ( clock_update ), będzie wy-
woływana co sekundę. Jej treść znajduje
się na Listingu 2.
Głównym zadaniem funkcji clock_up-
date jest odczytanie aktualnego czasu przy
wykorzystaniu funkcji time oraz localti-
me . Uzyskane informacje przepisujemy do
pól h , m , s obiektu clock . Pozostaje już tylko
wywołać funkcję gtk_widget_queue_draw ,
której zadaniem jest ponowne narysowania
widgetu, czyli wywołanie funkcji przypisa-
nej do zdarzenia expose .
Danie główne – rysowanie
zegara
Za proces rysowania naszej kontrolki odpo-
wiedzialne są trzy funkcje. Pierwsza, która
jest wywoływana przez system GTK+, to
gtk_clock_expose . Oczywiście, aby kod
naszego widgetu był bardziej przejrzy-
sty, sam zegar jest rysowany przez funk-
cję draw_clock . Korzystamy także z jesz-
cze jednej funkcji o nazwie my_draw_text .
Zgodnie ze swoją nazwą, funkcja ta „rysuje”
tekst, co jest dość dobrym określeniem dla
go zaprezentować w całości, więc przeana-
lizujemy tylko wybrane fragmenty.
Na początku po włączeniu niezbęd-
nych plików nagłówkowych time.h , math.h
i gtk.h dołączamy nasz plik nagłówkowy
gtk_clock.h . Następnie, zanim przystąpi-
my do implementacji, pojawia się bardzo
ważna linia, w której wykorzystujemy
makro G_DEFINE_TYPE :
oraz gtk_clock_init . Pierwsza dokonuje
inicjalizacji klasy, a druga obiektu.
Treść pierwszej jest następująca:
static void gtk_clock_class_init
(GtkClockClass *class) {
GtkWidgetClass *widget_class;
widget_class = GTK_WIDGET_
CLASS (class);
widget_class->expose_event =
gtk_clock_expose;
}
G_DEFINE_TYPE
(GtkClock, gtk_clock,
GTK_TYPE_DRAWING_AREA);
W ten sposób tworzymy podstawowy
szkielet obiektu GtkClock . Jest w nim m.in.
funkcja o nazwie gtk_clock_get_type ,
o której była mowa w poprzednim punk-
cie, więc nie musimy jej samodzielnie
implementować – dokona tego za nas ma-
kro G_DEFINE_TYPE .
Najwięcej miejsca w implementacji
widgetu zegara poświęcamy samemu pro-
cesowi rysowania tego zegara, ale ważne
są wszystkie czynności, a szczególnie
funkcje o nazwach gtk_clock_class_init
Pierwsza linia kodu tej funkcji to deklara-
cja zmiennej pomocniczej widget_class .
Druga linia dokonuje konwersji klasy
GtkClockClass na klasę GtkWidgetClass , a
następnie do funkcji expose_event podłą-
czana jest funkcja, której zadaniem będzie
rysowanie naszego zegara. Więcej czynno-
ści nie musimy wykonywać. Warto jesz-
cze zwrócić uwagę na argument funkcji
gtk_clock_class_init . Możemy bezkarnie
użyć słowa class , ponieważ plik gtk_clock.c
będzie kompilowany za pomocą kompila-
tora języka C. Dość często w GTK+ zamiast
Rysunek 2. Widget GtkClock
74 kwiecień 2006
439113691.021.png 439113691.022.png 439113691.023.png
 
439113691.024.png 439113691.025.png 439113691.026.png 439113691.027.png 439113691.028.png 439113691.029.png 439113691.030.png
 
GTK+/Cairo
dla programistów
Listing 2. Uaktualnienie czasu w kontrolce GtkClock
Godzinami głównymi (dłuższa kreska)
będą godziny podzielne przez trzy: 12, 9,
6 oraz 3. Ustalenie długości odbywa się za
pomocą instrukcji warunkowej w liniach
18-27 – zostaje ona zapamiętana w zmien-
nej tmp . Dodatkowo, gdy rysujemy krótsze
linie, dla pozostałych godzin pogrubiamy
nieco linię.
Po ustaleniu długości, czeka nas małe
wyzwanie matematyczne. Za pomocą
wspomnianej powyżej pętli for generuje-
my 12 godzin, a dla każdej godziny pod
pewnym kątem musimy narysować na
blacie naszego zegara kreskę o odpowied-
niej ustalonej już długości.
Proces ten zaczynamy od przesunię-
cia kursora graicznego za pomocą funk-
cji cairo_move_to o odległość promienia
pomniejszoną o wartość tmp . W pewnym
sensie wykorzystujemy tu układ biegu-
nowy (taki, w którym nie posługujemy
się wartościami przesunięcia wzdłuż osi
X i Y, ale mówimy, że przesuwamy się
od początku układu o ustaloną długość
pod pewnym kątem), bowiem od ustalo-
nego punktu x i y przesuwamy się o dłu-
gość radius – tmp , ale pod kątem, który
jest dany wzorem i * M_PI / 6 , czyli o
wielokrotność 30 stopni. Gdy przesunie-
my kursor pod wyznaczone współrzędne,
to funkcją cairo_line_to rysujemy linię
oznaczającą odpowiednią godzinę.
Po narysowaniu wszystkich oznaczeń
godzin na cyferblacie naszego zegara, w
linii 40 umieszczamy tekst z komunika-
tem o producencie zegarka. Oczywiście,
gboolean clock_update ( gpointer data ) {
time_t t ;
struct tm * td ;
GtkClock * c =( GtkClock *) data ;
time (& t ); td = localtime (& t );
c -> h = td -> tm_hour ;
c -> m = td -> tm_min ;
c -> s = td -> tm_sec ;
gtk_widget_queue_draw ( GTK_WIDGET ( c ));
return TRUE ;
}
sposobu pracy biblioteki Cairo.
Przed właściwym rysowaniem kon-
trolki, w funkcji obsługującej zdarzenie
expose , musimy utworzyć obiekt typu
cairo_t . Wykonujemy to w następujący
sposób:
go obszaru, po którym będziemy rysować.
Niezbędne obliczenia są przeprowadzane
w 6 i 7 linii. Istotny problem to dopasowa-
nie wielkość promienia (zmienna radius )
do obszaru, który został przydzielony kon-
trolce – tym zajmuje się linia 8.
Po obliczeniach rysujemy dwa okręgi,
wykorzystując funkcję cairo_arc . Pierwszy
okrąg, rysowany w linii 10, to cyferblat
naszego zegara, natomiast mniejszy okrąg
w linii 13 będzie reprezentować punkt,
w którym zostaną zaczepione wskazów-
ki. Po funkcji cairo_arc , jak widać, poja-
wia się wywołanie funkcji cairo_stroke ,
która nakazuje wykonanie ostatnich pole-
ceń rysunkowych.
Po narysowaniu okręgów rysujemy
ramkę wokół naszego zegar. Pętla for ,
która rozpoczyna się w linii 18, a kończy
w linii 37, rysuje oznaczenia godzin.
cairo_t *cr;
cr = gdk_cairo_create (clock->window);
Następnie rysujemy prostokąt na obsza-
rze, który został przydzielony kontrolce:
cairo_rectangle
(cr, event->area.x,
event->area.y,
event->area.width,
event->area.height);
Nakazujemy także wycinanie wszystkie-
go, co wychodzi poza obszar, po którym
będziemy rysować. W tym celu wystarczy
posłużyć się funkcją cairo_clip (cr); .
Ostatnim zadaniem jest uaktualnienie
czasu (przez funkcję, którą już omawiali-
śmy wcześniej) oraz narysowanie samego
zegara:
clock_update(clock);
draw_clock (clock, cr);
Po narysowaniu kontrolki możemy usunąć
obiekt Cairo, ponieważ wszystkie zmiany
zostały już umieszczone na ekranie – cairo_
destroy (cr); .
Rysujemy zegar
Doszliśmy do miejsca, w którym musimy
się zająć rysowaniem zegara, czyli funk-
cją o nazwie draw_clock . Listing 3 zawiera
wybrane fragmenty tej funkcji.
Na samym początku naszym zada-
niem jest wyznaczenie punktu środkowe-
Rysunek 2. Kontrolka GtkClock oraz program Glade
aby nasz widget
www.lpmagazine.org
75
439113691.031.png 439113691.032.png 439113691.033.png 439113691.034.png 439113691.035.png 439113691.036.png 439113691.037.png 439113691.038.png 439113691.039.png 439113691.040.png
dla programistów
Listing 3. Uaktualnienie czasu w kontrolce GtkClock
był zegarem, musimy narysować jesz-
cze wskazówki. Na Listingu 3 w liniach
od 43 do 49 rysujemy wskazówkę odpo-
wiedzialną za godzinę. Technika ryso-
wania jest podobna jak przy oznacze-
niu godzin. Na początku przesuwamy
się do środka, a następnie rysujemy linię
o odpowiedniej długości, pod kątem,
który wyznacza nam aktualna godzina.
Jednak, aby godziny nam się zgadzały
z wartościami kątów, musimy od aktual-
nej godziny odjąć wartość trzy. Podobnie
dla minut oraz sekund, gdzie odejmujemy
wartość 15.
1 : static void draw_clock ( GtkWidget * clock , cairo_t * cr ) {
2 : double x , y , radius , tmp ;
3 :
4 : int i , _h , _m , _s ;
5 :
6 : x = clock -> allocation . x + clock -> allocation . width / 2 ;
7 : y = clock -> allocation . y + clock -> allocation . height / 2 ;
8 : radius = MIN ( clock -> allocation . width /
2 , clock -> allocation . height / 2 ) 5 ;
9 :
10 : cairo_arc ( cr , x , y , radius , 0 , 2 * M_PI );
11 : cairo_stroke ( cr );
12 :
13 : cairo_arc ( cr , x , y , 4 , 0 , 2 * M_PI );
14 : cairo_stroke ( cr );
15 :
16 : // rysowanie ramki zegara
17 :
18 : for ( i = 0 ; i < 12 ; i ++) {
19 : cairo_save ( cr );
20 :
21 : if ( i % 3 == 0 ) {
22 : tmp = 0.2 * radius ;
23 : }
24 : else {
25 : tmp = 0.1 * radius ;
26 : cairo_set_line_width ( cr , 0.5 *
cairo_get_line_width ( cr ));
27 : }
28 :
29 : cairo_move_to ( cr ,
30 : x + ( radius - tmp ) * cos ( i * M_PI / 6 ) ,
31 : y + ( radius - tmp ) * sin ( i * M_PI / 6 ));
32 : cairo_line_to ( cr ,
33 : x + radius * cos ( i * M_PI / 6 ) ,
34 : y + radius * sin ( i * M_PI / 6 ));
35 : cairo_stroke ( cr );
36 : cairo_restore ( cr );
37 : }
38 : cairo_stroke ( cr );
39 :
40 : my_draw_text ( cr , x , y + 25 , "Made by YOU!" );
41 : cairo_stroke ( cr );
42 :
43 : _h = GTK_CLOCK ( clock )-> h - 3 ;
44 :
45 : cairo_move_to ( cr , x , y );
46 : cairo_line_to ( cr ,
47 : x + ( radius * 0.4 ) * cos ( _h * (( 2 * M_PI ) / 12 )) ,
48 : y + ( radius * 0.4 ) * sin ( _h * (( 2 * M_PI ) / 12 )));
49 : cairo_stroke ( cr );
50 :
51 : // rysowanie pozosta ł ych wskaz ó wek
52 : }
Testujemy nowy widget
Nasz widget jest już gotowy do użycia,
więc warto go przetestować w aplikacji.
Ponieważ kompilacja źródeł widgetu prze-
biega w sposób normalny, więc możemy
utworzyć bibliotekę statyczną, która bę-
dzie dołączana do naszego programu. Oczy-
wiście, możemy też kompilować plik gtk_
clock.c samodzielnie we własnej aplikacji.
Utworzenie widgetu i dodanie go do
własnej aplikacji jest typowe dla bibliote-
ki GTK+. Na początek deklarujemy zmien-
ną:
GtkWidget *clock;
W programie tworzymy nowy obiekt:
clock = gtk_clock_new ();
Pozostaje tylko dodać nowo utworzony
widget do innego kontenera np. do okna:
gtk_container_add
(GTK_CONTAINER (win), clock);
W ten sposób dodajemy dowolny inny wid-
get GTK+ do aplikacji, ale bardziej intere-
sujące jest wykorzystanie programu Glade.
Program ten nie pozwala na bezpośrednie
dodanie widgetu GtkClock , ale jego autorzy
zostawili furtkę, którą można wykorzystać,
aby dołączyć do aplikacji dowolny widget,
nieznany programowi Glade.
Rysunek 2 prezentuje dołączenie do ok-
na nowego nieznanego widgetu. W Glade
tego typu widget jest reprezentowany przez
kontrolkę o nazwie Custom . Sposób budowy
tego typu kontrolki leży w gestii programi-
sty, bowiem, jak widać na wspomnianym
rysunku, najważniejsze to podanie nazwy
(w naszym przypadku create_my_clock )
specjalnej funkcji, która jest odpowiedzialna
za utworzenie kontrolki. Funkcja ta zosta-
76 kwiecień 2006
439113691.041.png 439113691.042.png 439113691.043.png
 
439113691.044.png 439113691.045.png 439113691.046.png 439113691.048.png 439113691.049.png 439113691.050.png 439113691.051.png
 
Zgłoś jeśli naruszono regulamin