ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2004/gtk2.pod
Revision: 1.3
Committed: Sun Apr 25 02:31:05 2004 UTC (22 years, 5 months ago) by root
Branch: MAIN
Changes since 1.2: +69 -18 lines
Log Message:
*** empty log message ***

File Contents

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