1
|
- Einführung in die Erstellung
- grafischer Oberflächen
- mit Perl / Tk
- von Christian Dühl
|
2
|
- Grafische Oberflächen bestehen aus verschiedenen Fenster-Elementen,
sogenannten Widgets, die zur Information des Anwenders oder zur
Interaktion mit dem Anwender dienen.
- Diese Widgets reichen von der Anzeige eines einfachen Wortes bis zu
Textfeldern, die schon viele Eigenschaften eines Editors aufweisen und
zu mächtigen vektororientierten Zeichenflächen.
|
3
|
- Rechts sieht man das Optionenmenü von Powerpoint, folgende Widgets
lassen sich erkennen:
- Texteingabefelder (Entrys)
- Überschriften (Label)
- Auswahlfelder (Checkboxen)
- Rahmen (Frames)
- Schalter (Buttons)
- Reiter (NoteBooks)
|
4
|
- Bei grafischen Oberflächen hat das Programm keine lineare
Handlungssteuerung, wie man es von der „normalen“ Programmierung her
gewohnt ist. Das liegt daran, dass man dem Benutzer nicht die
Reihenfolge seiner Eingaben vorgeben möchte. Der Benutzer muss etwa im
Dialog auf der vorigen Folie nicht von oben nach unten seine Wünsche eingeben,
sondern kann auf ein beliebiges Widget klicken bzw. Text in beliebige
Eingabefelder eintragen.
- Diese Aktionen des Benuztzers nennt man Ereignisse („Events“) und der
Programmablauf ist nun ereignisgesteuert, das heißt, dass das Programm
auf bestimmte Ereignisse reagiert. Um dies tun zu können, gibt es eine
Schleife, die immer wieder durchlaufen wird, und in der auftretende
Ereignisse (vom Benutzer oder anders ausgelöst) behandelt werden.
- Diese Ereignisschleife wird von Perl/Tk bereitgestellt und kann mit dem
Befehl MainLoop()aufgerufen werden.
|
5
|
- Während solche Funktionen ablaufen, reagiert die Oberfläche nicht auf
Benutzereingaben. Normalerweise ist dies nicht schlimm, wenn nach dem
Druck auf etwa den Ok-Button kurz etwas gemacht wird und der Dialog dann
beispielsweise verschwindet.
- Sollte man längere Berechnungen durchführen, so kann man dies der
Oberfläche vorher mitteilen (dafür gibt es die Methoden Busy und Unbusy).
Dann wird unter anderem ein Wartecursor angezeigt.
- Sehr lange Wartezeiten sollte man dann mit einem Fortschrittsbalken oder
ähnlichem „unterhaltsam“ gestalten.
- Nun kommen wir zum ersten Perl/Tk-Programm.
|
6
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- my $mw = MainWindow->new();
- $mw->Label(-text => 'Hallo Welt')
- ->pack();
- MainLoop();
|
7
|
- Wenn man mal die „Vorrede“ (Shebang, Pragmas und use Tk;) und den Aufruf
der MainLoop weglässt, bleiben nur zwei Anweisungen übrig.
- my $mw = MainWindow->new();
- Damit wird ein neues Objekt vom Typ MainWindow erzeugt. Mindestens ein
solches Objekt wird in jedem Perl/Tk-Programm gebraucht. Mit
- $mw->Label(-text =>
'Hallo Welt')
->pack();
- wird eine Überschrift (Label) erzeugt, die den Text „Hallo Welt“
anzeigt. Genauer gesagt wird ein Label-Objekt erzeugt. Hinterher wird
noch die Methode pack des erzeugten Objektes aufgerufen. Dann wird das
Objekt wieder vergessen. Man könnte es mit „my $label =“ vorweg
„einfangen“, aber es wird hier nicht weiter benötigt.
- Die Methode pack() packt ein Widget ins erzeugende Fenster (oder
Rahmen), hier ins Hauptfenster.
Dabei kann man nähere Angaben machen, wie das Objekt eingefügt werden
soll. Die Darstellung hängt sehr davon ab, in welcher Reihenfolge die
Objekte gepackt werden.
|
8
|
- pack: Der Standardgeometriemanager, man umgibt Gruppen von Widgets mit
(meist unsichtbaren) Rahmen, um diese gemeinsam anzuordnen.
- grid: Ein Geometriemanager für tabellenartige Fenster.
- place: Ein Geometriemanager zur freien Platzierung von Widgets. Mit
diesem Manager können Widgets auch überlappt dargestellt werden.
|
9
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- my $mw = MainWindow->new();
- $mw->Button(-text =>
'Klick mich',
- -command => sub {
$mw->destroy() },
- )
- ->pack();
- MainLoop();
|
10
|
- Mit den Zeilen
- $mw->Button(-text => 'Klick mich',
-command
=> sub { $mw->destroy() },
)
->pack();
- wird ein Schalter-Objekt (Button) erzeugt und gepackt. Der Schalter
bekommt die Aufschrift „Klick mich“ und außerdem wird über -command eine
sogenannte Callback-Funktion hinterlegt, die aufgerufen wird, wenn der
Schalter ausgelöst wird.
- Im Beispiel ist die Callback-Funktion eine Closure, man könnte statt sub
{...} auch eine Referenz zu einer benannten Funktion angeben, etwa so:
- -command =>
\&beenden
- Wieder könnte man das Schalter-Objekt mit „my $schalter =“ vor der
obigen Zeile für die spätere Verwendung abspeichern, aber das ist hier
noch nicht nötig.
|
11
|
- -option => Anweisung ist
typischer Tk-Stil um Parameter festzulegen. Hier ein paar
Widget-Optionen, die man häufiger anwendet:
- Widget-Option mögliche Werte Bedeutung
- -anchor "n", "ne", "e", "se",
"s", "sw", "w", Der Text wird an dieser
Position verankert. "nw" oder "center "
- -background Farbe (etwa 'SeaGreen3') Legt die Hintergrundfarbe des
Widgets fest.
- -borderwidth Betrag Ändert die Breite des Rahmens.
- -command Callback (Funktionsreferenz, anonyme Subroutine Aktiviert die
Callback-Funktion, wenn das
oder anonyme Liste, deren erstes Element Widget angeklickt
wird.
eine Funktionsreferenz und deren weitere Elemente
Parameter für diese Funktion sind):
\&myfunc
sub { ... }
[ \&myfunc, $arg1,
$arg2, \@arg3 ]
- -height Betrag (in Pixeln oder Zeilen) Ändert die Höhe des Widgets.
- -width Betrag (in Pixeln oder Zeichen) Ändert die Breite des Widgets.
- -justify "left", "right" oder
"center“ Ausrichtung von mehrzeiligen Text.
- -relief "flat", "groove", "raised",
"ridge", Ändert den Kantentyp.
"sunken" oder "solid "
- -state "normal", "disabled" oder "active "
Der Status des Widgets.
- -text "Text " Der Textstring, der im Widget angezeigt wird.
- -textvariable Variablenreferenz: \$text Wie -text , nur das sich der
Text ändert,
wenn die Variable $text sich ändert.
- -title "Titel" Gibt dem Widget einen Titel.
|
12
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- my $mw = MainWindow->new();
- $mw->Entry()->pack();
- MainLoop();
|
13
|
- Mit der Zeile
- $mw->Entry()->pack();
- wird ein Eingabefeld-Objekt (Entry) erzeugt und gepackt. In diesem
Eingabefeld können einzeilige Eingaben des Benutzers entgegengenommen
werden.
- Man kann es auch beim Start des Programms schon mit Text vorbelegen, den
der Benutzer dann ggf. ändern kann.
- Möchte man später abfragen, was der Benutzer in das Eingabefeld
eingetragen hat, so kann man dazu die Methode get verwenden. Dazu muss
man das Eingabefeld bei der Erzeugung aber in einer Variablen
abspeichern:
my $entry = $mw->Entry()->pack();
Dann kann man den Inhalt mit
my $input = $entry->get();
ermitteln.
- Alternativ kann man beim Erzeugen des Eingabefeldes mit
-textvariable =>
\$text
eine (vorher definierte) Variable an das Eingabeelement binden.
Ändert man den Inhalt der Variablen, so ändert sich der angezeigte Text
und umgekehrt.
|
14
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- my $mw = MainWindow->new();
- my $f1 = $mw->Frame(-relief
=> 'sunken',
- -width => '50',
- -height => '50',
- -borderwidth
=> '1',
- )
- ->pack();
- $f1->Scale(-from => 0,
- -to => 100,
- -orient =>
"vertical",
- -label => "Schieb mich",
- )
- ->pack();
- MainLoop();
|
15
|
- Mit den Zeilen
- my $f1 = $mw->Frame(-relief => 'sunken',
-
-width => '50',
-
-height => '50',
-
-borderwidth => '1',
- )
- ->pack();
- wird ein Rahmenelement (Frame) $f1 mit den Maßen 50x50 Pixeln und der
Randbreite 1 Pixel erzeugt und in
das Hauptfenster $wm gepackt.
- Es hat die Reliefart „sunken“. Außerdem gibt es noch die Reliefarten raised,
flat, ridge, solid und groove (vergleiche perldoc Tk::options). Diese
Reliefarten kann man auch bei anderen Widgets setzen, die Defaultwerte
der Reliefart sind von Widget zu Widget unterschiedlich.
|
16
|
- Mit den Zeilen
- $f1->Scale(-from => 0,
-to => 100,
-orient =>
"vertical",
-label => "Schieb mich",
)
->pack();
- wird ein Skalenelement erzeugt und in den Rahmen $f1 gepackt. Das
Skalenelement hat den Wertebereich von 0 bis 100, ist vertikal
ausgerichtet und trägt das Label „Schieb mich“.
- Nun kommen wir zu einem etwas komplexeren Programm, an dem einige
weitere Widgets und das generelle Umgehen mit und das Auslesen von
Widgets erläutert wird.
|
17
|
|
18
|
|
19
|
|
20
|
|
21
|
|
22
|
|
23
|
- Und so sieht das Programm dann aus. Der Benutzer kann mit Checkbuttons
(jeder einzelne wählbar oder nicht wählbar), Radiobuttons (nur eine
Auswahl pro Gruppe) und der Listbox (hier: mehrere Einträge gleichzeitig
auswählbar) seine „Bestellung“ zusammenklicken und dann per OK-Button
absenden.
|
24
|
- Sahne : ja
Extrawaffel: ja
Streusel :
Zartbitterabrieb
Sauce :
Schokoladensauce
Vanille
Schokolade
Malaga
Wallnuss
weiße Schokolade
- Aber natürlich könnte hier auch etwas anderes passieren, etwa die
Bestellung per E-Mail an den nächsten Eisladen zu verschicken oder
dergleichen.
|
25
|
- Hier tauchten nun zum ersten Mal Optionen der Methode pack auf. Etwa
beim Schalter:
- pack(-side => 'bottom',
- -expand => 0,
- -fill => 'none',
- -ipadx => 20,
- -pady => 2,
- );
- pack-Option mögliche Werte Bedeutung
- -side "left", "right", "top" oder
"bottom" Platziert das Widgetrechteck an die angegebene
Seite
des Fensters oder Frames.
- -fill "none", "x", "y" oder
"both" Das Widgetrechteck breitet sich in die
angegebene
Richtung aus.
- -expand 1 oder 0 Das Widget füllt den Platz im Widgetrechteck
aus
(oder nicht).
- -ipadx Betrag in Pixeln Definiert einen horizontalen Abstand um das
Widget
- (dabei wird es um 2xBetrag in horizontaler Richtung
vergrößert).
- -ipady Betrag in Pixeln Definiert einen vertikalen Abstand um das
Widget
(dabei wird es um 2xBetrag in vertikaler Richtung
vergrößert).
- -padx Betrag Setzt links und rechts je Betrag Pixel Polster ein.
- -pady Betrag Setzt oben und unten je Betrag Pixel Polster ein.
- -anchor "n", "ne", "e", "se",
"s", "sw", "w", "nw“ Verankert das
Widget in seinem Rechteck an der
oder "center“ angegebenen Stelle.
|
26
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- my $mw = MainWindow->new();
- my $box = $mw->Scrolled('Listbox',
-
-scrollbars => 'oe',
-
-height => 5,
- )
-
->pack(-side =>
'left',
- -fill => 'both',
-
-expand => 1,
- );
- $box->insert('end', $_)
- for qw(Eins Zwei Drei Vier
Fünf Sechs Sieben Acht Neun Zehn);
- MainLoop();
|
27
|
- Mit den Zeilen
- my $box = $mw->Scrolled('Listbox',
-scrollbars => 'oe',
-height => 5,
)
- wird eine Listbox erzeugt, die über einen optionalen „östlichen“ Rollbalken
(Scrollbar) verfügt und fünf Zeilen hoch ist. Mit
- $box->insert('end',
$_)
for qw(Eins Zwei
Drei Vier Fünf Sechs
Sieben Acht
Neun Zehn);
- werden nacheinander ans Ende der Listbox zehn Werte eingefügt. Da die
Listbox nur fünf Zeilen hoch ist, wird der Rollbalken benötigt (und
deshalb angezeigt).
|
28
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- my $mw = MainWindow->new();
- my $c1 = $mw->Canvas(-width
=> '350',
- -height =>
'350',
- )
- ->pack();
- $c1->createLine( 25, 175, 325, 175,
- -arrow =>
'last', );
- $c1->createText( 335, 175,
- -fill => 'blue',
- -text => 'X', );
- $c1->createLine(175, 325, 175,
25,
- -arrow =>
'last', );
- $c1->createText(175, 15,
- -fill => 'darkgreen',
- -text => 'Y',
- );
- MainLoop();
|
29
|
- Mit den Zeilen
- my $c1 = $mw->Canvas(-width => '350',
-height => '350',
)
- wird eine Canvas erzeugt, welche 350x350 Pixel groß ist. Dann werden mit
createLine und createText x-, y-Achse und Achsenbeschriftungen erzeugt:
- $c1->createLine( 25, 175,
325, 175,
-arrow
=> 'last', );
$c1->createText(
335, 175,
-fill => 'blue',
-text => 'X', );
|
30
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- my $mw = MainWindow->new();
- $mw->Button(-text =>
'Exit',
- -command => [$mw
=> 'destroy'],
- )
- ->pack(-side => 'bottom');
- $mw->Scrolled('Text',
- -scrollbars =>
'osoe',
- -wrap => 'none',
- )
- ->pack(-expand => 1,
- -fill => 'both',
- );
- MainLoop();
|
31
|
- Mit den Zeilen
- $mw->Scrolled('Text',
-scrollbars => 'osoe',
-wrap =>
'none',
)
- wird ein Textelement erzeugt, welches rechts und unten über optionale
Scrollbalken verfügt. Der Text wird nicht umgebrochen.
- Der Exit-Button wird zuerst eingesetzt, damit er auch noch zu sehen ist,
wenn das Fenster stark verkleinert wird. Damit er trotzdem unter dem
Text-Widget landet, wird er mit
-side =>
'bottom'
gepackt.
|
32
|
- #!/usr/bin/perl
- use strict;
- use warnings;
- use Tk;
- use Tk::NoteBook;
- my $mw = new MainWindow;
- my $nb = $mw->NoteBook()->pack();
- my $page1 = $nb->add('PageID-1',
- -label =>
'Reiter Eins', );
- my $page2 = $nb->add('PageID-2',
- -label =>
'Reiter Zwei', );
- $page1->Label(-text => 'In Seite 1')->pack();
- $page2->Label(-text => 'In Seite 2')->pack();
- MainLoop();
|
33
|
- Mit den Zeile
- my $nb = $mw->NoteBook()->pack();
- wird ein Reiterelement (NoteBook) erzeugt und gepackt. In diesem werden
nun mit
- my $page1 = $nb->add('PageID-1',
-label => 'Reiter Eins', );
my $page2 = $nb->add('PageID-2',
-label => 'Reiter Zwei', );
- zwei Seiten angelegt mit den Reitertiteln „Reiter Eins“ und „Reiter
zwei“. In die Seiten wird nun noch je ein Label gesetzt:
- $page1->Label(-text =>
'In Seite 1')->pack();
$page2->Label(-text
=> 'In Seite 2')->pack();
|
34
|
- Man kann seinem Perl/Tk-Programm ein Menü hinzuzufügen, das man wie man
es unter Windows gewöhnt ist, mit Alt+Buchstabe aufrufen und mit Maus
und Tastatur darin navigieren kann. Einzelnen Menüpunkten kann man dabei
Tastenkürzel zuordnen, die auch im Menü angezeigt werden.
- Das Beispielprogramm menu.pl ist ziemlich lang, deshalb gehe ich
zunächst auf den wichtigen Punkt, das Menü ein.
- Das gesamte Programm kopiere ich unkommentiert auf eine ausgeblendete
Folie für alle, die sich diesen Vortrag selbst ansehen.
|
35
|
- 1.) Menü (Menubar) erstellen:
my $menu = $mw->Menu(-type
=> 'menubar');
- 2.) Dem Fensterwidget dieses Menü zuweisen:
$mw->configure(-menu
=> $menu);
- 3.) Eigentliche Menüs in der Menubar eintragen:
$menu->cascade(-label => 'Datei',
-underline => 0,
);
$menu->cascade(-label => 'Bearbeiten',
-underline => 0,
);
$menu->separator();
$menu->cascade(-label => 'Hilfe',
-underline => 0,
);
|
36
|
4.) Die einzelnen
Untermenüs definieren:
my $menu_datei = $menu
->Menu(-menuitems =>
[
[
'command' => 'Datei
neu',
-command =>
\&datei_neu,
-accelerator => 'Ctrl-N',
-underline => 6,
],
..........
'-',
[
'command' =>
'Beenden',
-command =>
\&tk_ende,
-accelerator => 'Ctrl-B',
-underline => 0,
],
],
);
- 5.) Untermenü in Menubar eintragen:
$menu->entryconfigure('Datei',
-menu => $menu_datei);
- 6.) Bindungen zum Aufruf des Menüs erzeugen:
$mw->bind('<Alt-d>',
sub {$menu->postcascade('Datei');});
$mw->bind('<Alt-b>',
sub {$menu->postcascade('Bearbeiten');});
$mw->bind('<Alt-h>',
sub {$menu->postcascade('Hilfe');});
|
37
|
- So sieht das Programm aus:
|
38
|
- Empfehlenswertes Buch: „Mastering Perl/Tk“ von Steve Lidie und Nancy
Walsh.
- Perldoc: Zu allen Teilproblemen hilft einem meist ein entsprechender
perldoc aufruf weiter.
- Perl/Tk im Netz:
http://www.perltk.org/
- Onlinetutorial:
http://wiki.perl-community.de/bin/view/Wissensbasis/PerlTkTutorial
|