The Practical Programming in Script Based Graphics User Interface

Menu Menu

Shinji Kono 河野真治


Self Introduction

kono@ie.u-ryukyu.ac.jp

http://rananim.ie.u-ryukyu.ac.jp

Associate Professor of University of the Ryukyus ('96-)

Sony Computer Science Laboratory, Inc. ('89-'95)

Phd. The university of Tokyo, Information Engineering

Research Area

	Temporal Logic, Object Oriented Programming,
	Concurrent Object, Program Verificaiton,
	Network Programming


Script Language

	Shell
	Awk
	Perl
	Ruby
	HTML/SHTML


Advantage of Script Language

	Quick
	Visible
	Network Transparent
	High Portability
	Easy to modify


Disadvantage of Script Language

	Slow
	No hidden source
	High Portability
	Easy to modify


Perl

	Unix Culture Oriented
	No adhoc limitation on data size
	String manipulation
	Dynamic Extendable Array
	Associatibe Array
	Object Orientation


Target of Perl

	CGI (WWW page generator)
	Log processing ( login record, etc. )
	Database Proprocessing of large data
	Data conversion
	GUI application


What is Unix Culture

	Flat text
	Combination of Command Tools
	File descriptor
	stdin, stdout, stderr
	pipe, redirect, socket


Programming Perl

	Similarity
		Sh, Csh, Awk, C


Programming Perl (conditional)

1. if ($i++ <10 ) { print $i; }2. print $i if ($i++ <10 );3. print $i unless ($i++ > 9 );4. open(FD,"<test") || die("error $@\n");5. open(FD,"<test") or die("error $@\n");


Programming Perl (control)

1. while(<>) { $i++; }; print $i;2. print $_ while(<>);3. while(<>) { print $_; last if ($i++ > 10); }4. while(<>) { next if ($i++ < 10); print $_; last if ($i++ > 20); }5. while(<>) { print if (10..20); }6. do { print "$i\n"; } until($i++ < 10) ;

sub gcd0 {
    my ($a,$b) = @_;
    return ($a > $b) ? $a % $b : $b % $a;

}

Ex. complete a program which calculate GCD.


Perl Data Types

Perl's variables are prefixed by one character type description.

Perl Type Anotation
CharacterType
$ascalar (0 dimention value)
@aentire array, vector(1 dimention value)
$a[1]value of an element of the array (scalar)
%aentire associative array
$a{1}value of an element of the associative array
<a>File handle
&aprocedure
\$areference
$$avalue of reference
()list
[]anonymous array
{}anonymous associative array
--boolean if(), while()

reference image


Perl document

perldoc -f builtin-function


Debugging Perl

	perl -de 0


Quick and easy programming

Even if we use script language, we have to program clearly.


Perl programming (pattern)

defined($var)variable $var is defined
$var$var is defined and neither 0 or ""
$a == $bequal numerically
$a != $bnot equal numerically
$a > $bnumerically large
$a eq $bequal literally
$a ne $bnot equal literally
$a =~ /pattern/pattern match
$a =~ s/pattern/replace/substitution

      $var =~ /pattern/;
      $var =~ s/pattern/replace/;

if $var is ommited, defualt variable $_ is used. In while(<>), $_ is automatically set from current file handle.
      while(<>) {
         if (/pattern/) {
              print;
         }
      }

or
      /pattern/ && print while (<>);

is the same as grep command in Unix.


Perl programming (regular expression)

ABCDLiteral string
[a-z]raging from a to z
[a-z]*0 or more repeated range
[a-z]+1 or more repeated range
.arbitrary character except new line
(ABCD)+repeated word pattern
$var$var itself
\Wpredefine word class
\{special character
() parenthsised pattern are stored in $,$2... respectively.
      s/j980(\d\d)/& = $1/;


Perl programming (Reference)

pw071: {1} % perl5 -de 0

Loading DB routines from perl5db.pl version 1 Emacs support available.

Enter h or `h h' for help.

main::(-e:1): 0

  DB&lt;1&gt; @a = (1,2,3,4,5)
  DB&lt;2&gt; p "@a"

1 2 3 4 5
  DB&lt;3&gt; @b = @a
  DB&lt;4&gt; p "@b"

1 2 3 4 5
  DB&lt;5&gt; $a[2]="kono"
  DB&lt;6&gt; p "@a"

1 2 kono 4 5
  DB&lt;7&gt; p "@b"

1 2 3 4 5
  DB&lt;8&gt; $a = [1,2,3,4,5]
  DB&lt;9&gt; p $a

ARRAY(0x805b3b4)
  DB&lt;10&gt; p @$a

12345
  DB&lt;11&gt; p "@$a"

1 2 3 4 5
  DB&lt;12&gt; $$a[1] = "kono"
  DB&lt;13&gt; p "@$a"

1 kono 3 4 5
  DB&lt;14&gt; $b = $a
  DB&lt;15&gt; $$b[2] = "kakazu"
  DB&lt;16&gt; p "@$b"

1 kono kakazu 4 5
  DB&lt;17&gt; p $b

ARRAY(0x805b3b4)
  DB&lt;18&gt; p $b-&gt;[2] = "higa"

higa
  DB&lt;19&gt; p "@$b"

1 kono higa 4 5
  DB&lt;20&gt; $c = {}
  DB&lt;21&gt; $c-&gt;{'kono'} = 'teacher'
  DB&lt;22&gt; $c-&gt;{'higa'} = 'student'
  DB&lt;23&gt; p %$c

higastudentkonoteacher
  DB&lt;24&gt; $c{'kono'} = 1
  DB&lt;25&gt; $c{'higa'} = 2
  DB&lt;26&gt; p keys %c

higakono
  DB&lt;27&gt; p $c

HASH(0x8134cc0)
Understnad reference in examples below.
  DB&lt;28&gt; $d  = \%c
  DB&lt;29&gt; p $d

HASH(0x8152b00)
  DB&lt;30&gt; $d-&gt;{'shimabukuro'} = 'student'
  DB&lt;31&gt; p keys %c

higashimabukurokono
  DB&lt;32&gt; 

Ex. Try following examples.

     $a=[1,2,3,4];
     $a->[5]=3;
     print "@$a, $a->[2]\n";
     $b={};
     $b->{First}='Cat';
     $b->{Second}='Dog';
     $b->{Third}='Pig';
     foreach $key ( keys %$b)  { print "$key is $b->{$key}\n"  }

     @a =  ( 1,2,3,4);
     $refa = \@a;
     $refa->[5]=3;
     print "@$refa, $refa->[2]\n";


The Practice of Programming

Brian W. Kerninghan, Rob Pike 1999, Adison-Wesley.

There are good old books,

	The Elements of Programming Style, 1978
	Software Tools, Adison-Wesley, 1976

(based on fortran))


Performance of languages

  </td><td> 250MHz <br> R10000</td><td> 400MHz <br> Pentinum II</td><td> Lines of <br> source code

c 0.36sec 0.30sec 150
Java 4.9 9.2 105
C++/dequeue 2.6 11.2 70
C++/list 1.7 1.5 70
Awk 2.2 2.1 20
Perl 1.8 1.0 18


Perl Module

Find.pm


Perl Object

Object = Data + Module

package Mammal;

sub new {

       my $type = shift;
       my %params = @_;
       my $self = {};
       $self->{'Name'} = $params{'Name'};
       $self->{'Sex'}  = $params{'Sex'};
       $self->{'Weight'}  = $params{'Weight'};
       $self->{'Color'}  = $params{'Color'};
       bless $self, $type;

}

package Cat;

@ISA = qw( Mammal );

sub new {

       my $type = shift;
       my %params = @_;
       my $self = Mammal->new(@_);
       $self->{'Character'}  = $params{'Character'};
       bless $self, $type;

}

# method

  sub miyao {   my ($self,$arg) = @_;    $self->{Name} = $arg; }
  sub name_print {   my ($self) = @_;    print $self->{Name}; print "\n";}

# Usage

 $a = Cat->new(Name=> Jackey, Sex=>F);
 print $a->{Name};print "\n";
 $a->name_print;


CPAN

The CPAN </a> contains the collected wisdom of the entire Perl community:hundreds of Perl utilities, several books' worth of documentation, and the entire Perl distribution. If it's written in Perl, and it's helpful and free, it's in the CPAN.


Perl/Tk

	Tk library
	Separation of GUI and main program
	Combination


Traffic Singal in Perl/Tk

Write a traffic signal in Perl/Tk.

    package Signal;
    sub new {
	my $type = shift;
	my %params = @_;
	my $self = {};
	    $self-&gt;{'State'}  = $params{'State'};
	$self-&gt;{'State'}  = 
	    defined($params{'State'})? $params{'State'}:'red';
	$self-&gt;{'States'}  = ['green','yellow','red'];
	bless $self;
    }
    sub next {
	my ($self) = shift;
	my $state = $self-&gt;{'State'};
	if($state eq 'red') {
	    $self-&gt;{'State'} = 'green';
	} elsif($state eq 'green') {
	    $self-&gt;{'State'} = 'yellow';
	} else {
	    $self-&gt;{'State'} = 'red';   # Red for all other cases 
	}
	# return $self-&gt;{'State'};
    }
    sub print {
	my ($self) = shift;
	my $state = $self-&gt;{'State'};
	print $state;
    }

This program is executed in this way.

      DB&lt;3&gt; $a = Signal-&gt;new(State=&gt;Red);
      DB&lt;4&gt; $a-&gt;print
      DB&lt;5&gt; $a-&gt;next
      DB&lt;6&gt; $a-&gt;print
    red
      DB&lt;7&gt; $a-&gt;next
      DB&lt;8&gt; $a-&gt;print
    green


Perl/Tk (main)

Perl/Tk では、MainWindow を作り、そこに、いろいろなwidgetをpack していく。
	my $main = MainWindow-&gt;new();

とすれば、MainWindowができる。MainWindowのインスタンスとして、いろいろなものを使うことができる。
Label文字を印として置く
Text編集用のテキスト
Entry入力カラム
Canvas図形表示
Frameいくつかのwidgetをまとめる



Canvas とタグ

Canvasには以下のような図を書くことができる。
oval楕円
rectangle
line
polygon多角形
bitmapイメージ
textテキスト
これらは、CanvasにタグやIDで指定することによって移動したり変形したりすることができる。
$canv->move($ball, $deltax, $deltay);移動
$canvas->itemconfigure($view,-fill=>'black');色などの変更
$canvas->delete($view);削除
これらに関しては man canvas でもだいたいのことを知ることができる。


信号機を表示する<a > Perl/Tkのプログラム</a>は以下のようになる。

    package SignalView;
    use Tk;
    sub new {
	my $type = shift;
	my %params = @_;
	my $self = {};
	my $signal = Signal-&gt;new(%params);
	my $main = $params{-main};
	my $canvas;
	my $states = $signal-&gt;{'States'};
	my %views = ();
	if(! defined( $main)) { $main = MainWindow-&gt;new(%params); }
	$canvas = $main-&gt;Canvas(-width=&gt;50,-height=&gt;150);
	$x = 5; $y = 5;
	$r = 40;
	for $state ( @$states ) {
	    $views{$state} = 
		$canvas-&gt;create('oval', $x, $y, $x+$r, $y+$r, 
		    -width =&gt; 1, -outline =&gt; 'black', -fill =&gt; 'black');
	    $y += 50;
	}
	$canvas-&gt;pack();
	$self-&gt;{'MainWindow'}  = $main;
	$self-&gt;{'Canvas'}  = $canvas;
	$self-&gt;{'Views'}  = \%views;
	$self-&gt;{'Signal'}  = $signal;
	bless $self;
    }
    sub next {
	my ($self) = shift;
	my $state = $self-&gt;{'Signal'}-&gt;{'State'};
	my $view = $self-&gt;{'Views'}-&gt;{$state};
	my $canvas = $self-&gt;{'Canvas'};
	$canvas-&gt;itemconfigure($view,-fill=&gt;'black');
	$state = $self-&gt;{'Signal'}-&gt;next();
	$view = $self-&gt;{'Views'}-&gt;{$state};
	$canvas-&gt;itemconfigure($view,-fill=&gt;$state);
    }
    sub update {
	my ($self) = shift;
	$self-&gt;{'MainWindow'}-&gt;update();
    }
    package Main;
    $signal = SignalView-&gt;new();
    $signal-&gt;update();
    while($i++&lt;100) {
	$signal-&gt;next();
	$signal-&gt;{'Signal'}-&gt;print(); print "\n";
	$signal-&gt;update();
	sleep(1);
    }

この方法では、信号は自動的に点滅するという感じではない。そのためには、after という機能を使うことができる。

    package MainWindow;
    sub Signal {
	my ($self) = shift;
	return SignalView-&gt;new(-main=&gt;$self);
    }
    package SignalView;
    sub new {
	my $type = shift;
	my %params = @_;
	my $self = {};
	my $signal = Signal-&gt;new(%params);
	my $main = $params{-main};
	my $canvas;
	my $states = $signal-&gt;{'States'};
	my %views = ();
	$self-&gt;{'Interval'} = 500;
	$canvas = $main-&gt;Canvas(-width=&gt;50,-height=&gt;150);
	$x = 5; $y = 5;
	$r = 40;
	for $state ( @$states ) {
	    $views{$state} = 
		$canvas-&gt;create('oval', $x, $y, $x+$r, $y+$r, 
		    -width =&gt; 1, -outline =&gt; 'black', -fill =&gt; 'black');
	    $y += 50;
	}
	$canvas-&gt;pack(-side=&gt;left);
	$self-&gt;{'MainWindow'}  = $main;
	$self-&gt;{'Canvas'}  = $canvas;
	$self-&gt;{'Views'}  = \%views;
	$self-&gt;{'Signal'}  = $signal;
	bless $self;
    }
    sub next {
	my ($self) = shift;
	my $state = $self-&gt;{'Signal'}-&gt;{'State'};
	my $view = $self-&gt;{'Views'}-&gt;{$state};
	my $canvas = $self-&gt;{'Canvas'};
	$canvas-&gt;itemconfigure($view,-fill=&gt;'black');
	$state = $self-&gt;{'Signal'}-&gt;next();
	$view = $self-&gt;{'Views'}-&gt;{$state};
	$canvas-&gt;itemconfigure($view,-fill=&gt;$state);
    }
    sub update {
	my ($self) = shift;
	$self-&gt;{'MainWindow'}-&gt;update();
    }
    sub run {
	my ($self) = shift;
	my %params = @_;
	my $main=$self-&gt;{'MainWindow'};
	if(defined($params{'Interval'})) {
	    $self-&gt;{'Interval'} = $params{'Interval'};
	}
	if(! $self-&gt;{'Running'})  {
	    $self-&gt;{'Running'} = 1;
	    $main-&gt;after($self-&gt;{'Interval'},sub {$self-&gt;running()});
	}
    }
    sub running {
	my ($self) = shift;
	my $interval = $self-&gt;{'Interval'};
	if($self-&gt;{'Running'}) {
	    $self-&gt;next();
	    $self-&gt;update();
	    $self-&gt;{'MainWindow'}-&gt;after($interval,sub {$self-&gt;running()});
	} 
    }
    sub stop {
	my ($self) = shift;
	$self-&gt;{'Running'} = 0;
    }
    package Main;
    use Tk;
    $main = MainWindow-&gt;new();
    $signal = $main-&gt;Signal();
    $signal-&gt;run();
    &amp;MainLoop();



Call Back と Controller

この信号をさらに外から制御するには、controller をViewに付加する。

ボタンからの情報を処理するにはCall Backを使う。Call Back では、Call Back する先を、my 変数により保持する。これをClosure という。オブジェクトを使っても同じことが実現できるが、Closureの方が構文的には軽い。


    package SingalView;
    sub controller {
	my ($self) = shift;
	my $main=$self-&gt;{'MainWindow'};
	# my $c= $main-&gt;Toplevel();
	my $c= $main-&gt;Frame();
	my $int= $c-&gt;Frame();
	my $int_entry = $int-&gt;Entry(-relief =&gt; 'sunken',-width=&gt;5);
	my $int_label= $int-&gt;Label(-text=&gt;"Interval:");
	my $quit = $c-&gt;Button( 
	    -text =&gt; 'Quit', -width =&gt; 10, -command =&gt; sub {$main-&gt;destroy});
	my $run = $c-&gt;Button( 
	    -text =&gt; 'Run', -width =&gt; 10, -command =&gt; 
		sub { $self-&gt;run(Interval=&gt;($int_entry-&gt;get())) }
	    );
	my $stop = $c-&gt;Button( 
	    -text =&gt; 'Stop', -width =&gt; 10, -command =&gt; sub {$self-&gt;stop});
	$int-&gt;pack(-side =&gt; 'top', -fill =&gt; 'x');
	$int_entry-&gt;pack(-side =&gt; 'right');
	$int_label-&gt;pack(-side =&gt; 'left');
	$c-&gt;pack( -side =&gt; 'right', -expand =&gt; 'no', -pady =&gt; 2);
	$int-&gt;pack(-side =&gt; 'top', -expand =&gt; 'no', -pady =&gt; 2);
	$run-&gt;pack( -side =&gt; 'top', -expand =&gt; 'no', -pady =&gt; 2);
	$stop-&gt;pack(-side =&gt; 'top', -expand =&gt; 'no', -pady =&gt; 2);
	$quit-&gt;pack(-side =&gt; 'top', -expand =&gt; 'no', -pady =&gt; 2);
	# set default value
	$int_entry-&gt;insert(0,$self-&gt;{'Interval'});
	$self-&gt;{'Controller'}=$c;
	$self-&gt;update();
    }
    # end


Shinji Kono 河野真治 / Mon Oct 4 08:16:09 1999