ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2004/gtk2.pod
Revision: 1.5
Committed: Tue May 18 00:22:26 2004 UTC (22 years, 5 months ago) by root
Branch: MAIN
Changes since 1.4: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.5 =encoding utf8
2    
3 root 1.1 =head1 Gtk+2 - ein erweiterbares GUI-Toolkit
4    
5     =head2 Abstract
6    
7 root 1.3 Gtk+2 (das {{G}}IMP {{T}}ool{{K}}it, Version 2) unterlief bei der
8     Entwicklung zu Version 2 tiefgreifende Änderungen. Das Typsystem wurde
9     stark abstrahiert, so daß Schnittstellen zu anderen Sprachen sich im
10     wesentlichen auf das Bereitstellen des Objektsystems beschränken.
11    
12     In diesem Dokument wird das Toolkit Gtk2 kurz vorgestellt, wobei Erfahrung
13     mit GUI-Programmierung vorausgesetzt wird. Im wesentlichen wird es jedoch
14     darum gehen, einige besondere Techniken vorzustellen sowie das Toolkit von
15     Perl aus selbst zu erweitern.
16 root 1.1
17     =head1 Teil 1 - Gtk+ als GUI-Baukasten
18    
19 root 1.3 =head2 Übersicht über die G-Module
20 root 1.1
21 root 1.3 Es gibt eine Menge Bibliotheken, deren Namen mit G anfängt und im
22     Dunstkreis von Gtk+ stehen. Vielleicht wäre es sinnvoll gewesen, eine neue
23     G-Hierarchie in Perl zu begründen, so muß man sich mit einer teilweise
24     nicht sehr logischen Namensgebung zurechtzufinden.
25    
26     =over 4
27    
28     =item Glib
29    
30     Glib ist die Schnittstelle zur C<libglib> (sowie zu C<libgobject>,
31     C<libgmodule> und C<libgthread>). Es bildet die Grundlage für das Objekt-
32     und Typ- und Signalsystem, bietet Hilfsfunktionen zum Umwandeln von
33     Dateinamen, Logging usf.
34    
35     Eine I<sehr> sauber geschriebene Bilbiothek, die auf GObject aufsetzt,
36     läßt sich praktisch ohne zusätzlichen Schnittstellencode nutzen: sobald
37     die entsprechenden Typen registriert wurden (geschieht meist in einer
38     Init-Funktion) kann man Objekte instantiieren und benutzen.
39    
40     =item Gtk2
41    
42     Dieses Modul ist eine Sammelstelle für diverse Bilbiotheken: neben
43     C<libgtk+> auch C<libgdk>, C<libgdk_pixbuf> und C<libpango>.
44    
45     Sie reicht für fast alle Anwendungen aus.
46    
47     =item Gtk2::GLExt, Gtk2::GladeXML, Gtk2::TrayIcon und Gtk2::Spell
48    
49     Bieten Integration von OpenGL, GladeXML, EggTryIcon und Spell-checking für
50     Text-Widgets.
51    
52     =item Gnome2
53    
54     Schnittstelle zur C<libgnome> und vielem mehr. Muss man nicht
55     benutzen, kann mir aber vorstellen, das sie für die Erstellung von
56     Gnome-Applikationen ganz nützlich sind :)
57    
58     =item Gnome2::Canvas, Gnome2::GConf, Gnome2::PanelApplet, Gnome2::Print,
59     Gnome2::Rsvg, Gnome2::VFS, Gnome2::Vte, Gnome2::Wnck.
60    
61     Jede Menge Gnoem-Zeugs.
62    
63     =back
64 root 1.1
65 root 1.4 =head2 Die Widgets von Gtk2 sind GObjekte
66 root 1.1
67 root 1.3 Wie jedes andere Toolkit auch, bietet Gtk2 eine Menge vorgefertigter
68     I<Widgets>: I<Buttons>, I<Labels>, I<Frames> und andere "einfache"
69     Widgets, aber auch komplexe, wie das I<Text>- (komplett in Unicode,
70     einbettbare Objekte) oder das I<TreeView>- (Listen und Bäume im
71     MVC-Modell) Widget.
72    
73     =begin latex
74    
75     \begin{figure}[h]\includegraphics{gtk2-textwidget.png}\label{Das Text-Widget}\end{figure}
76    
77     =end latex
78    
79 root 1.4 Alle diese Widgets sind sogenannte I<G-Objekte> (C<GObject>s), und haben
80     daher folgende Features:
81    
82     =over 4
83    
84     =item Eine Klasse
85    
86     Jedes GObject ist eine Instanz einer Klasse (C<GObjectClass>), eine Datenstruktur, die
87     Informationen über Methoden u.ä. speichert.
88    
89     =item Methoden
90    
91     Jedes GObjekt hat mindestens Methoden zum Erzeugen (C<constructor>)
92     und Zerstören (C<finalize>), setzen und lesen von Properties und eine
93     Spezialität von GObject - C<dispose>. Letzteres ist eine Art Anfrage an
94     ein Objekt, sich freiwillig aufzulösen.
95    
96     =item Signale
97    
98     =item Properties (Eigenschaften)
99    
100     =back
101 root 1.3
102 root 1.1 =head2 Properties und Signale
103    
104 root 1.4 =head2 Leben und sterben lassen: Wie man seine Objekte wieder loskriegt
105    
106     =head2 Informationen über Klassen zur Laufzeit abfragen
107 root 1.1
108 root 1.4 =head2 Beispiel: Session-Management
109 root 1.1
110 root 1.4 =head2 Beispiel: Glade
111 root 1.1
112     =head1 Teil 2 - Gtk+ als solide Grundlage für Eigenentwicklungen
113    
114     =head2 Perl-Objekte vs. Glib-Objekte
115 root 1.3
116     =head2 Objekte aus anderen Sprachen nutzen
117 root 1.1
118     mit einem objektorientiertem Design. Gtk+ selbst ist in C geschrieben,
119     es existieren jedoch Bindings für C++, Perl, Python und einige andere
120     Sprachen. Das Perl-Interface ist noch nicht vollkommen ausgereift,
121     ist aber schon hervorragend benutzbar und wird immer mehr eingesetzt
122     (z.B. für Administrationsfrontends in Debian GNU/Linux). Die Vorteile
123     von Gtk+ gegenüber Tk und anderen Toolkits ist die hervorragende
124     Integration{{}}: Perl-Widgets können von anderen Sprachen benutzt werden (z.B.
125     von C) und natürlich umgekehrt. Eigene Widgets können sehr einfach erzeugt
126     werden (im Gegensatz zu Tk), und die Gtk+-Bibliothek ist frei (im Sinne
127     der LGPL) -- auch auf anderen Betriebssystemen als UNIX.
128    
129     H1: Gtk
130    
131     C<Gtk> ist das Perl-Modul, das die Schnittstelle zur Gtk+-Bibliothek
132     bildet. Da die meisten Menschen "Gtk" sagen, wenn sie Gtk+ meinen, wird
133     die Perl-Schnittstelle meistens explizit "Gtk-Perl" genannt (genauso, wie
134     das Gimp-Modul meistens Gimp-Perl genannt wird).
135    
136     Zur Zeit bietet das Gtk-Modul auch Bindungen für Gnome und einige
137     andere Bibliotheken an, möglicherweise (das ist nicht sicher) werden
138     diese Module aber aufgetrennt werden: Gtk+ war ursprünglich das
139     {{G}}imp-{{T}}ool{{K}}it, und sowohl Gtk+ als auch Gimp sind {{kein}} Teil
140     des Gnome-Projektes und können deshalb ohne Gnome verwendet werden.
141    
142     H2: Ein einfaches Programm
143    
144     Hier ist ein ganz einfaches Gtk-Programm. Nichtsdestotrotz öffnet es schon ein Fenster:
145    
146     !block perl
147     use Gtk;
148    
149     Gtk->init;
150    
151     $main = new Gtk::Window;
152    
153     $main->show;
154     Gtk->main;
155     !endblock
156    
157     C<use Gtk;> sollte klar sein. Eine Eigenheit von Gtk+ ist es, daß es
158     zuerst explizit initialisiert werden muß (in einem Gnome-Programm würde
159     statt {{C:Gtk->init}} ein {{C:Gnome->init}} stehen), sonst gibt es jede Menge
160     Fehler.
161    
162     Der Aufruf C<new Gtk::Window> ist {{ein}} Weg, ein neues Fenster zu
163     erzeugen. Neue Gtk-{{Widgets}} sind Anfangs aber noch unsichtbar. Damit
164     sie angezeigt werden, muß zuerst die C<show>-Methode aufgerufen werden (es
165     gibt auch das entsprechende C<hide>).
166    
167     Das letzte, was unser Programm macht, ist, in die Hauptschleife von Gtk+
168     zu springen. Die Hauptschleife zeigt das Fenster und und -- wartet auf
169     Ereignisse{{}}:
170    
171     !import "hello1"; title="Das erste Fenster"
172    
173     Das Fenster ist natürlich leer und es wurden auch keine Reaktionen auf
174     Ereignisse. Die einzige Möglichkeit, das Programm zu beenden, ist es, es
175     zu "killen" (entweder C<xkill> oder z.B. C<SIGINT>).
176    
177     H2: Das Signalsystem von Gtk+
178    
179     Gtk+ setzt intern auf einer Bibliothek namens C<Gdk> (GNU Drawing ToolKit) auf, die
180     eine Schnittstelle auf niedriger Ebene zum jeweiligen Fenstersystem (X, Win32, BeOS...)
181     bildet. Diese Schnittstelle erzeugt Ereignisobjekte und reicht sie an Gtk+ weiter.
182    
183     Gtk+ verteilt diese Ereignisse an seine Widgets, indem es diesen Signale
184     schickt. Ein Signal ist z.B. eine Mausklick (C<clicked>) oder das
185     anklicken des "Fenster-Schließen"-Knopfes (C<delete_event>). Gtk+ kennt
186     aber auch eigene Signal, z.B. wenn ein Objekt zerstört wird (C<destroy>),
187     was einem Destruktor entspricht.
188    
189     Jeder Signal-Handler kann das Signal konsumieren, an andere Widgets
190     weiterreichen oder einfach ignorieren (wodurch es z.B. an das Vaterwidget
191     gelangt).
192    
193     Um eine Aktion an ein Signal zu binden, kann man die C<signal_connect>-Methode aufrufen:
194    
195     !block perl
196     $main = new Gtk::Window;
197    
198     $main->signal_connect(delete_event => sub { Gtk->main_quit });
199     !endblock
200    
201     Nun kann man den Schließknopf des Fensters betätigen, und das ausgelöste
202     Signal (C<delete_event>) führt zu einem Aufruf von {{C:Gtk->main_quit}}. Das
203     Beendet die Hauptschleife und damit das Programm.
204    
205     H2: Der erste Button
206    
207     Nun zu etwas mehr Aktion. Ein "Hello-World!"-Button muß her. Dies ist ganz einfach:
208    
209     !block perl
210     $button = new Gtk::Button "Hello, World!";
211     $main->add($button);
212    
213     $button->show;
214     !endblock
215    
216     Das einzig neue (neben der Erkenntnis, daß es auch C<Gtk::Button>s
217     gibt), ist der Aufruf von C<$main->add>. C<Gtk::Window> {{ist ein}}
218     C<Gtk::Container>, und erbt von diesem einige Methoden (unter anderem
219     C<add>).
220    
221     Das Fenster sieht nun so aus (nicht schön, aber es wird):
222    
223     !import "hello2"; title="Das Fenster -- mit Button!"
224    
225     Nun besetzen wir noch das C<clicked>-Ereignis mit einem überflüssigen Signal-Handler:
226    
227     !block perl
228     $button->signal_connect(clicked => sub { print "I was here!\n" });
229     !endblock
230    
231     H2: Vereinfachungen
232    
233     Das ganze Programm kann man (wenn man will) noch etwas einfacher
234     haben. Zuersteinmal: mir geht dieses dauernde {{C:$xxx->show}} auf
235     die Nerven. Weil es anderen wohl auch so ging, gibt es die Methode
236     C<show_all>. Sie ruft C<show> für das Widget und, rekursiv, für alle seine
237     Kinder auf. Man kann also alle (naja, zwei) C<show>-Aufrufe durch ein
238     einzelnes {{C:$main->show_all}} ersetzen.
239    
240     Die zweite Vereinfachung ist eher Geschmackssache: Man kann die Erzeugung
241     des Widgets und alle Initialisierungen (z.B. Signale) in einem Aufruf
242     erledigen:
243    
244     !block perl
245     use Gtk;
246    
247     init Gtk;
248    
249     $main = new Gtk::Widget "Gtk::Window",
250     -signal::delete_event => sub { Gtk->main_quit };
251    
252     add $main (new Gtk::Widget "Gtk::Button",
253     -label => "Hello, World!",
254     -signal::clicked => sub { print "I was here!\n" });
255    
256     $main->show_all;
257    
258     Gtk->main;
259     !endblock
260    
261     H2: Verschönerungen
262    
263     Um noch ein paar Features vorzustellen sollen noch ein paar Knöpfe
264     hinzukommen. Der "Hello-World"-Knopf soll in einen Rahmen. Unter den
265     Rahmen sollen zwei Knöpfe: der erste soll den Text an- und abschalten, der
266     zweite soll das Programm beenden:
267    
268     !import "hello-layout"; title="Schematisches Layout"
269     !import "hello31"; title="Das Programm beim Start"
270     !import "hello32"; title="Nach dem abschalten der Nachricht"
271    
272     Die Technik, Widgets an- und abzuschalten wird gerne für Dialoge in
273     der Art "Advanced Options >>" verwendet, um dem Benutzer mehr Optionen
274     anzubieten.
275    
276     Gtk+ bietet viele Arten von Layout-Managern. Grundsätzlich möchte es
277     aber das Layouten des Fensters gerne selbst übernehmen. Man {{kann}}
278     die Größe und Lage von Widgets selbst bestimmen, aber Gtk+ arbeitet
279     wesentlich besser, wenn man nur Hinweise gibt. Ein solcher Hinweis kann
280     in Form der C<Gtk::VBox> und C<Gtk::HBox>-Container geschehen. Diese
281     sind Rechtecke, die mehrere Widgets enthalten können, die vertikal oder
282     horizontal ausgerichtet werden.
283    
284     Das Hauptelement des Fensters soll also eine C<Gtk::VBox> werden. Oben
285     soll eine C<Gtk::Frame> stehen, und im unteren Teil soll eine C<Gtk::HBox>
286     mit den "Bedienelementen" sein (Eine C<Gtk::Box> kann durchaus auch mehr
287     als zwei Widgets enthalten). Die VBox wird einfach erzeugt mit:
288    
289     !block perl
290     add $main (my $vbox = new Gtk::Widget "Gtk::VBox",
291     homogeneous => 0,
292     spacing => 5,
293     border_width => 5);
294     !endblock
295    
296     Eine C<Gtk::Box> ist C<homogeneous>, wenn alle Widgets die gleiche Größe
297     haben. Unsere VBox soll das {{nicht}} sein, die C<Gtk::HBox> dagegen
298     schon. Dann wird eine C<Gtk::Frame> erzeugt, in die das C<Gtk::Label> mit
299     dem "Hello, World!" gepackt wird (der Layoutvorgang wird auch "packen"
300     genannt, da die Widgets dabei in den verfügbaren Raum "eingepackt
301     werden").
302    
303     !block perl
304     # Message-Frame:
305     add $vbox (my $frame = new Gtk::Frame "A Message:");
306    
307     # Message-Label:
308     add $frame (my $label = new Gtk::Label "Hello, World!");
309     !endblock
310    
311     Die horizontale Box für die Knöpfe wird mit einem vereinfachten
312     Konstruktor (statt dem allgemeinen {{C:Gtk::Widget->new}}) erzeugt, der
313     nur zwei Argumente ("homogen" und "Abstand") akzeptiert.
314    
315     !block perl
316     add $vbox (my $hbox = new Gtk::HBox 1,5);
317     !endblock
318    
319     Das Interessanteste an dem Programm ist zweifellos der Umschaltknopf,
320     der die Nachricht an- und abschaltet. Dazu bedienen wir uns eines
321     C<Gtk::ToggleButton>s, der zwei Zustände (aktiv und inaktiv) besitzt:
322    
323     !block perl
324     add $hbox (new Gtk::Widget "Gtk::ToggleButton",
325     label => "Message Shown",
326     active => 1,
327     signal::clicked => sub {
328     $label->visible
329     ? $label->hide
330     : $label->show;
331     });
332     !endblock
333    
334     Hier ist das gesamte Programm:
335    
336     !block perl
337     use Gtk;
338    
339     init Gtk;
340    
341     $main = new Gtk::Widget "Gtk::Window",
342     -signal::delete_event => sub { Gtk->main_quit };
343    
344     add $main (my $vbox = new Gtk::Widget "Gtk::VBox",
345     homogeneous => 0,
346     spacing => 5,
347     border_width => 5);
348    
349     # Message-Frame:
350     add $vbox (my $frame = new Gtk::Frame "A Message:");
351    
352     # Message-Label:
353     add $frame (my $label = new Gtk::Label "Hello, World!");
354    
355     # Button-Bar
356     add $vbox (my $hbox = new Gtk::HBox 1,5);
357    
358     # Toggle-Button
359     add $hbox (new Gtk::Widget "Gtk::ToggleButton",
360     label => "Message Shown",
361     active => 1,
362     signal::clicked => sub {
363     $label->visible
364     ? $label->hide
365     : $label->show;
366     });
367    
368     # Close Button
369     add $hbox (new Gtk::Widget "Gtk::Button",
370     label => "OK",
371     signal::clicked => sub { main_quit Gtk });
372    
373     $main->show_all;
374    
375     Gtk->main;
376     !endblock
377    
378     H1: Eine Widget-Demo
379    
380     Als Abschluß folgt noch ein Screenshot, bei dem ich mich bemüht habe,
381     die wichtigsten (schon verfügbaren) Widgets alle auf einen Bildschirm
382     zu bekommen (das Gtk-Perl-Demoprogramm, C<Gtk/samples/test.pl> war sehr
383     hilfreich ;)
384    
385     Natürlich kann man jederzeit auch eigene Widgets programmieren...
386    
387     !import "screenshot"; title="Der mega-unübersichtliche Screenshot"
388    
389    
390    
391    
392