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

# User Rev Content
1 root 1.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