Perl-Programmierung: TK



Erstellen einer GUI

Bearbeiten

Zur Nutzung von Perl/Tk wird das Modul Tk benötigt.

  use Tk;
 
Beispiel 1

Eine neue Instanz wird mit der Funktion Mainwindow aufgerufen.

  my $Hauptfenster = MainWindow->new;

Zur Anzeige und Verwendung wird die Funktion MainLoop verwendet, deren Aufruf einfacher nicht sein kann.

  MainLoop;

Beispiel 1:

#!/usr/bin/perl
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->title ("Perl/Tk - Erste Schritte");
$mw->configure (-width=>"640",-height=>"480");
MainLoop;
#das wars schon

Als Gestaltungselemente grafischer Benutzeroberflächen stellt Tk sogenannte Widgets zur Verfügung. Sie sind der Kern der GUI-Programmierung mit Tk. Im Wesentlichen sind dies:

  • Das Frame-Widget zur Erzeugung von Containerwidgets. Diese sind unsichtbar, erlauben aber die Gruppierung diverser sichtbarer Widgets.
  • Das Menu-Widget und das Menubutton-Widget zur Erzeugung von Kopfzeilenmenüs.
  • Das Label-Widget zur Anzeige von Strings.
  • Das Entry-Widget zur Eingabe von Werten per Tastatur.
  • Das Text-Widget zur Anzeige und Bearbeitung von Texten.
  • Das Button-Widget als Befehlsschaltfläche.
  • Das Scrolled-Widget zur Erzeugung von Rollbalken.
  • Das Listbox-Widget zur Darstellung von mehreren Daten in einem Widget(in einer Box).

Geometriemanager

Bearbeiten

Um die Positionierung der Widgets zu erleichtern, stellt Tk Geometriemanager zur Verfügung.

  • pack verwendet die nächstmögliche Position innerhalb der Richtungen top, right, bottom, left.
  • grid positioniert Widgets innerhalb einer Tabelle anhand der übergebenen Tabellenposition
  • place gestattet eine Pixelgenaue Zuordnung.

Zu beachten ist, daß die direkt dem Hauptfenster oder einem Frame zugeordneten Widgets nicht mit vermischten Geometriemanagern angeordnet werden.

Der Geometriemanager pack erlaubt die Anordnung der Widgets nach Richtungen, top,left und bottom,right.

Ausserdem werden sogenannte Anker gesetzt, die bei einer Grössenänderung des Hauptfenster die Widgets wie gewünscht in Position halten:

  pack Optionen:
  
  -side   {'left','right','top','bottom'}       , wo
  -anchor {'n','ne','nw','w','sw','s','se','e'} , der Anker
 
Beispiel 2 - Hauptfenster
 
messageBox in Beispiel 2

Beispiel 2:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
#configure mit Fenstergroesse macht bei pack keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
$label1->pack (-side=>"left");
$entry1->pack (-side=>"left");
$button1->pack(-side=>"left");
        
sub cmd_button
{
   $mw->messageBox (-message=>"Programm wird beendet!");
   exit;
}
MainLoop;

Wenn man nun die Grösse des Fensters verändert, wandern die Widgets in einer Reihe links in der Mitte mit, was nicht immer erwünscht ist, darum werden zur Positionierung meist <Anchors> eingesetzt.

 
Beispiel 3 mit Ankern

Beispiel 3 mit Ankern:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
#configure mit Fenstergroesse macht bei pack keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
$label1->pack (-side=>"left",-anchor=>'nw'); #Nordwest Ecke
$entry1->pack (-side=>"left",-anchor=>'nw');
$button1->pack(-side=>"left",-anchor=>'nw');
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;

Interessant ist nun die Frage wie bekommt man den Exit Button unter das Label und das Eingabefeld (Entry). Dazu stellt das MainWindow Frames zur Verfügung, die eine weitere Untergliederung innerhalb des Fensters erlauben. Es wird nun ein Frame erzeugt und das Label und Entry mittels der Option -in von pack innerhalb des Frames positioniert, der wiederum innerhalb des Hauptfensters angeordnet ist.

