ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2004/gtk2.pod
Revision: 1.1
Committed: Fri Apr 23 05:18:41 2004 UTC (22 years, 5 months ago) by root
Branch: MAIN
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     Gtk+2 (das {{G}}IMP {{T}}ool{{K}}it, Version 2)
6    
7     =head1 Teil 1 - Gtk+ als GUI-Baukasten
8    
9     =head2 Übersicht über die G-Bibliotheken
10    
11     Glib
12     Gtk2
13     Gnome2
14    
15     =head2 Der Umfang
16    
17     =head2 Properties und Signale
18    
19     =head3 Beispiel: Einfaches Session-Management
20    
21     =head2 Wie man seine Objekte wieder loskriegt
22    
23     =head2 Glade
24    
25     =head1 Teil 2 - Gtk+ als solide Grundlage für Eigenentwicklungen
26    
27     =head2 Perl-Objekte vs. Glib-Objekte
28    
29     mit einem objektorientiertem Design. Gtk+ selbst ist in C geschrieben,
30     es existieren jedoch Bindings für C++, Perl, Python und einige andere
31     Sprachen. Das Perl-Interface ist noch nicht vollkommen ausgereift,
32     ist aber schon hervorragend benutzbar und wird immer mehr eingesetzt
33     (z.B. für Administrationsfrontends in Debian GNU/Linux). Die Vorteile
34     von Gtk+ gegenüber Tk und anderen Toolkits ist die hervorragende
35     Integration{{}}: Perl-Widgets können von anderen Sprachen benutzt werden (z.B.
36     von C) und natürlich umgekehrt. Eigene Widgets können sehr einfach erzeugt
37     werden (im Gegensatz zu Tk), und die Gtk+-Bibliothek ist frei (im Sinne
38     der LGPL) -- auch auf anderen Betriebssystemen als UNIX.
39    
40     H1: Gtk
41    
42     C<Gtk> ist das Perl-Modul, das die Schnittstelle zur Gtk+-Bibliothek
43     bildet. Da die meisten Menschen "Gtk" sagen, wenn sie Gtk+ meinen, wird
44     die Perl-Schnittstelle meistens explizit "Gtk-Perl" genannt (genauso, wie
45     das Gimp-Modul meistens Gimp-Perl genannt wird).
46    
47     Zur Zeit bietet das Gtk-Modul auch Bindungen für Gnome und einige
48     andere Bibliotheken an, möglicherweise (das ist nicht sicher) werden
49     diese Module aber aufgetrennt werden: Gtk+ war ursprünglich das
50     {{G}}imp-{{T}}ool{{K}}it, und sowohl Gtk+ als auch Gimp sind {{kein}} Teil
51     des Gnome-Projektes und können deshalb ohne Gnome verwendet werden.
52    
53     H2: Ein einfaches Programm
54    
55     Hier ist ein ganz einfaches Gtk-Programm. Nichtsdestotrotz öffnet es schon ein Fenster:
56    
57     !block perl
58     use Gtk;
59    
60     Gtk->init;
61    
62     $main = new Gtk::Window;
63    
64     $main->show;
65     Gtk->main;
66     !endblock
67    
68     C<use Gtk;> sollte klar sein. Eine Eigenheit von Gtk+ ist es, daß es
69     zuerst explizit initialisiert werden muß (in einem Gnome-Programm würde
70     statt {{C:Gtk->init}} ein {{C:Gnome->init}} stehen), sonst gibt es jede Menge
71     Fehler.
72    
73     Der Aufruf C<new Gtk::Window> ist {{ein}} Weg, ein neues Fenster zu
74     erzeugen. Neue Gtk-{{Widgets}} sind Anfangs aber noch unsichtbar. Damit
75     sie angezeigt werden, muß zuerst die C<show>-Methode aufgerufen werden (es
76     gibt auch das entsprechende C<hide>).
77    
78     Das letzte, was unser Programm macht, ist, in die Hauptschleife von Gtk+
79     zu springen. Die Hauptschleife zeigt das Fenster und und -- wartet auf
80     Ereignisse{{}}:
81    
82     !import "hello1"; title="Das erste Fenster"
83    
84     Das Fenster ist natürlich leer und es wurden auch keine Reaktionen auf
85     Ereignisse. Die einzige Möglichkeit, das Programm zu beenden, ist es, es
86     zu "killen" (entweder C<xkill> oder z.B. C<SIGINT>).
87    
88     H2: Das Signalsystem von Gtk+
89    
90     Gtk+ setzt intern auf einer Bibliothek namens C<Gdk> (GNU Drawing ToolKit) auf, die
91     eine Schnittstelle auf niedriger Ebene zum jeweiligen Fenstersystem (X, Win32, BeOS...)
92     bildet. Diese Schnittstelle erzeugt Ereignisobjekte und reicht sie an Gtk+ weiter.
93    
94     Gtk+ verteilt diese Ereignisse an seine Widgets, indem es diesen Signale
95     schickt. Ein Signal ist z.B. eine Mausklick (C<clicked>) oder das
96     anklicken des "Fenster-Schließen"-Knopfes (C<delete_event>). Gtk+ kennt
97     aber auch eigene Signal, z.B. wenn ein Objekt zerstört wird (C<destroy>),
98     was einem Destruktor entspricht.
99    
100     Jeder Signal-Handler kann das Signal konsumieren, an andere Widgets
101     weiterreichen oder einfach ignorieren (wodurch es z.B. an das Vaterwidget
102     gelangt).
103    
104     Um eine Aktion an ein Signal zu binden, kann man die C<signal_connect>-Methode aufrufen:
105    
106     !block perl
107     $main = new Gtk::Window;
108    
109     $main->signal_connect(delete_event => sub { Gtk->main_quit });
110     !endblock
111    
112     Nun kann man den Schließknopf des Fensters betätigen, und das ausgelöste
113     Signal (C<delete_event>) führt zu einem Aufruf von {{C:Gtk->main_quit}}. Das
114     Beendet die Hauptschleife und damit das Programm.
115    
116     H2: Der erste Button
117    
118     Nun zu etwas mehr Aktion. Ein "Hello-World!"-Button muß her. Dies ist ganz einfach:
119    
120     !block perl
121     $button = new Gtk::Button "Hello, World!";
122     $main->add($button);
123    
124     $button->show;
125     !endblock
126    
127     Das einzig neue (neben der Erkenntnis, daß es auch C<Gtk::Button>s
128     gibt), ist der Aufruf von C<$main->add>. C<Gtk::Window> {{ist ein}}
129     C<Gtk::Container>, und erbt von diesem einige Methoden (unter anderem
130     C<add>).
131    
132     Das Fenster sieht nun so aus (nicht schön, aber es wird):
133    
134     !import "hello2"; title="Das Fenster -- mit Button!"
135    
136     Nun besetzen wir noch das C<clicked>-Ereignis mit einem überflüssigen Signal-Handler:
137    
138     !block perl
139     $button->signal_connect(clicked => sub { print "I was here!\n" });
140     !endblock
141    
142     H2: Vereinfachungen
143    
144     Das ganze Programm kann man (wenn man will) noch etwas einfacher
145     haben. Zuersteinmal: mir geht dieses dauernde {{C:$xxx->show}} auf
146     die Nerven. Weil es anderen wohl auch so ging, gibt es die Methode
147     C<show_all>. Sie ruft C<show> für das Widget und, rekursiv, für alle seine
148     Kinder auf. Man kann also alle (naja, zwei) C<show>-Aufrufe durch ein
149     einzelnes {{C:$main->show_all}} ersetzen.
150    
151     Die zweite Vereinfachung ist eher Geschmackssache: Man kann die Erzeugung
152     des Widgets und alle Initialisierungen (z.B. Signale) in einem Aufruf
153     erledigen:
154    
155     !block perl
156     use Gtk;
157    
158     init Gtk;
159    
160     $main = new Gtk::Widget "Gtk::Window",
161     -signal::delete_event => sub { Gtk->main_quit };
162    
163     add $main (new Gtk::Widget "Gtk::Button",
164     -label => "Hello, World!",
165     -signal::clicked => sub { print "I was here!\n" });
166    
167     $main->show_all;
168    
169     Gtk->main;
170     !endblock
171    
172     H2: Verschönerungen
173    
174     Um noch ein paar Features vorzustellen sollen noch ein paar Knöpfe
175     hinzukommen. Der "Hello-World"-Knopf soll in einen Rahmen. Unter den
176     Rahmen sollen zwei Knöpfe: der erste soll den Text an- und abschalten, der
177     zweite soll das Programm beenden:
178    
179     !import "hello-layout"; title="Schematisches Layout"
180     !import "hello31"; title="Das Programm beim Start"
181     !import "hello32"; title="Nach dem abschalten der Nachricht"
182    
183     Die Technik, Widgets an- und abzuschalten wird gerne für Dialoge in
184     der Art "Advanced Options >>" verwendet, um dem Benutzer mehr Optionen
185     anzubieten.
186    
187     Gtk+ bietet viele Arten von Layout-Managern. Grundsätzlich möchte es
188     aber das Layouten des Fensters gerne selbst übernehmen. Man {{kann}}
189     die Größe und Lage von Widgets selbst bestimmen, aber Gtk+ arbeitet
190     wesentlich besser, wenn man nur Hinweise gibt. Ein solcher Hinweis kann
191     in Form der C<Gtk::VBox> und C<Gtk::HBox>-Container geschehen. Diese
192     sind Rechtecke, die mehrere Widgets enthalten können, die vertikal oder
193     horizontal ausgerichtet werden.
194    
195     Das Hauptelement des Fensters soll also eine C<Gtk::VBox> werden. Oben
196     soll eine C<Gtk::Frame> stehen, und im unteren Teil soll eine C<Gtk::HBox>
197     mit den "Bedienelementen" sein (Eine C<Gtk::Box> kann durchaus auch mehr
198     als zwei Widgets enthalten). Die VBox wird einfach erzeugt mit:
199    
200     !block perl
201     add $main (my $vbox = new Gtk::Widget "Gtk::VBox",
202     homogeneous => 0,
203     spacing => 5,
204     border_width => 5);
205     !endblock
206    
207     Eine C<Gtk::Box> ist C<homogeneous>, wenn alle Widgets die gleiche Größe
208     haben. Unsere VBox soll das {{nicht}} sein, die C<Gtk::HBox> dagegen
209     schon. Dann wird eine C<Gtk::Frame> erzeugt, in die das C<Gtk::Label> mit
210     dem "Hello, World!" gepackt wird (der Layoutvorgang wird auch "packen"
211     genannt, da die Widgets dabei in den verfügbaren Raum "eingepackt
212     werden").
213    
214     !block perl
215     # Message-Frame:
216     add $vbox (my $frame = new Gtk::Frame "A Message:");
217    
218     # Message-Label:
219     add $frame (my $label = new Gtk::Label "Hello, World!");
220     !endblock
221    
222     Die horizontale Box für die Knöpfe wird mit einem vereinfachten
223     Konstruktor (statt dem allgemeinen {{C:Gtk::Widget->new}}) erzeugt, der
224     nur zwei Argumente ("homogen" und "Abstand") akzeptiert.
225    
226     !block perl
227     add $vbox (my $hbox = new Gtk::HBox 1,5);
228     !endblock
229    
230     Das Interessanteste an dem Programm ist zweifellos der Umschaltknopf,
231     der die Nachricht an- und abschaltet. Dazu bedienen wir uns eines
232     C<Gtk::ToggleButton>s, der zwei Zustände (aktiv und inaktiv) besitzt:
233    
234     !block perl
235     add $hbox (new Gtk::Widget "Gtk::ToggleButton",
236     label => "Message Shown",
237     active => 1,
238     signal::clicked => sub {
239     $label->visible
240     ? $label->hide
241     : $label->show;
242     });
243     !endblock
244    
245     Hier ist das gesamte Programm:
246    
247     !block perl
248     use Gtk;
249    
250     init Gtk;
251    
252     $main = new Gtk::Widget "Gtk::Window",
253     -signal::delete_event => sub { Gtk->main_quit };
254    
255     add $main (my $vbox = new Gtk::Widget "Gtk::VBox",
256     homogeneous => 0,
257     spacing => 5,
258     border_width => 5);
259    
260     # Message-Frame:
261     add $vbox (my $frame = new Gtk::Frame "A Message:");
262    
263     # Message-Label:
264     add $frame (my $label = new Gtk::Label "Hello, World!");
265    
266     # Button-Bar
267     add $vbox (my $hbox = new Gtk::HBox 1,5);
268    
269     # Toggle-Button
270     add $hbox (new Gtk::Widget "Gtk::ToggleButton",
271     label => "Message Shown",
272     active => 1,
273     signal::clicked => sub {
274     $label->visible
275     ? $label->hide
276     : $label->show;
277     });
278    
279     # Close Button
280     add $hbox (new Gtk::Widget "Gtk::Button",
281     label => "OK",
282     signal::clicked => sub { main_quit Gtk });
283    
284     $main->show_all;
285    
286     Gtk->main;
287     !endblock
288    
289     H1: Eine Widget-Demo
290    
291     Als Abschluß folgt noch ein Screenshot, bei dem ich mich bemüht habe,
292     die wichtigsten (schon verfügbaren) Widgets alle auf einen Bildschirm
293     zu bekommen (das Gtk-Perl-Demoprogramm, C<Gtk/samples/test.pl> war sehr
294     hilfreich ;)
295    
296     Natürlich kann man jederzeit auch eigene Widgets programmieren...
297    
298     !import "screenshot"; title="Der mega-unübersichtliche Screenshot"
299    
300    
301    
302    
303