Eine der größten Stärken von Perl ist das CPAN [2], das Comprehensive Perl Archive Network. Dieses weltweite Netzwerk hat sich etabliert, um Perl-Programmierern die schier unermessliche Anzahl von Modulen für ihre Sprache zugänglich zu machen. Neben kleinen Bibliotheken und nützlichen Kleinigkeiten finden sich auch Wrapper für ausgewachsene Werkzeuge zur Programmierung grafischer Oberflächen. Dabei dürfen Gtk+ und GNOME natürlich nicht fehlen und daher gibt es Gtk-Perl von Kenneth Albanowski. Seine Finger auf das benötigte Modul legen kann man mit der einfachen Installationsprozedur, wie man sie von Perl über das CPAN gewohnt ist, wie folgt:
# perl -MCPAN -e shell
cpan shell CPAN exploration and modules installation (v1.59)
ReadLine support enabled
cpan> install Gtk-Perl
Gtk-Perl liegt zurzeit in der Version 0.7004 vor und enthält die Unterstützung für GNOME. Die Version von CPAN ist unter Umständen nicht die aktuellste; es lohnt sich daher, einen Blick auf [3] zu werfen und zu schauen, ob es etwas Neues gibt.
Listing1: hallofrosch.pl
|
1: #!/usr/bin/perl -w
2:
3: use strict;
4: use Gnome;
5:
6: my $APPNAME = 'Hallo Froschi!';
7:
8: init Gnome $APPNAME;
9:
10: my $app = new Gnome::App $APPNAME, $APPNAME;
11:
12: my $button = new Gtk::Button "Hallo Froschi!";
13: $app -> set_contents ($button);
14:
15: show_all $app;
16:
17: main Gtk;
|
Erste Schritte
Normalerweise bevorzuge ich Python, um mir kleine Gtk+- oder GNOME-Programme zusammenzuhacken, Perl ist auf meinen Systemen für administrative Aufgaben abgestellt. Es liegt also nahe, mit einem kleinen Hallo-Frosch-Programm anzufangen, um erst mal das Vertrauen der Sprache zu gewinnen.
Listing 1 zeigt ein Beispiel für ein derartiges Programm, und der zugehörige Screenshot ist in Abbildung 1 zu sehen. So weit gibt es sowohl für Perl- als auch für GNOME-Programmierer keine besonderen Überraschungen. Das Modul wird in Zeile 4 eingebunden und die Applikation dann in Zeile 8 initialisiert.
Die Applikation ist in GNOME ein eigenes Widget, das im Gegensatz diverse Zusatzaufgaben übernimmt. So lassen sich beispielsweise leicht mehrere Instanzen ein und derselben Applikation erstellen. Das schlägt sich in Zeile 10 in der Erstellung dieses Widgets nieder. Auf die gleiche Weise wird ein Button erzeugt, in das Fenster eingefügt und dann die ganze Applikation angezeigt. In Zeile 17 erhält die Programmschleife gtk_main die Kontrolle. Bis hierher sieht das einem Hello World in C schon ziemlich ähnlich, mit dem Unterschied, dass Perl wieder seine Magie ausübt, dem Programmierer wesentlich weniger Tastenanschläge abzuverlangen.
Wenn sich ein aufmerksamer und schon in der Materie bewanderter Leser die Frage stellt, warum in der Titelzeile der Screenshots der Programmname nicht erscheint, obwohl er durch Zeile 10 gesetzt werden müsste: Das liegt an meinem missgebildeten Sawfish-Thema.
Abb. 1: Hallo Froschi! Hallo HalloFroschi!
Signale und Ereignisse
Gtk+ ist ein ereignisbasiertes Widget-Set, aber Ereignisse kommen hier wesentlich zu kurz. Tritt ein Ereignis auf, wird ein dazu korrespondierendes Signal ausgesandt, auf das eine durch den Programmierer festgelegte Funktion reagieren kann. Eine solche Funktion nennt man Callback. Soll das Programm in Listing 1 beendet werden, ist zum Beispiel das Einfügen des folgenden Codes zwischen den Zeilen 12 und 13 Standard:
signal_connect $button 'clicked', sub { Gtk -> main_quit;
print "Tschüs Froschi!n";
return 0; };
Wird durch den Button - die Schaltfläche, ach du meine Güte - das Signal clicked ausgesandt, soll die besagte anonyme Funktion ausgeführt werden, die zur Beendung des Programms führt. Zu beachten ist, dass das Folgende nicht funktionieren kann:
signal_connect $button 'clicked', Gtk -> main_quit;
Wer nicht auf anonyme Funktionen zurückgreifen möchte, baut sich zum Beispiel eine Routine beenden. Schließlich gehört es zum guten Ton, für jedes Signal eigene Callbacks zu schreiben, zumal für solche, die das Programm beenden, denn so bleiben Möglichkeiten zum Aufräumen. Man referenziert die Routine folgendermaßen:
sub beenden {
print "Tschüs Froschi!n";
Gtk -> main_quit;
return 0;
}
# ...
signal_connect $button 'clicked',
Listing 2: bookman.pl
|
1: #!/usr/bin/perl -w
2:
3: use strict;
4: use Gnome;
5:
6: my $APPNAME = 'Book manager';
7: my $APPVERSION = '0.1.0';
8: init Gnome $APPNAME;
9:
10: sub beenden {
11: Gtk -> main_quit;
12: print "Bye bye.!n";
13: return 0;
14: }
15:
16: sub infobox {
17: my $about = new Gnome::About $APPNAME, $APPVERSION,
18: '(c) 2000 Thorsten Fischer', ['Thorsten Fischer@mapmedia.de>'],
19: 'Gtk-Perl Beispielcode für das Linux-Magazin.';
20: show $about;
21: }
22:
23: sub selektieren {
24: my ($clist, $row, $column, $event, @data) = @_;
25: my $text = $clist -> get_text ($row, $column);
26: print "Die Auswahl wurde in Zeile $row, Spalte $column getroffen.n";
27: print "Inhalt: $textn";
28: }
29:
30: my $app = new Gnome::App $APPNAME, $APPNAME;
31: signal_connect $app 'delete_event', &beenden
32:
33: $app -> create_toolbar (
34: {
35: type => 'item',
36: label => 'Open',
37: pixmap_type => 'stock',
38: pixmap_info => 'Open',
39: hint => 'Open book list',
40: },
41: {
42: type => 'item',
43: label => 'Exit',
44: pixmap_type => 'stock',
45: pixmap_info => 'Quit',
46: hint => "Quit $APPNAME",
47: callback => &beenden
48: }
49: );
50:
51: $app->create_menus (
52: {
53: type => 'subtree',
54: label => '_File',
55: subtree => [
56: {
57: type => 'item',
58: label => '_New',
59: pixmap_type => 'stock',
60: pixmap_info => 'Menu_New'
61: },
62: {
63: type => 'item',
64: label => '_Quit',
65: pixmap_type => 'stock',
66: pixmap_info => 'Menu_Quit',
67: callback => &beenden
68: }
69: ]
70: },
71: {
72: type => 'subtree',
73: label => '_Help',
74: subtree => [
75: {
76: type => 'item',
77: label => '_About...',
78: pixmap_type => 'stock',
79: pixmap_info => 'Menu_About',
80: callback => &infobox
81: }
82: ]
83: }
84: );
85:
86: my $appbar = new Gnome::AppBar 1, 1, 'user';
87: $appbar -> set_status ('Willkommen!');
88: $app -> set_statusbar ($appbar);
89:
90: my $sw = new Gtk::ScrolledWindow undef, undef;
91: $sw -> set_policy ('automatic', 'always');
92:
93: my @listentitel = ('Autor', 'Titel', 'ISBN');
94: my $liste = new_with_titles Gtk::CList (@listentitel);
95: $liste -> signal_connect ('select_row', &selektieren);
96:
97: my @buch1 = ('Larry Wall, et al', 'Programming Perl', 1565921496);
98: my @buch2 = ('Helmut Herold', 'Linux Unix Systemprogrammierung', 3827315123);
99: my @buch3 = ('Wiglaf Droste, Gerhard Henschel', 'Der Mullah von Bullerbü', 3894013524);
100: $liste -> append (@buch1);
101: $liste -> append (@buch2);
102: $liste -> append (@buch3);
103:
104: for (my $i = 0; $i < $liste -> n_columns; $i++) {
105: $liste -> set_column_width ($i, $liste -> optimal_column_width ($i) + 5);
106: }
107:
108: $sw -> add ($liste);
109:
110: $app -> set_contents ($sw);
111: $app -> set_default_size (640, 480);
112: show_all $app;
113:
114: main Gtk;
|