ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/gtk.sdf
Revision: 1.1
Committed: Mon Mar 19 11:08:50 2001 UTC (25 years, 6 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Log Message:
*** empty log message ***

File Contents

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