=>Frames können mit den Optionen -width,-height und -bg wie jedes Fenster in Ihrer Groesse und Hintergrundfarbe geändert werde

  pack option:
   
  -in     {Frame} Widgets in ein untergeordnetes Fenster einsortien
  -expand {0,1}   1= Widget nimmt restliche Breite des Fensters ein
  -fill   {'x','y','none','both'} expansion in 'x','y','keine' oder 'beide' Richtung(en)
 
Beispiel 4

Beispiel 4:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
    
my $frame = $mw->Frame();
    
#configure mit Fenstergroesse macht bei pack keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
    
$frame->pack (-side=>"top");
     
#using -in
$label1->pack (-in=>$frame,-side=>"left",-anchor=>'nw'); #Nordwest Ecke
$entry1->pack (-in=>$frame,-side=>"left",-anchor=>'nw');
    
$button1->pack(-side=>"left",-fill=>"x",-expand=>1);
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;

Jetzt befindet sich der Button unterhalb des Frame mit dem Eingabefeld. Die Kombination der Optionen -fill und -expand führt dazu, das der Button die komplette Fensterbreite einnimmt.

Der Geometriemanager grid erlaubt die Anordnung der Widgets tabellarisch in Zellen, beginnend in der linken oberen Ecke mit -row=0 -column=0. Außerdem ist das verbinden von Zellen möglich mit -rowspan und -columnspan. Des Weiteren können Widgets wiederum in einer Zelle an Richtungen gebunden werden (-sticky). Die Untergliederung des in Layouts in Frames ist genauso wie in pack möglich.

  grid optionen:
  
  -row       {0..x} Nummer der Zeile
  -column    {0..x} Nummer der Spalte
  -rowspan   {2..x} Anzahl der zu zusammenzufassenden Zeilen
  -columnspan{2..x} Anzahl der zu zusammenzufassenden Spalten
  -sticky    {'n','s','e','w'} Kombinationen erlaubt (auch durch Komma getrennt} 
                               'ew' bzw. 'ns' zieht Widget auf komplette Zellenbreite (auch bei
                                              columnspan) bzw. Zellenhöhe (auch bei rowspan)

  -in               weitere Untergliederung mit Hilfe von Frames
 
Beispiel 5

Beispiel 5 mit grid:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
#configure mit Fenstergroesse macht bei grid keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
    
$label1->grid (-row=>0, -column=>0);
$entry1->grid(-row=>0, -column=>1); # eine Spalte weiter rechts
$button1->grid(-row=>0, -column=>2);
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;

Das ergibt das gleiche Bild wie mit pack. Wenn jetzt der Button in die nächste Zeile soll, dann wird für $button einfach -row geändert:

   $button->grid (-row=>1,-column=>0);

soll der Button in der Mitte stehen und vielleicht noch die gesamte Fensterbreite in Anspruch nehmen:

   $button->grid (-row=>1,-column=>0,-columnspan=>2,-sticky=>'ew'); #zwei Spalten überbrücken, Ost bis West

Mit Frames ändert sich eigentlich nicht viel, $label und $entry werden im Frame mit grid plaziert, $button braucht keine columnspan mehr, da nur eine Spalte vom Frame beansprucht wird:

 
Beispiel 6

Beispiel 6:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
my $frame = $mw->Frame();
#configure mit Fenstergroesse macht bei grid keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
    
$frame->grid (-row=>0,-column=>0);
    
$label1->grid (-in=>$frame,-row=>0, -column=>0);
$entry1->grid (-in=>$frame, -row=>0, -column=>1); # einer Spalte weiter rechts
$button1->grid(-row=>1, -column=>0,-sticky=>'ew');
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;