Software-Engineering Martin Fabiani

Sitemap (Navigation ohne JavaScript)

Impressum: Martin Fabiani, Röderbergweg 104, D-60485 Frankfurt, Tel: +49 (69) 49084808, E-Mail: info (at) fabiani.net, USt-IdNr: DE217298609

Tips und Tricks zu Perl

Perl/Tk

 

Programm-schließen abfangen:

Wenn man auf ein Programm-Schließen-Ereignis (entweder durch <Alt><F4> oder Mausklick auf das X rechts oben nicht will, daß sich das Programm einfach beendet, sondern z.B. eine lästige Nachfrage ausgeben will (so auf die Art: Wollen Sie wirklich mein wunderschönes Programm verlassen???), dann könnte man dies folgendermaßen machen:


#! /usr/bin/perl
use warnings; use strict; use Tk; my $mw = MainWindow->new(); $mw->protocol('WM_DELETE_WINDOW', \&ExitApplication); MainLoop; sub ExitApplication { # Prepare dialog yes|no my $dialog = $mw->Dialog(-text => 'Do you really want to quit?', -bitmap => 'question', -title => 'Quit?', -default_button => 'Yes', -buttons => [qw/Yes No/], ); my $answer = $dialog->Show(); # and display dialog if( lc($answer) =~ /y/i ){ # maybe do some cleaning up and exit; } else { # continue } } # ExitApplication
Vielen Dank an physi, der mir diesen Weg gezeigt hat.

Wie kann man in einem Entry-Feld die Maximalzeichenanzahl beschränken?

Am einfachsten benützt man dafür die Entry-Optionen -validate und -validatecommand, womit man die eingegebenen Werte on-the-fly überprüfen kann, z.B.

my $text = '';
my $entry = $parent->Entry(-textvariable => \$text, -validate => 'all', -validatecommand => \&Validate);
sub Validate { my ($text, $newText, $oldText, $position, $mode) = @_; if (length($text) > 10) { # auf 10 Zeichen beschraenken return 0; # falsch: der letzte Input wird abgelehnt } return 1; # der input wird angenommen } # Validate

Für genauere Erklärung der Parameter: siehe perldoc Tk::Entry und auch das folgene Beispiel (vor allem die Probleme):


Wie kann man in einem Entry-Feld die Maximalzeichenanzahl beschränken?

Indem man den Inhalt von $text und $newText überprüft. Etwas flexibler kann man das folgendermaßen machen:

my $text = "";
my $entry = $mw->EntryCheck($parent, -textvariable => \$text,
                            -maxLength => 10,
					  	       -pattern => qr~[A-Za-z0-9]~, # nur Buchstaben und Ziffern gestatten
						  )
    ->pack(); # oder was auch immer
# ---------------------------------------------------------------------------
# Eine Zwischensubroutine, die einem gerade bei vielen Entry-Feldern viel
# Tipparbeit ersparen kann, fungiert als Zwischenstation zu Entry
sub EntryCheck { 
  my ($parent, %options) = @_;
 
  # Eigene Parameter herausspeichern und aus %options entfernen
  my $maxLength = delete $options{-maxLength};
  my $pattern   = delete $options{-pattern};

  return $parent->Entry(-validate => 'all', 
                        -validatecommand => [ \&Validate, $pattern, $maxLength ],
                        %options, 
} # EntryCheck
# ---------------------------------------------------------------------------
sub Validate {
  my ($pattern, $maxLength, $text, $newText, $oldText, $position, $mode) = @_;

  # laenge ueberpruefen: wenn $maxLength vorhanden und der text laenger ist: FEHLER
  return 0 if defined ($maxLength) and length($text) > $maxLength;

  # wenn das pattern angegeben wurde, ueberpruefe das/die neuhinzugekommene(n) Zeichen
  if (defined $pattern) {
    if (defined($newText)) {
      return 0 unless $newText =~ /^$pattern+$/; # check pattern
	  } # if
  
    # falls $newText leer ist, halten wir uns an den kompletten $text
    else {
  	return 0 unless $text =~ /^$pattern+$/; # check pattern
    } # else
  } # if

  return 1;
} # Validate

Mögliche Probleme:

Ich habe auf CPAN das Modul Tk::EntryCheck gestellt, das genau das macht.


Diverses zu Tk::Photo

Wie kann ich ein Bild in Tk darstellen?

use Tk;
use Tk::JPEG;
use Tk::Photo;

my $imageFile = "myImage.jpg"

my $mw    = MainWindow->new();
my $image = $mw->Photo( -format => 'jpeg', -file => $imageFile ); # oder 'gif'
$mw->Label( -image => $image )->pack();

MainLoop();

Auf die folgende Weise kann man mehrere Bilder nacheinander darstellen

#! /usr/bin/perl
use warnings;
use strict;
use Tk;
use Tk::JPEG;
use Tk::Photo;
use MIME::Base64;

use vars qw($RepeatId);

my @images = glob("*.jpg"); # alle jpg im aktuellen verzeichnis

my $mw = MainWindow->new;
my $image = $mw->Photo(); # leeres Bildobjekt erstellen
my $label = $mw->Label( -image => $image )->pack();

$RepeatId = $mw->repeat( 2000, [ \&ShowImage, $mw, $image, \@images] );

MainLoop();
# ------------------------------------------------------------
sub ReadImageData {
  my( $imageFile ) = @_;

  open( my $IMAGE, "<", $imageFile )
    or die "Error in reading image: $!\n";
  binmode( $IMAGE );
  local $/ = undef; # slurp mode

  # bild einlesen und MIME-encoden
  return MIME::Base64::encode_base64( <$IMAGE> );

  # close( $IMAGE ) ist nicht noetig wegen my $IMAGE
}; # ReadImageData
# ------------------------------------------------------------
sub ShowImage {
  my( $mw, $image, $images ) = @_;

  # wenn keine Bilder mehr zum Anzeigen vorhanden
  $RepeatId->cancel() unless scalar @$images;
  
  my $imageFilename = shift @$images;
  my $imageData = &ReadImageData( $imageFilename );

  # fuelle die Bilddaten in das $image-Objekt
  $image->configure( -format => 'jpeg', -data => $imageData );

  # und aktualisiere das MainWindow
  $mw->update();
} # ShowImage

Habe mal spasshalber die Spiele Käsekästchen und Tk-Mines mit Perl/Tk implementiert. Interessierte können es sich unter Eigene Scripte downloaden.


Letztes Update dieser Seite: Wednesday, 02-Aug-2006 23:12:14 CEST